Fix Blenderplayer (c)
[blender.git] / source / blender / modifiers / intern / MOD_surfacedeform.c
1 #include "DNA_object_types.h"
2 #include "DNA_scene_types.h"
3
4 #include "BLI_alloca.h"
5 #include "BLI_math.h"
6 #include "BLI_math_geom.h"
7 #include "BLI_task.h"
8
9 #include "BKE_cdderivedmesh.h"
10 #include "BKE_editmesh.h"
11 #include "BKE_library_query.h"
12 #include "BKE_modifier.h"
13
14 #include "MEM_guardedalloc.h"
15
16 #include "MOD_util.h"
17
18 typedef struct SDefAdjacency {
19         struct SDefAdjacency *next;
20         unsigned int index;
21 } SDefAdjacency;
22
23 typedef struct SDefAdjacencyArray {
24         SDefAdjacency *first;
25         unsigned int num; /* Careful, this is twice the number of polygons (avoids an extra loop) */
26 } SDefAdjacencyArray;
27
28 typedef struct SDefEdgePolys {
29         unsigned int polys[2], num;
30 } SDefEdgePolys;
31
32 typedef struct SDefBindCalcData {
33         BVHTreeFromMesh * const treeData;
34         const SDefAdjacencyArray * const vert_edges;
35         const SDefEdgePolys * const edge_polys;
36         SDefVert * const bind_verts;
37         const MLoopTri * const looptri;
38         const MPoly * const mpoly;
39         const MEdge * const medge;
40         const MLoop * const mloop;
41         float (* const targetCos)[3];
42         float (* const vertexCos)[3];
43         float imat[4][4];
44         const float falloff;
45         int success;
46 } SDefBindCalcData;
47
48 typedef struct SDefBindPoly {
49         float (*coords)[3];
50         float (*coords_v2)[2];
51         float point_v2[2];
52         float weight_angular;
53         float weight_dist_proj;
54         float weight_dist;
55         float weight;
56         float scales[2];
57         float centroid[3];
58         float centroid_v2[2];
59         float normal[3];
60         float cent_edgemid_vecs_v2[2][2];
61         float edgemid_angle;
62         float point_edgemid_angles[2];
63         float corner_edgemid_angles[2];
64         float dominant_angle_weight;
65         unsigned int index;
66         unsigned int numverts;
67         unsigned int loopstart;
68         unsigned int edge_inds[2];
69         unsigned int edge_vert_inds[2];
70         unsigned int corner_ind;
71         unsigned int dominant_edge;
72         bool inside;
73 } SDefBindPoly;
74
75 typedef struct SDefBindWeightData {
76         SDefBindPoly *bind_polys;
77         unsigned int numpoly;
78         unsigned int numbinds;
79 } SDefBindWeightData;
80
81 typedef struct SDefDeformData {
82         const SDefVert * const bind_verts;
83         float (* const targetCos)[3];
84         float (* const vertexCos)[3];
85 } SDefDeformData;
86
87 /* Bind result values */
88 enum {
89         MOD_SDEF_BIND_RESULT_SUCCESS = 1,
90         MOD_SDEF_BIND_RESULT_GENERIC_ERR = 0,
91         MOD_SDEF_BIND_RESULT_MEM_ERR = -1,
92         MOD_SDEF_BIND_RESULT_NONMANY_ERR = -2,
93         MOD_SDEF_BIND_RESULT_CONCAVE_ERR = -3,
94         MOD_SDEF_BIND_RESULT_OVERLAP_ERR = -4,
95 };
96
97 /* Infinite weight flags */
98 enum {
99         MOD_SDEF_INFINITE_WEIGHT_ANGULAR = (1 << 0),
100         MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ = (1 << 1),
101         MOD_SDEF_INFINITE_WEIGHT_DIST = (1 << 2),
102 };
103
104 static void initData(ModifierData *md)
105 {
106         SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
107         smd->target = NULL;
108         smd->verts = NULL;
109         smd->flags = 0;
110         smd->falloff = 4.0f;
111 }
112
113 static void freeData(ModifierData *md)
114 {
115         SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
116
117         if (smd->verts) {
118                 for (int i = 0; i < smd->numverts; i++) {
119                         if (smd->verts[i].binds) {
120                                 for (int j = 0; j < smd->verts[i].numbinds; j++) {
121                                         MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds);
122                                         MEM_SAFE_FREE(smd->verts[i].binds[j].vert_weights);
123                                 }
124
125                                 MEM_freeN(smd->verts[i].binds);
126                         }
127                 }
128
129                 MEM_freeN(smd->verts);
130                 smd->verts = NULL;
131         }
132 }
133
134 static void copyData(ModifierData *md, ModifierData *target)
135 {
136         SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
137         SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target;
138
139         *tsmd = *smd;
140
141         if (smd->verts) {
142                 tsmd->verts = MEM_dupallocN(smd->verts);
143
144                 for (int i = 0; i < smd->numverts; i++) {
145                         if (smd->verts[i].binds) {
146                                 tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds);
147
148                                 for (int j = 0; j < smd->verts[i].numbinds; j++) {
149                                         if (smd->verts[i].binds[j].vert_inds) {
150                                                 tsmd->verts[i].binds[j].vert_inds = MEM_dupallocN(smd->verts[i].binds[j].vert_inds);
151                                         }
152
153                                         if (smd->verts[i].binds[j].vert_weights) {
154                                                 tsmd->verts[i].binds[j].vert_weights = MEM_dupallocN(smd->verts[i].binds[j].vert_weights);
155                                         }
156                                 }
157                         }
158                 }
159         }
160 }
161
162 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
163 {
164         SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
165
166         walk(userData, ob, &smd->target, IDWALK_NOP);
167 }
168
169 static void updateDepsgraph(ModifierData *md,
170                             struct Main *UNUSED(bmain),
171                             struct Scene *UNUSED(scene),
172                             Object *UNUSED(ob),
173                             struct DepsNodeHandle *node)
174 {
175         SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
176         if (smd->target != NULL) {
177                 DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "Surface Deform Modifier");
178         }
179 }
180
181 static void freeAdjacencyMap(SDefAdjacencyArray * const vert_edges, SDefAdjacency * const adj_ref, SDefEdgePolys * const edge_polys)
182 {
183         MEM_freeN(edge_polys);
184
185         MEM_freeN(adj_ref);
186
187         MEM_freeN(vert_edges);
188 }
189
190 static int buildAdjacencyMap(const MPoly *poly, const MEdge *edge, const MLoop * const mloop, const unsigned int numpoly, const unsigned int numedges,
191                               SDefAdjacencyArray * const vert_edges, SDefAdjacency *adj, SDefEdgePolys * const edge_polys)
192 {
193         const MLoop *loop;
194
195         /* Fing polygons adjacent to edges */
196         for (int i = 0; i < numpoly; i++, poly++) {
197                 loop = &mloop[poly->loopstart];
198
199                 for (int j = 0; j < poly->totloop; j++, loop++) {
200                         if (edge_polys[loop->e].num == 0) {
201                                 edge_polys[loop->e].polys[0] = i;
202                                 edge_polys[loop->e].polys[1] = -1;
203                                 edge_polys[loop->e].num++;
204                         }
205                         else if (edge_polys[loop->e].num == 1) {
206                                 edge_polys[loop->e].polys[1] = i;
207                                 edge_polys[loop->e].num++;
208                         }
209                         else {
210                                 return MOD_SDEF_BIND_RESULT_NONMANY_ERR;
211                         }
212                 }
213         }
214
215         /* Find edges adjacent to vertices */
216         for (int i = 0; i < numedges; i++, edge++) {
217                 adj->next = vert_edges[edge->v1].first;
218                 adj->index = i;
219                 vert_edges[edge->v1].first = adj;
220                 vert_edges[edge->v1].num += edge_polys[i].num;
221                 adj++;
222
223                 adj->next = vert_edges[edge->v2].first;
224                 adj->index = i;
225                 vert_edges[edge->v2].first = adj;
226                 vert_edges[edge->v2].num += edge_polys[i].num;
227                 adj++;
228         }
229
230         return MOD_SDEF_BIND_RESULT_SUCCESS;
231 }
232
233 BLI_INLINE void sortPolyVertsEdge(unsigned int *indices, const MLoop * const mloop, const unsigned int edge, const unsigned int num)
234 {
235         bool found = false;
236
237         for (int i = 0; i < num; i++) {
238                 if (mloop[i].e == edge) {
239                         found = true;
240                 }
241                 if (found) {
242                         *indices = mloop[i].v;
243                         indices++;
244                 }
245         }
246
247         /* Fill in remaining vertex indices that occur before the edge */
248         for (int i = 0; mloop[i].e != edge; i++) {
249                 *indices = mloop[i].v;
250                 indices++;
251         }
252 }
253
254 BLI_INLINE void sortPolyVertsTri(unsigned int *indices, const MLoop * const mloop, const unsigned int loopstart, const unsigned int num)
255 {
256         for (int i = loopstart; i < num; i++) {
257                 *indices = mloop[i].v;
258                 indices++;
259         }
260
261         for (int i = 0; i < loopstart; i++) {
262                 *indices = mloop[i].v;
263                 indices++;
264         }
265 }
266
267 BLI_INLINE unsigned int nearestVert(SDefBindCalcData * const data, const float point_co[3])
268 {
269         BVHTreeNearest nearest = {.dist_sq = FLT_MAX, .index = -1};
270         const MPoly *poly;
271         const MEdge *edge;
272         const MLoop *loop;
273         float t_point[3];
274         float max_dist = FLT_MAX;
275         float dist;
276         unsigned int index = 0;
277
278         mul_v3_m4v3(t_point, data->imat, point_co);
279
280         BLI_bvhtree_find_nearest(data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData);
281
282         poly = &data->mpoly[data->looptri[nearest.index].poly];
283         loop = &data->mloop[poly->loopstart];
284
285         for (int i = 0; i < poly->totloop; i++, loop++) {
286                 edge = &data->medge[loop->e];
287                 dist = dist_squared_to_line_segment_v3(point_co, data->targetCos[edge->v1], data->targetCos[edge->v2]);
288
289                 if (dist < max_dist) {
290                         max_dist = dist;
291                         index = loop->e;
292                 }
293         }
294
295         edge = &data->medge[index];
296         if (len_squared_v3v3(point_co, data->targetCos[edge->v1]) < len_squared_v3v3(point_co, data->targetCos[edge->v2])) {
297                 return edge->v1;
298         }
299         else {
300                 return edge->v2;
301         }
302 }
303
304 BLI_INLINE int isPolyValid(const float coords[][2], const unsigned int nr)
305 {
306         float prev_co[2];
307         float curr_vec[2], prev_vec[2];
308
309         if (!is_poly_convex_v2(coords, nr)) {
310                 return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
311         }
312
313         copy_v2_v2(prev_co, coords[nr - 1]);
314         sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]);
315
316         for (int i = 0; i < nr; i++) {
317                 sub_v2_v2v2(curr_vec, coords[i], prev_co);
318
319                 if (len_squared_v2(curr_vec) < FLT_EPSILON) {
320                         return MOD_SDEF_BIND_RESULT_OVERLAP_ERR;
321                 }
322
323                 if (1.0f - dot_v2v2(prev_vec, curr_vec) < FLT_EPSILON) {
324                         return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
325                 }
326
327                 copy_v2_v2(prev_co, coords[i]);
328                 copy_v2_v2(prev_vec, curr_vec);
329         }
330
331         return MOD_SDEF_BIND_RESULT_SUCCESS;
332 }
333
334 static void freeBindData(SDefBindWeightData * const bwdata)
335 {
336         SDefBindPoly *bpoly = bwdata->bind_polys;
337
338         if (bwdata->bind_polys) {
339                 for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
340                         MEM_SAFE_FREE(bpoly->coords);
341                         MEM_SAFE_FREE(bpoly->coords_v2);
342                 }
343
344                 MEM_freeN(bwdata->bind_polys);
345         }
346
347         MEM_freeN(bwdata);
348 }
349
350 BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle)
351 {
352         float weight;
353
354         weight = point_angle;
355         weight /= edgemid_angle;
356         weight *= M_PI_2;
357
358         return sinf(weight);
359 }
360
361 BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData * const data, const float point_co[3])
362 {
363         const unsigned int nearest = nearestVert(data, point_co);
364         const SDefAdjacency * const vert_edges = data->vert_edges[nearest].first;
365         const SDefEdgePolys * const edge_polys = data->edge_polys;
366
367         const SDefAdjacency *vedge;
368         const MPoly *poly;
369         const MLoop *loop;
370
371         SDefBindWeightData *bwdata;
372         SDefBindPoly *bpoly;
373
374         float world[3] = {0.0f, 0.0f, 1.0f};
375         float avg_point_dist = 0.0f;
376         float tot_weight = 0.0f;
377         int inf_weight_flags = 0;
378
379         bwdata = MEM_callocN(sizeof(*bwdata), "SDefBindWeightData");
380         if (bwdata == NULL) {
381                 data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
382                 return NULL;
383         }
384
385         bwdata->numpoly = data->vert_edges[nearest].num / 2;
386
387         bpoly = MEM_callocN(sizeof(*bpoly) * bwdata->numpoly, "SDefBindPoly");
388         if (bpoly == NULL) {
389                 freeBindData(bwdata);
390                 data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
391                 return NULL;
392         }
393
394         bwdata->bind_polys = bpoly;
395
396         /* Loop over all adjacent edges, and build the SDefBindPoly data for each poly adjacent to those */
397         for (vedge = vert_edges; vedge; vedge = vedge->next) {
398                 unsigned int edge_ind = vedge->index;
399
400                 for (int i = 0; i < edge_polys[edge_ind].num; i++) {
401                         {
402                                 bpoly = bwdata->bind_polys;
403
404                                 for (int j = 0; j < bwdata->numpoly; bpoly++, j++) {
405                                         /* If coords isn't allocated, we have reached the first uninitialized bpoly */
406                                         if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) {
407                                                 break;
408                                         }
409                                 }
410                         }
411
412                         /* Check if poly was already created by another edge or still has to be initialized */
413                         if (!bpoly->coords) {
414                                 float angle;
415                                 float axis[3];
416                                 float tmp_vec_v2[2];
417                                 int is_poly_valid;
418
419                                 bpoly->index = edge_polys[edge_ind].polys[i];
420                                 bpoly->coords = NULL;
421                                 bpoly->coords_v2 = NULL;
422
423                                 /* Copy poly data */
424                                 poly = &data->mpoly[bpoly->index];
425                                 loop = &data->mloop[poly->loopstart];
426
427                                 bpoly->numverts = poly->totloop;
428                                 bpoly->loopstart = poly->loopstart;
429
430                                 bpoly->coords = MEM_mallocN(sizeof(*bpoly->coords) * poly->totloop, "SDefBindPolyCoords");
431                                 if (bpoly->coords == NULL) {
432                                         freeBindData(bwdata);
433                                         data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
434                                         return NULL;
435                                 }
436
437                                 bpoly->coords_v2 = MEM_mallocN(sizeof(*bpoly->coords_v2) * poly->totloop, "SDefBindPolyCoords_v2");
438                                 if (bpoly->coords_v2 == NULL) {
439                                         freeBindData(bwdata);
440                                         data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
441                                         return NULL;
442                                 }
443
444                                 for (int j = 0; j < poly->totloop; j++, loop++) {
445                                         copy_v3_v3(bpoly->coords[j], data->targetCos[loop->v]);
446
447                                         /* Find corner and edge indices within poly loop array */
448                                         if (loop->v == nearest) {
449                                                 bpoly->corner_ind = j;
450                                                 bpoly->edge_vert_inds[0] = (j == 0) ? (poly->totloop - 1) : (j - 1);
451                                                 bpoly->edge_vert_inds[1] = (j == poly->totloop - 1) ? (0) : (j + 1);
452
453                                                 bpoly->edge_inds[0] = data->mloop[poly->loopstart + bpoly->edge_vert_inds[0]].e;
454                                                 bpoly->edge_inds[1] = loop->e;
455                                         }
456                                 }
457
458                                 /* Compute poly's parametric data */
459                                 mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly->totloop);
460                                 normal_poly_v3(bpoly->normal, bpoly->coords, poly->totloop);
461
462                                 /* Compute poly skew angle and axis */
463                                 angle = angle_normalized_v3v3(bpoly->normal, world);
464
465                                 cross_v3_v3v3(axis, bpoly->normal, world);
466                                 normalize_v3(axis);
467
468                                 /* Map coords onto 2d normal plane */
469                                 map_to_plane_axis_angle_v2_v3v3fl(bpoly->point_v2, point_co, axis, angle);
470
471                                 zero_v2(bpoly->centroid_v2);
472                                 for (int j = 0; j < poly->totloop; j++) {
473                                         map_to_plane_axis_angle_v2_v3v3fl(bpoly->coords_v2[j], bpoly->coords[j], axis, angle);
474                                         madd_v2_v2fl(bpoly->centroid_v2, bpoly->coords_v2[j], 1.0f / poly->totloop);
475                                 }
476
477                                 is_poly_valid = isPolyValid(bpoly->coords_v2, poly->totloop);
478
479                                 if (is_poly_valid != MOD_SDEF_BIND_RESULT_SUCCESS) {
480                                         freeBindData(bwdata);
481                                         data->success = is_poly_valid;
482                                         return NULL;
483                                 }
484
485                                 bpoly->inside = isect_point_poly_v2(bpoly->point_v2, bpoly->coords_v2, poly->totloop, false);
486
487                                 /* Initialize weight components */
488                                 bpoly->weight_angular = 1.0f;
489                                 bpoly->weight_dist_proj = len_v2v2(bpoly->centroid_v2, bpoly->point_v2);
490                                 bpoly->weight_dist = len_v3v3(bpoly->centroid, point_co);
491
492                                 avg_point_dist += bpoly->weight_dist;
493
494                                 /* Compute centroid to mid-edge vectors */
495                                 mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0],
496                                             bpoly->coords_v2[bpoly->edge_vert_inds[0]],
497                                             bpoly->coords_v2[bpoly->corner_ind]);
498
499                                 mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1],
500                                             bpoly->coords_v2[bpoly->edge_vert_inds[1]],
501                                             bpoly->coords_v2[bpoly->corner_ind]);
502
503                                 sub_v2_v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->centroid_v2);
504                                 sub_v2_v2(bpoly->cent_edgemid_vecs_v2[1], bpoly->centroid_v2);
505
506                                 /* Compute poly scales with respect to mid-edges, and normalize the vectors */
507                                 bpoly->scales[0] = normalize_v2(bpoly->cent_edgemid_vecs_v2[0]);
508                                 bpoly->scales[1] = normalize_v2(bpoly->cent_edgemid_vecs_v2[1]);
509
510                                 /* Compute the required polygon angles */
511                                 bpoly->edgemid_angle = angle_normalized_v2v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->cent_edgemid_vecs_v2[1]);
512
513                                 sub_v2_v2v2(tmp_vec_v2, bpoly->coords_v2[bpoly->corner_ind], bpoly->centroid_v2);
514                                 normalize_v2(tmp_vec_v2);
515
516                                 bpoly->corner_edgemid_angles[0] = angle_normalized_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[0]);
517                                 bpoly->corner_edgemid_angles[1] = angle_normalized_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[1]);
518
519                                 /* Check for inifnite weights, and compute angular data otherwise */
520                                 if (bpoly->weight_dist < FLT_EPSILON) {
521                                         inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
522                                         inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
523                                 }
524                                 else if (bpoly->weight_dist_proj < FLT_EPSILON) {
525                                         inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
526                                 }
527                                 else {
528                                         float cent_point_vec[2];
529
530                                         sub_v2_v2v2(cent_point_vec, bpoly->point_v2, bpoly->centroid_v2);
531                                         normalize_v2(cent_point_vec);
532
533                                         bpoly->point_edgemid_angles[0] = angle_normalized_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[0]);
534                                         bpoly->point_edgemid_angles[1] = angle_normalized_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[1]);
535                                 }
536                         }
537                 }
538         }
539
540         avg_point_dist /= bwdata->numpoly;
541
542         /* If weights 1 and 2 are not infinite, loop over all adjacent edges again,
543          * and build adjacency dependent angle data (depends on all polygons having been computed) */
544         if (!inf_weight_flags) {
545                 for (vedge = vert_edges; vedge; vedge = vedge->next) {
546                         SDefBindPoly *bpolys[2];
547                         const SDefEdgePolys *epolys;
548                         float ang_weights[2];
549                         unsigned int edge_ind = vedge->index;
550                         unsigned int edge_on_poly[2];
551
552                         epolys = &edge_polys[edge_ind];
553
554                         /* Find bind polys corresponding to the edge's adjacent polys */
555                         bpoly = bwdata->bind_polys;
556
557                         for (int i = 0, j = 0; (i < bwdata->numpoly) && (j < epolys->num); bpoly++, i++) {
558                                 if (ELEM(bpoly->index, epolys->polys[0], epolys->polys[1])) {
559                                         bpolys[j] = bpoly;
560
561                                         if (bpoly->edge_inds[0] == edge_ind) {
562                                                 edge_on_poly[j] = 0;
563                                         }
564                                         else {
565                                                 edge_on_poly[j] = 1;
566                                         }
567
568                                         j++;
569                                 }
570                         }
571
572                         /* Compute angular weight component */
573                         if (epolys->num == 1) {
574                                 ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], bpolys[0]->edgemid_angle);
575                                 bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0];
576                         }
577                         else if (epolys->num == 2) {
578                                 ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], bpolys[0]->edgemid_angle);
579                                 ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]], bpolys[1]->edgemid_angle);
580
581                                 bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1];
582                                 bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1];
583                         }
584                 }
585         }
586
587         /* Compute scalings and falloff.
588          * Scale all weights if no infinite weight is found,
589          * scale only unprojected weight if projected weight is infinite,
590          * scale none if both are infinite. */
591         if (!inf_weight_flags) {
592                 bpoly = bwdata->bind_polys;
593
594                 for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
595                         float corner_angle_weights[2];
596                         float scale_weight, sqr, inv_sqr;
597
598                         corner_angle_weights[0] = bpoly->point_edgemid_angles[0] / bpoly->corner_edgemid_angles[0];
599                         corner_angle_weights[1] = bpoly->point_edgemid_angles[1] / bpoly->corner_edgemid_angles[1];
600
601                         if (isnan(corner_angle_weights[0]) || isnan(corner_angle_weights[1])) {
602                                 freeBindData(bwdata);
603                                 data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
604                                 return NULL;
605                         }
606
607                         /* Find which edge the point is closer to */
608                         if (corner_angle_weights[0] < corner_angle_weights[1]) {
609                                 bpoly->dominant_edge = 0;
610                                 bpoly->dominant_angle_weight = corner_angle_weights[0];
611                         }
612                         else {
613                                 bpoly->dominant_edge = 1;
614                                 bpoly->dominant_angle_weight = corner_angle_weights[1];
615                         }
616
617                         bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2);
618
619                         /* Compute quadratic angular scale interpolation weight */
620                         scale_weight = bpoly->point_edgemid_angles[bpoly->dominant_edge] / bpoly->edgemid_angle;
621                         scale_weight /= scale_weight + (bpoly->point_edgemid_angles[!bpoly->dominant_edge] / bpoly->edgemid_angle);
622
623                         sqr = scale_weight * scale_weight;
624                         inv_sqr = 1.0f - scale_weight;
625                         inv_sqr *= inv_sqr;
626                         scale_weight = sqr / (sqr + inv_sqr);
627
628                         /* Compute interpolated scale (no longer need the individual scales,
629                          * so simply storing the result over the scale in index zero) */
630                         bpoly->scales[0] = bpoly->scales[bpoly->dominant_edge] * (1.0f - scale_weight) +
631                                            bpoly->scales[!bpoly->dominant_edge] * scale_weight;
632
633                         /* Scale the point distance weights, and introduce falloff */
634                         bpoly->weight_dist_proj /= bpoly->scales[0];
635                         bpoly->weight_dist_proj = powf(bpoly->weight_dist_proj, data->falloff);
636
637                         bpoly->weight_dist /= avg_point_dist;
638                         bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
639
640                         /* Re-check for infinite weights, now that all scalings and interpolations are computed */
641                         if (bpoly->weight_dist < FLT_EPSILON) {
642                                 inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
643                                 inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
644                         }
645                         else if (bpoly->weight_dist_proj < FLT_EPSILON) {
646                                 inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
647                         }
648                         else if (bpoly->weight_angular < FLT_EPSILON) {
649                                 inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_ANGULAR;
650                         }
651                 }
652         }
653         else if (!(inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST)) {
654                 bpoly = bwdata->bind_polys;
655
656                 for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
657                         /* Scale the point distance weight by average point distance, and introduce falloff */
658                         bpoly->weight_dist /= avg_point_dist;
659                         bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
660
661                         /* Re-check for infinite weights, now that all scalings and interpolations are computed */
662                         if (bpoly->weight_dist < FLT_EPSILON) {
663                                 inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
664                         }
665                 }
666         }
667
668         /* Final loop, to compute actual weights */
669         bpoly = bwdata->bind_polys;
670
671         for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
672                 /* Weight computation from components */
673                 if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST) {
674                         bpoly->weight = bpoly->weight_dist < FLT_EPSILON ? 1.0f : 0.0f;
675                 }
676                 else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ) {
677                         bpoly->weight = bpoly->weight_dist_proj < FLT_EPSILON ?
678                                         1.0f / bpoly->weight_dist : 0.0f;
679                 }
680                 else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_ANGULAR) {
681                         bpoly->weight = bpoly->weight_angular < FLT_EPSILON ?
682                                         1.0f / bpoly->weight_dist_proj / bpoly->weight_dist : 0.0f;
683                 }
684                 else {
685                         bpoly->weight = 1.0f / bpoly->weight_angular /
686                                                bpoly->weight_dist_proj /
687                                                bpoly->weight_dist;
688                 }
689
690                 tot_weight += bpoly->weight;
691         }
692
693         bpoly = bwdata->bind_polys;
694
695         for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
696                 bpoly->weight /= tot_weight;
697
698                 /* Evaluate if this poly is relevant to bind */
699                 /* Even though the weights should add up to 1.0,
700                  * the losses of weights smaller than epsilon here
701                  * should be negligible... */
702                 if (bpoly->weight >= FLT_EPSILON) {
703                         if (bpoly->inside) {
704                                 bwdata->numbinds += 1;
705                         }
706                         else {
707                                 if (bpoly->dominant_angle_weight < FLT_EPSILON || 1.0f - bpoly->dominant_angle_weight < FLT_EPSILON) {
708                                         bwdata->numbinds += 1;
709                                 }
710                                 else {
711                                         bwdata->numbinds += 2;
712                                 }
713                         }
714                 }
715         }
716
717         return bwdata;
718 }
719
720 BLI_INLINE float computeNormalDisplacement(const float point_co[3], const float point_co_proj[3], const float normal[3])
721 {
722         float disp_vec[3];
723         float normal_dist;
724
725         sub_v3_v3v3(disp_vec, point_co, point_co_proj);
726         normal_dist = len_v3(disp_vec);
727
728         if (dot_v3v3(disp_vec, normal) < 0) {
729                 normal_dist *= -1;
730         }
731
732         return normal_dist;
733 }
734
735 static void bindVert(void *userdata, void *UNUSED(userdata_chunk), const int index, const int UNUSED(threadid))
736 {
737         SDefBindCalcData * const data = (SDefBindCalcData *)userdata;
738         float point_co[3];
739         float point_co_proj[3];
740
741         SDefBindWeightData *bwdata;
742         SDefVert *sdvert = data->bind_verts + index;
743         SDefBindPoly *bpoly;
744         SDefBind *sdbind;
745
746         if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) {
747                 sdvert->binds = NULL;
748                 sdvert->numbinds = 0;
749                 return;
750         }
751
752         copy_v3_v3(point_co, data->vertexCos[index]);
753         bwdata = computeBindWeights(data, point_co);
754
755         if (bwdata == NULL) {
756                 sdvert->binds = NULL;
757                 sdvert->numbinds = 0;
758                 return;
759         }
760
761         sdvert->binds = MEM_callocN(sizeof(*sdvert->binds) * bwdata->numbinds, "SDefVertBindData");
762         if (sdvert->binds == NULL) {
763                 data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
764                 sdvert->numbinds = 0;
765                 return;
766         }
767
768         sdvert->numbinds = bwdata->numbinds;
769
770         sdbind = sdvert->binds;
771
772         bpoly = bwdata->bind_polys;
773
774         for (int i = 0; i < bwdata->numbinds; bpoly++) {
775                 if (bpoly->weight >= FLT_EPSILON) {
776                         if (bpoly->inside) {
777                                 const MLoop *loop = &data->mloop[bpoly->loopstart];
778
779                                 sdbind->influence = bpoly->weight;
780                                 sdbind->numverts = bpoly->numverts;
781
782                                 sdbind->mode = MOD_SDEF_MODE_NGON;
783                                 sdbind->vert_weights = MEM_mallocN(sizeof(*sdbind->vert_weights) * bpoly->numverts, "SDefNgonVertWeights");
784                                 if (sdbind->vert_weights == NULL) {
785                                         data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
786                                         return;
787                                 }
788
789                                 sdbind->vert_inds = MEM_mallocN(sizeof(*sdbind->vert_inds) * bpoly->numverts, "SDefNgonVertInds");
790                                 if (sdbind->vert_inds == NULL) {
791                                         data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
792                                         return;
793                                 }
794
795                                 interp_weights_poly_v2(sdbind->vert_weights, bpoly->coords_v2, bpoly->numverts, bpoly->point_v2);
796
797                                 /* Reproject vert based on weights and original poly verts, to reintroduce poly non-planarity */
798                                 zero_v3(point_co_proj);
799                                 for (int j = 0; j < bpoly->numverts; j++, loop++) {
800                                         madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]);
801                                         sdbind->vert_inds[j] = loop->v;
802                                 }
803
804                                 sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
805
806                                 sdbind++;
807                                 i++;
808                         }
809                         else {
810                                 float tmp_vec[3];
811                                 float cent[3], norm[3];
812                                 float v1[3], v2[3], v3[3];
813
814                                 if (1.0f - bpoly->dominant_angle_weight >= FLT_EPSILON) {
815                                         sdbind->influence = bpoly->weight * (1.0f - bpoly->dominant_angle_weight);
816                                         sdbind->numverts = bpoly->numverts;
817
818                                         sdbind->mode = MOD_SDEF_MODE_CENTROID;
819                                         sdbind->vert_weights = MEM_mallocN(sizeof(*sdbind->vert_weights) * 3, "SDefCentVertWeights");
820                                         if (sdbind->vert_weights == NULL) {
821                                                 data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
822                                                 return;
823                                         }
824
825                                         sdbind->vert_inds = MEM_mallocN(sizeof(*sdbind->vert_inds) * bpoly->numverts, "SDefCentVertInds");
826                                         if (sdbind->vert_inds == NULL) {
827                                                 data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
828                                                 return;
829                                         }
830
831                                         sortPolyVertsEdge(sdbind->vert_inds, &data->mloop[bpoly->loopstart],
832                                                           bpoly->edge_inds[bpoly->dominant_edge], bpoly->numverts);
833
834                                         copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
835                                         copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
836                                         copy_v3_v3(v3, bpoly->centroid);
837
838                                         mid_v3_v3v3v3(cent, v1, v2, v3);
839                                         normal_tri_v3(norm, v1, v2, v3);
840
841                                         add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
842
843                                         /* We are sure the line is not parallel to the plane.
844                                          * Checking return value just to avoid warning... */
845                                         if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
846                                                 BLI_assert(false);
847                                         }
848
849                                         interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
850
851                                         sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
852
853                                         sdbind++;
854                                         i++;
855                                 }
856
857                                 if (bpoly->dominant_angle_weight >= FLT_EPSILON) {
858                                         sdbind->influence = bpoly->weight * bpoly->dominant_angle_weight;
859                                         sdbind->numverts = bpoly->numverts;
860
861                                         sdbind->mode = MOD_SDEF_MODE_LOOPTRI;
862                                         sdbind->vert_weights = MEM_mallocN(sizeof(*sdbind->vert_weights) * 3, "SDefTriVertWeights");
863                                         if (sdbind->vert_weights == NULL) {
864                                                 data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
865                                                 return;
866                                         }
867
868                                         sdbind->vert_inds = MEM_mallocN(sizeof(*sdbind->vert_inds) * bpoly->numverts, "SDefTriVertInds");
869                                         if (sdbind->vert_inds == NULL) {
870                                                 data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
871                                                 return;
872                                         }
873
874                                         sortPolyVertsTri(sdbind->vert_inds, &data->mloop[bpoly->loopstart], bpoly->edge_vert_inds[0], bpoly->numverts);
875
876                                         copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
877                                         copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
878                                         copy_v3_v3(v3, data->targetCos[sdbind->vert_inds[2]]);
879
880                                         mid_v3_v3v3v3(cent, v1, v2, v3);
881                                         normal_tri_v3(norm, v1, v2, v3);
882
883                                         add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
884
885                                         /* We are sure the line is not parallel to the plane.
886                                          * Checking return value just to avoid warning... */
887                                         if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
888                                                 BLI_assert(false);
889                                         }
890
891                                         interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
892
893                                         sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
894
895                                         sdbind++;
896                                         i++;
897                                 }
898                         }
899                 }
900         }
901
902         freeBindData(bwdata);
903 }
904
905 static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos)[3],
906                               unsigned int numverts, unsigned int tnumpoly, unsigned int tnumverts, DerivedMesh *tdm)
907 {
908         BVHTreeFromMesh treeData = {NULL};
909         const MVert *mvert = tdm->getVertArray(tdm);
910         const MPoly *mpoly = tdm->getPolyArray(tdm);
911         const MEdge *medge = tdm->getEdgeArray(tdm);
912         const MLoop *mloop = tdm->getLoopArray(tdm);
913         unsigned int tnumedges = tdm->getNumEdges(tdm);
914         int adj_result;
915         SDefAdjacencyArray *vert_edges;
916         SDefAdjacency *adj_array;
917         SDefEdgePolys *edge_polys;
918
919         vert_edges = MEM_callocN(sizeof(*vert_edges) * tnumverts, "SDefVertEdgeMap");
920         if (vert_edges == NULL) {
921                 modifier_setError((ModifierData *)smd, "Out of memory");
922                 return false;
923         }
924
925         adj_array = MEM_mallocN(sizeof(*adj_array) * tnumedges * 2, "SDefVertEdge");
926         if (adj_array == NULL) {
927                 modifier_setError((ModifierData *)smd, "Out of memory");
928                 MEM_freeN(vert_edges);
929                 return false;
930         }
931
932         edge_polys = MEM_callocN(sizeof(*edge_polys) * tnumedges, "SDefEdgeFaceMap");
933         if (edge_polys == NULL) {
934                 modifier_setError((ModifierData *)smd, "Out of memory");
935                 MEM_freeN(vert_edges);
936                 MEM_freeN(adj_array);
937                 return false;
938         }
939
940         smd->verts = MEM_mallocN(sizeof(*smd->verts) * numverts, "SDefBindVerts");
941         if (smd->verts == NULL) {
942                 modifier_setError((ModifierData *)smd, "Out of memory");
943                 freeAdjacencyMap(vert_edges, adj_array, edge_polys);
944                 return false;
945         }
946
947         bvhtree_from_mesh_looptri(&treeData, tdm, 0.0, 2, 6);
948         if (treeData.tree == NULL) {
949                 modifier_setError((ModifierData *)smd, "Out of memory");
950                 freeAdjacencyMap(vert_edges, adj_array, edge_polys);
951                 MEM_freeN(smd->verts);
952                 smd->verts = NULL;
953                 return false;
954         }
955
956         adj_result = buildAdjacencyMap(mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys);
957
958         if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
959                 modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
960                 freeAdjacencyMap(vert_edges, adj_array, edge_polys);
961                 free_bvhtree_from_mesh(&treeData);
962                 MEM_freeN(smd->verts);
963                 smd->verts = NULL;
964                 return false;
965         }
966
967         smd->numverts = numverts;
968         smd->numpoly = tnumpoly;
969
970         SDefBindCalcData data = {.treeData = &treeData,
971                                      .vert_edges = vert_edges,
972                                      .edge_polys = edge_polys,
973                                      .mpoly = mpoly,
974                                      .medge = medge,
975                                      .mloop = mloop,
976                                      .looptri = tdm->getLoopTriArray(tdm),
977                                      .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetBindVertArray"),
978                                      .bind_verts = smd->verts,
979                                      .vertexCos = vertexCos,
980                                      .falloff = smd->falloff,
981                                      .success = MOD_SDEF_BIND_RESULT_SUCCESS};
982
983         if (data.targetCos == NULL) {
984                 modifier_setError((ModifierData *)smd, "Out of memory");
985                 freeData((ModifierData *)smd);
986                 return false;
987         }
988
989         invert_m4_m4(data.imat, smd->mat);
990
991         for (int i = 0; i < tnumverts; i++) {
992                 mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
993         }
994
995         BLI_task_parallel_range_ex(0, numverts, &data, NULL, 0, bindVert,
996                                    numverts > 10000, false);
997
998         MEM_freeN(data.targetCos);
999
1000         if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
1001                 modifier_setError((ModifierData *)smd, "Out of memory");
1002                 freeData((ModifierData *)smd);
1003         }
1004         else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
1005                 modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
1006                 freeData((ModifierData *)smd);
1007         }
1008         else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) {
1009                 modifier_setError((ModifierData *)smd, "Target contains concave polygons");
1010                 freeData((ModifierData *)smd);
1011         }
1012         else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) {
1013                 modifier_setError((ModifierData *)smd, "Target contains overlapping verts");
1014                 freeData((ModifierData *)smd);
1015         }
1016         else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) {
1017                 /* I know this message is vague, but I could not think of a way
1018                  * to explain this whith a reasonably sized message.
1019                  * Though it shouldn't really matter all that much,
1020                  * because this is very unlikely to occur */
1021                 modifier_setError((ModifierData *)smd, "Target contains invalid polygons");
1022                 freeData((ModifierData *)smd);
1023         }
1024
1025         freeAdjacencyMap(vert_edges, adj_array, edge_polys);
1026         free_bvhtree_from_mesh(&treeData);
1027
1028         return data.success == 1;
1029 }
1030
1031 static void deformVert(void *userdata, void *UNUSED(userdata_chunk), const int index, const int UNUSED(threadid))
1032 {
1033         const SDefDeformData * const data = (SDefDeformData *)userdata;
1034         const SDefBind *sdbind = data->bind_verts[index].binds;
1035         float * const vertexCos = data->vertexCos[index];
1036         float norm[3], temp[3];
1037
1038         zero_v3(vertexCos);
1039
1040         for (int j = 0; j < data->bind_verts[index].numbinds; j++, sdbind++) {
1041                 /* Mode-generic operations (allocate poly coordinates) */
1042                 float (*coords)[3] = MEM_mallocN(sizeof(*coords) * sdbind->numverts, "SDefDoPolyCoords");
1043
1044                 for (int k = 0; k < sdbind->numverts; k++) {
1045                         copy_v3_v3(coords[k], data->targetCos[sdbind->vert_inds[k]]);
1046                 }
1047
1048                 normal_poly_v3(norm, coords, sdbind->numverts);
1049                 zero_v3(temp);
1050
1051                 /* ---------- looptri mode ---------- */
1052                 if (sdbind->mode == MOD_SDEF_MODE_LOOPTRI) {
1053                         madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
1054                         madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
1055                         madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[2]], sdbind->vert_weights[2]);
1056                 }
1057                 else {
1058                         /* ---------- ngon mode ---------- */
1059                         if (sdbind->mode == MOD_SDEF_MODE_NGON) {
1060                                 for (int k = 0; k < sdbind->numverts; k++) {
1061                                         madd_v3_v3fl(temp, coords[k], sdbind->vert_weights[k]);
1062                                 }
1063                         }
1064
1065                         /* ---------- centroid mode ---------- */
1066                         else if (sdbind->mode == MOD_SDEF_MODE_CENTROID) {
1067                                 float cent[3];
1068                                 mid_v3_v3_array(cent, coords, sdbind->numverts);
1069
1070                                 madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
1071                                 madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
1072                                 madd_v3_v3fl(temp, cent, sdbind->vert_weights[2]);
1073                         }
1074                 }
1075
1076                 MEM_freeN(coords);
1077
1078                 /* Apply normal offset (generic for all modes) */
1079                 madd_v3_v3fl(temp, norm, sdbind->normal_dist);
1080
1081                 madd_v3_v3fl(vertexCos, temp, sdbind->influence);
1082         }
1083 }
1084
1085 static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], unsigned int numverts, Object *ob)
1086 {
1087         SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
1088         DerivedMesh *tdm;
1089         unsigned int tnumverts, tnumpoly;
1090
1091         /* Exit function if bind flag is not set (free bind data if any) */
1092         if (!(smd->flags & MOD_SDEF_BIND)) {
1093                 freeData(md);
1094                 return;
1095         }
1096
1097         /* Handle target mesh both in and out of edit mode */
1098         if (smd->target == md->scene->obedit) {
1099                 BMEditMesh *em = BKE_editmesh_from_object(smd->target);
1100                 tdm = em->derivedFinal;
1101         }
1102         else {
1103                 tdm = smd->target->derivedFinal;
1104         }
1105
1106         tnumverts = tdm->getNumVerts(tdm);
1107         tnumpoly = tdm->getNumPolys(tdm);
1108
1109         /* If not bound, execute bind */
1110         if (!(smd->verts)) {
1111                 float tmp_mat[4][4];
1112
1113                 invert_m4_m4(tmp_mat, ob->obmat);
1114                 mul_m4_m4m4(smd->mat, tmp_mat, smd->target->obmat);
1115
1116                 if (!surfacedeformBind(smd, vertexCos, numverts, tnumpoly, tnumverts, tdm)) {
1117                         smd->flags &= ~MOD_SDEF_BIND;
1118                         return;
1119                 }
1120         }
1121
1122         /* Poly count checks */
1123         if (smd->numverts != numverts) {
1124                 modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts);
1125                 tdm->release(tdm);
1126                 return;
1127         }
1128         else if (smd->numpoly != tnumpoly) {
1129                 modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
1130                 tdm->release(tdm);
1131                 return;
1132         }
1133
1134         /* Actual vertex location update starts here */
1135         SDefDeformData data = {.bind_verts = smd->verts,
1136                                    .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetVertArray"),
1137                                    .vertexCos = vertexCos};
1138
1139         if (data.targetCos != NULL) {
1140                 bool tdm_vert_alloc;
1141                 const MVert * const mvert = DM_get_vert_array(tdm, &tdm_vert_alloc);
1142
1143                 for (int i = 0; i < tnumverts; i++) {
1144                         mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
1145                 }
1146
1147                 BLI_task_parallel_range_ex(0, numverts, &data, NULL, 0, deformVert,
1148                                            numverts > 10000, false);
1149
1150                 if (tdm_vert_alloc) {
1151                         MEM_freeN((void *)mvert);
1152                 }
1153
1154                 MEM_freeN(data.targetCos);
1155         }
1156
1157         tdm->release(tdm);
1158 }
1159
1160 static void deformVerts(ModifierData *md, Object *ob,
1161                         DerivedMesh *UNUSED(derivedData),
1162                         float (*vertexCos)[3], int numVerts,
1163                         ModifierApplyFlag UNUSED(flag))
1164 {
1165         surfacedeformModifier_do(md, vertexCos, numVerts, ob);
1166 }
1167
1168 static void deformVertsEM(ModifierData *md, Object *ob,
1169                           struct BMEditMesh *UNUSED(editData),
1170                           DerivedMesh *UNUSED(derivedData),
1171                           float (*vertexCos)[3], int numVerts)
1172 {
1173         surfacedeformModifier_do(md, vertexCos, numVerts, ob);
1174 }
1175
1176 static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
1177 {
1178         SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
1179
1180         return !smd->target;
1181 }
1182
1183 ModifierTypeInfo modifierType_SurfaceDeform = {
1184         /* name */              "Surface Deform",
1185         /* structName */        "SurfaceDeformModifierData",
1186         /* structSize */        sizeof(SurfaceDeformModifierData),
1187         /* type */              eModifierTypeType_OnlyDeform,
1188         /* flags */             eModifierTypeFlag_AcceptsMesh |
1189                                 eModifierTypeFlag_SupportsEditmode,
1190
1191         /* copyData */          copyData,
1192         /* deformVerts */       deformVerts,
1193         /* deformMatrices */    NULL,
1194         /* deformVertsEM */     deformVertsEM,
1195         /* deformMatricesEM */  NULL,
1196         /* applyModifier */     NULL,
1197         /* applyModifierEM */   NULL,
1198         /* initData */          initData,
1199         /* requiredDataMask */  NULL,
1200         /* freeData */          freeData,
1201         /* isDisabled */        isDisabled,
1202         /* updateDepsgraph */   updateDepsgraph,
1203         /* dependsOnTime */     NULL,
1204         /* dependsOnNormals */  NULL,
1205         /* foreachObjectLink */ foreachObjectLink,
1206         /* foreachIDLink */     NULL,
1207         /* foreachTexLink */    NULL,
1208 };