Blender  V3.3
shrinkwrap.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright Blender Foundation. All rights reserved. */
3 
8 #include <float.h>
9 #include <math.h>
10 #include <memory.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <time.h>
14 
16 #include "DNA_mesh_types.h"
17 #include "DNA_meshdata_types.h"
18 #include "DNA_modifier_types.h"
19 #include "DNA_object_types.h"
20 
21 #include "BLI_math.h"
22 #include "BLI_math_solvers.h"
23 #include "BLI_task.h"
24 #include "BLI_utildefines.h"
25 
26 #include "BKE_DerivedMesh.h"
27 #include "BKE_cdderivedmesh.h"
28 #include "BKE_context.h"
29 #include "BKE_lattice.h"
30 #include "BKE_lib_id.h"
31 #include "BKE_modifier.h"
32 #include "BKE_shrinkwrap.h"
33 
34 #include "BKE_deform.h"
35 #include "BKE_editmesh.h"
36 #include "BKE_mesh.h" /* for OMP limits. */
37 #include "BKE_mesh_runtime.h"
38 #include "BKE_mesh_wrapper.h"
39 #include "BKE_subsurf.h"
40 
41 #include "DEG_depsgraph_query.h"
42 
43 #include "MEM_guardedalloc.h"
44 
45 #include "BLI_strict_flags.h"
46 
47 /* for timing... */
48 #if 0
49 # include "PIL_time_utildefines.h"
50 #else
51 # define TIMEIT_BENCH(expr, id) (expr)
52 #endif
53 
54 /* Util macros */
55 #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
56 
57 typedef struct ShrinkwrapCalcData {
58  ShrinkwrapModifierData *smd; /* shrinkwrap modifier data */
59 
60  struct Object *ob; /* object we are applying shrinkwrap to */
61 
62  struct MVert *vert; /* Array of verts being projected. */
63  const float (*vert_normals)[3];
64  float (*vertexCos)[3]; /* vertexs being shrinkwraped */
65  int numVerts;
66 
67  struct MDeformVert *dvert; /* Pointer to mdeform array */
68  int vgroup; /* Vertex group num */
69  bool invert_vgroup; /* invert vertex group influence */
70 
71  struct Mesh *target; /* mesh we are shrinking to */
72  struct SpaceTransform local2target; /* transform to move between local and target space */
73  struct ShrinkwrapTreeData *tree; /* mesh BVH tree data */
74 
75  struct Object *aux_target;
76 
77  float keepDist; /* Distance to keep above target surface (units are in local space) */
79 
80 typedef struct ShrinkwrapCalcCBData {
82 
85 
86  float *proj_axis;
89 
90 bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
91 {
92  return (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) ||
93  (shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX &&
94  shrinkMode == MOD_SHRINKWRAP_ABOVE_SURFACE);
95 }
96 
98  ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals)
99 {
100  memset(data, 0, sizeof(*data));
101 
102  if (mesh == NULL) {
103  return false;
104  }
105 
106  /* We could create a BVH tree from the edit mesh,
107  * however accessing normals from the face/loop normals gets more involved.
108  * Convert mesh data since this isn't typically used in edit-mode. */
110 
111  if (mesh->totvert <= 0) {
112  return false;
113  }
114 
115  data->mesh = mesh;
116 
117  if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) {
119 
120  return data->bvh != NULL;
121  }
122 
123  if (mesh->totpoly <= 0) {
124  return false;
125  }
126 
128 
129  if (data->bvh == NULL) {
130  return false;
131  }
132 
133  if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) {
135  if ((mesh->flag & ME_AUTOSMOOTH) != 0) {
137  }
138  }
139 
140  if (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
141  data->boundary = mesh->runtime.shrinkwrap_data;
142  }
143 
144  return true;
145 }
146 
148 {
149  free_bvhtree_from_mesh(&data->treeData);
150 }
151 
153 {
155 
156  if (data != NULL) {
157  MEM_freeN((void *)data->edge_is_boundary);
158  MEM_freeN((void *)data->looptri_has_boundary);
159  MEM_freeN((void *)data->vert_boundary_id);
160  MEM_freeN((void *)data->boundary_verts);
161 
162  MEM_freeN(data);
163  }
164 
166 }
167 
168 /* Accumulate edge for average boundary edge direction. */
170  signed char *status,
171  int index,
172  const float edge_dir[3],
173  signed char side)
174 {
175  BLI_assert(index >= 0);
176  float *direction = vdata[index].direction;
177 
178  /* Invert the direction vector if either:
179  * - This is the second edge and both edges have the vertex as start or end.
180  * - For third and above, if it points in the wrong direction.
181  */
182  if (status[index] >= 0 ? status[index] == side : dot_v3v3(direction, edge_dir) < 0) {
183  sub_v3_v3(direction, edge_dir);
184  }
185  else {
186  add_v3_v3(direction, edge_dir);
187  }
188 
189  status[index] = (status[index] == 0) ? side : -1;
190 }
191 
193 {
194  const MLoop *mloop = mesh->mloop;
195  const MEdge *medge = mesh->medge;
196  const MVert *mvert = mesh->mvert;
197 
198  /* Count faces per edge (up to 2). */
199  char *edge_mode = MEM_calloc_arrayN((size_t)mesh->totedge, sizeof(char), __func__);
200 
201  for (int i = 0; i < mesh->totloop; i++) {
202  unsigned int eidx = mloop[i].e;
203 
204  if (edge_mode[eidx] < 2) {
205  edge_mode[eidx]++;
206  }
207  }
208 
209  /* Build the boundary edge bitmask. */
211  "ShrinkwrapBoundaryData::edge_is_boundary");
212  unsigned int num_boundary_edges = 0;
213 
214  for (int i = 0; i < mesh->totedge; i++) {
215  edge_mode[i] = (edge_mode[i] == 1);
216 
217  if (edge_mode[i]) {
219  num_boundary_edges++;
220  }
221  }
222 
223  /* If no boundary, return NULL. */
224  if (num_boundary_edges == 0) {
226  MEM_freeN(edge_mode);
227  return NULL;
228  }
229 
230  /* Allocate the data object. */
232  "ShrinkwrapBoundaryData");
233 
234  data->edge_is_boundary = edge_is_boundary;
235 
236  /* Build the boundary looptri bitmask. */
237  const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
238  int totlooptri = BKE_mesh_runtime_looptri_len(mesh);
239 
241  "ShrinkwrapBoundaryData::looptri_is_boundary");
242 
243  for (int i = 0; i < totlooptri; i++) {
244  int edges[3];
245  BKE_mesh_looptri_get_real_edges(mesh, &mlooptri[i], edges);
246 
247  for (int j = 0; j < 3; j++) {
248  if (edges[j] >= 0 && edge_mode[edges[j]]) {
250  break;
251  }
252  }
253  }
254 
255  data->looptri_has_boundary = looptri_has_boundary;
256 
257  /* Find boundary vertices and build a mapping table for compact storage of data. */
259  (size_t)mesh->totvert, sizeof(int), "ShrinkwrapBoundaryData::vert_boundary_id");
260 
261  for (int i = 0; i < mesh->totedge; i++) {
262  if (edge_mode[i]) {
263  const MEdge *edge = &medge[i];
264 
265  vert_boundary_id[edge->v1] = 1;
266  vert_boundary_id[edge->v2] = 1;
267  }
268  }
269 
270  unsigned int num_boundary_verts = 0;
271 
272  for (int i = 0; i < mesh->totvert; i++) {
273  vert_boundary_id[i] = (vert_boundary_id[i] != 0) ? (int)num_boundary_verts++ : -1;
274  }
275 
276  data->vert_boundary_id = vert_boundary_id;
277  data->num_boundary_verts = num_boundary_verts;
278 
279  /* Compute average directions. */
281  num_boundary_verts, sizeof(*boundary_verts), "ShrinkwrapBoundaryData::boundary_verts");
282 
283  signed char *vert_status = MEM_calloc_arrayN(num_boundary_verts, sizeof(char), __func__);
284 
285  for (int i = 0; i < mesh->totedge; i++) {
286  if (edge_mode[i]) {
287  const MEdge *edge = &medge[i];
288 
289  float dir[3];
290  sub_v3_v3v3(dir, mvert[edge->v2].co, mvert[edge->v1].co);
291  normalize_v3(dir);
292 
293  merge_vert_dir(boundary_verts, vert_status, vert_boundary_id[edge->v1], dir, 1);
294  merge_vert_dir(boundary_verts, vert_status, vert_boundary_id[edge->v2], dir, 2);
295  }
296  }
297 
298  MEM_freeN(vert_status);
299 
300  /* Finalize average direction and compute normal. */
301  const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
302  for (int i = 0; i < mesh->totvert; i++) {
303  int bidx = vert_boundary_id[i];
304 
305  if (bidx >= 0) {
307  float tmp[3];
308 
309  normalize_v3(vdata->direction);
310 
311  cross_v3_v3v3(tmp, vert_normals[i], vdata->direction);
312  cross_v3_v3v3(vdata->normal_plane, tmp, vert_normals[i]);
313  normalize_v3(vdata->normal_plane);
314  }
315  }
316 
317  data->boundary_verts = boundary_verts;
318 
319  MEM_freeN(edge_mode);
320  return data;
321 }
322 
324 {
326 
328 }
329 
336 static void shrinkwrap_calc_nearest_vertex_cb_ex(void *__restrict userdata,
337  const int i,
338  const TaskParallelTLS *__restrict tls)
339 {
340  ShrinkwrapCalcCBData *data = userdata;
341 
342  ShrinkwrapCalcData *calc = data->calc;
343  BVHTreeFromMesh *treeData = &data->tree->treeData;
344  BVHTreeNearest *nearest = tls->userdata_chunk;
345 
346  float *co = calc->vertexCos[i];
347  float tmp_co[3];
348  float weight = BKE_defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
349 
350  if (calc->invert_vgroup) {
351  weight = 1.0f - weight;
352  }
353 
354  if (weight == 0.0f) {
355  return;
356  }
357 
358  /* Convert the vertex to tree coordinates */
359  if (calc->vert) {
360  copy_v3_v3(tmp_co, calc->vert[i].co);
361  }
362  else {
363  copy_v3_v3(tmp_co, co);
364  }
365  BLI_space_transform_apply(&calc->local2target, tmp_co);
366 
367  /* Use local proximity heuristics (to reduce the nearest search)
368  *
369  * If we already had an hit before.. we assume this vertex is going to have a close hit to that
370  * other vertex so we can initiate the "nearest.dist" with the expected value to that last hit.
371  * This will lead in pruning of the search tree. */
372  if (nearest->index != -1) {
373  nearest->dist_sq = len_squared_v3v3(tmp_co, nearest->co);
374  }
375  else {
376  nearest->dist_sq = FLT_MAX;
377  }
378 
379  BLI_bvhtree_find_nearest(treeData->tree, tmp_co, nearest, treeData->nearest_callback, treeData);
380 
381  /* Found the nearest vertex */
382  if (nearest->index != -1) {
383  /* Adjusting the vertex weight,
384  * so that after interpolating it keeps a certain distance from the nearest position */
385  if (nearest->dist_sq > FLT_EPSILON) {
386  const float dist = sqrtf(nearest->dist_sq);
387  weight *= (dist - calc->keepDist) / dist;
388  }
389 
390  /* Convert the coordinates back to mesh coordinates */
391  copy_v3_v3(tmp_co, nearest->co);
393 
394  interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
395  }
396 }
397 
399 {
401 
402  /* Setup nearest */
403  nearest.index = -1;
404  nearest.dist_sq = FLT_MAX;
405 
407  .calc = calc,
408  .tree = calc->tree,
409  };
410  TaskParallelSettings settings;
412  settings.use_threading = (calc->numVerts > BKE_MESH_OMP_LIMIT);
413  settings.userdata_chunk = &nearest;
414  settings.userdata_chunk_size = sizeof(nearest);
416  0, calc->numVerts, &data, shrinkwrap_calc_nearest_vertex_cb_ex, &settings);
417 }
418 
420  const float vert[3],
421  const float dir[3],
422  const float ray_radius,
423  const SpaceTransform *transf,
425  BVHTreeRayHit *hit)
426 {
427  /* don't use this because this dist value could be incompatible
428  * this value used by the callback for comparing previous/new dist values.
429  * also, at the moment there is no need to have a corrected 'dist' value */
430  // #define USE_DIST_CORRECT
431 
432  float tmp_co[3], tmp_no[3];
433  const float *co, *no;
434  BVHTreeRayHit hit_tmp;
435 
436  /* Copy from hit (we need to convert hit rays from one space coordinates to the other */
437  memcpy(&hit_tmp, hit, sizeof(hit_tmp));
438 
439  /* Apply space transform (TODO readjust dist) */
440  if (transf) {
441  copy_v3_v3(tmp_co, vert);
442  BLI_space_transform_apply(transf, tmp_co);
443  co = tmp_co;
444 
445  copy_v3_v3(tmp_no, dir);
446  BLI_space_transform_apply_normal(transf, tmp_no);
447  no = tmp_no;
448 
449 #ifdef USE_DIST_CORRECT
450  hit_tmp.dist *= mat4_to_scale(((SpaceTransform *)transf)->local2target);
451 #endif
452  }
453  else {
454  co = vert;
455  no = dir;
456  }
457 
458  hit_tmp.index = -1;
459 
461  tree->bvh, co, no, ray_radius, &hit_tmp, tree->treeData.raycast_callback, &tree->treeData);
462 
463  if (hit_tmp.index != -1) {
464  /* invert the normal first so face culling works on rotated objects */
465  if (transf) {
466  BLI_space_transform_invert_normal(transf, hit_tmp.no);
467  }
468 
470  /* Apply back-face. */
471  const float dot = dot_v3v3(dir, hit_tmp.no);
472  if (((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) ||
474  return false; /* Ignore hit */
475  }
476  }
477 
478  if (transf) {
479  /* Inverting space transform (TODO: make coherent with the initial dist readjust). */
480  BLI_space_transform_invert(transf, hit_tmp.co);
481 #ifdef USE_DIST_CORRECT
482  hit_tmp.dist = len_v3v3(vert, hit_tmp.co);
483 #endif
484  }
485 
486  BLI_assert(hit_tmp.dist <= hit->dist);
487 
488  memcpy(hit, &hit_tmp, sizeof(hit_tmp));
489  return true;
490  }
491  return false;
492 }
493 
494 static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata,
495  const int i,
496  const TaskParallelTLS *__restrict tls)
497 {
498  ShrinkwrapCalcCBData *data = userdata;
499 
500  ShrinkwrapCalcData *calc = data->calc;
501  ShrinkwrapTreeData *tree = data->tree;
502  ShrinkwrapTreeData *aux_tree = data->aux_tree;
503 
504  float *proj_axis = data->proj_axis;
505  SpaceTransform *local2aux = data->local2aux;
506 
507  BVHTreeRayHit *hit = tls->userdata_chunk;
508 
509  const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit;
510  float *co = calc->vertexCos[i];
511  float tmp_co[3], tmp_no[3];
512  float weight = BKE_defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
513 
514  if (calc->invert_vgroup) {
515  weight = 1.0f - weight;
516  }
517 
518  if (weight == 0.0f) {
519  return;
520  }
521 
522  if (calc->vert != NULL && calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) {
523  /* calc->vert contains verts from evaluated mesh. */
524  /* These coordinates are deformed by vertexCos only for normal projection
525  * (to get correct normals) for other cases calc->verts contains undeformed coordinates and
526  * vertexCos should be used */
527  copy_v3_v3(tmp_co, calc->vert[i].co);
528  copy_v3_v3(tmp_no, calc->vert_normals[i]);
529  }
530  else {
531  copy_v3_v3(tmp_co, co);
532  copy_v3_v3(tmp_no, proj_axis);
533  }
534 
535  hit->index = -1;
536 
537  /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
538  hit->dist = BVH_RAYCAST_DIST_MAX;
539 
540  bool is_aux = false;
541 
542  /* Project over positive direction of axis */
544  if (aux_tree) {
545  if (BKE_shrinkwrap_project_normal(0, tmp_co, tmp_no, 0.0, local2aux, aux_tree, hit)) {
546  is_aux = true;
547  }
548  }
549 
551  calc->smd->shrinkOpts, tmp_co, tmp_no, 0.0, &calc->local2target, tree, hit)) {
552  is_aux = false;
553  }
554  }
555 
556  /* Project over negative direction of axis */
558  float inv_no[3];
559  negate_v3_v3(inv_no, tmp_no);
560 
561  char options = calc->smd->shrinkOpts;
562 
566  }
567 
568  if (aux_tree) {
569  if (BKE_shrinkwrap_project_normal(0, tmp_co, inv_no, 0.0, local2aux, aux_tree, hit)) {
570  is_aux = true;
571  }
572  }
573 
575  options, tmp_co, inv_no, 0.0, &calc->local2target, tree, hit)) {
576  is_aux = false;
577  }
578  }
579 
580  /* don't set the initial dist (which is more efficient),
581  * because its calculated in the targets space, we want the dist in our own space */
582  if (proj_limit_squared != 0.0f) {
583  if (hit->index != -1 && len_squared_v3v3(hit->co, co) > proj_limit_squared) {
584  hit->index = -1;
585  }
586  }
587 
588  if (hit->index != -1) {
589  if (is_aux) {
591  local2aux,
592  calc->smd->shrinkMode,
593  hit->index,
594  hit->co,
595  hit->no,
596  calc->keepDist,
597  tmp_co,
598  hit->co);
599  }
600  else {
602  &calc->local2target,
603  calc->smd->shrinkMode,
604  hit->index,
605  hit->co,
606  hit->no,
607  calc->keepDist,
608  tmp_co,
609  hit->co);
610  }
611 
612  interp_v3_v3v3(co, co, hit->co, weight);
613  }
614 }
615 
617 {
618  /* Options about projection direction */
619  float proj_axis[3] = {0.0f, 0.0f, 0.0f};
620 
621  /* Ray-cast and tree stuff. */
622 
626  BVHTreeRayHit hit;
627 
628  /* auxiliary target */
629  Mesh *auxMesh = NULL;
630  ShrinkwrapTreeData *aux_tree = NULL;
631  ShrinkwrapTreeData aux_tree_stack;
632  SpaceTransform local2aux;
633 
634  /* If the user doesn't allows to project in any direction of projection axis
635  * then there's nothing todo. */
636  if ((calc->smd->shrinkOpts &
638  return;
639  }
640 
641  /* Prepare data to retrieve the direction in which we should project each vertex */
643  if (calc->vert == NULL) {
644  return;
645  }
646  }
647  else {
648  /* The code supports any axis that is a combination of X,Y,Z
649  * although currently UI only allows to set the 3 different axis */
651  proj_axis[0] = 1.0f;
652  }
654  proj_axis[1] = 1.0f;
655  }
657  proj_axis[2] = 1.0f;
658  }
659 
660  normalize_v3(proj_axis);
661 
662  /* Invalid projection direction */
663  if (len_squared_v3(proj_axis) < FLT_EPSILON) {
664  return;
665  }
666  }
667 
668  if (calc->aux_target) {
670  if (!auxMesh) {
671  return;
672  }
673  BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->aux_target);
674  }
675 
677  &aux_tree_stack, auxMesh, calc->smd->shrinkType, calc->smd->shrinkMode, false)) {
678  aux_tree = &aux_tree_stack;
679  }
680 
681  /* After successfully build the trees, start projection vertices. */
683  .calc = calc,
684  .tree = calc->tree,
685  .aux_tree = aux_tree,
686  .proj_axis = proj_axis,
687  .local2aux = &local2aux,
688  };
689  TaskParallelSettings settings;
691  settings.use_threading = (calc->numVerts > BKE_MESH_OMP_LIMIT);
692  settings.userdata_chunk = &hit;
693  settings.userdata_chunk_size = sizeof(hit);
695  0, calc->numVerts, &data, shrinkwrap_calc_normal_projection_cb_ex, &settings);
696 
697  /* free data structures */
698  if (aux_tree) {
699  BKE_shrinkwrap_free_tree(aux_tree);
700  }
701 }
702 
703 /*
704  * Shrinkwrap Target Surface Project mode
705  *
706  * It uses Newton's method to find a surface location with its
707  * smooth normal pointing at the original point.
708  *
709  * The equation system on barycentric weights and normal multiplier:
710  *
711  * (w0*V0 + w1*V1 + w2*V2) + l * (w0*N0 + w1*N1 + w2*N2) - CO = 0
712  * w0 + w1 + w2 = 1
713  *
714  * The actual solution vector is [ w0, w1, l ], with w2 eliminated.
715  */
716 
717 //#define TRACE_TARGET_PROJECT
718 
719 typedef struct TargetProjectTriData {
720  const float **vtri_co;
721  const float (*vtri_no)[3];
722  const float *point_co;
723 
724  float n0_minus_n2[3], n1_minus_n2[3];
725  float c0_minus_c2[3], c1_minus_c2[3];
726 
727  /* Current interpolated position and normal. */
728  float co_interp[3], no_interp[3];
730 
731 /* Computes the deviation of the equation system from goal. */
732 static void target_project_tri_deviation(void *userdata, const float x[3], float r_delta[3])
733 {
734  TargetProjectTriData *data = userdata;
735 
736  const float w[3] = {x[0], x[1], 1.0f - x[0] - x[1]};
737  interp_v3_v3v3v3(data->co_interp, data->vtri_co[0], data->vtri_co[1], data->vtri_co[2], w);
738  interp_v3_v3v3v3(data->no_interp, data->vtri_no[0], data->vtri_no[1], data->vtri_no[2], w);
739 
740  madd_v3_v3v3fl(r_delta, data->co_interp, data->no_interp, x[2]);
741  sub_v3_v3(r_delta, data->point_co);
742 }
743 
744 /* Computes the Jacobian matrix of the equation system. */
745 static void target_project_tri_jacobian(void *userdata, const float x[3], float r_jacobian[3][3])
746 {
747  TargetProjectTriData *data = userdata;
748 
749  madd_v3_v3v3fl(r_jacobian[0], data->c0_minus_c2, data->n0_minus_n2, x[2]);
750  madd_v3_v3v3fl(r_jacobian[1], data->c1_minus_c2, data->n1_minus_n2, x[2]);
751 
752  copy_v3_v3(r_jacobian[2], data->vtri_no[2]);
753  madd_v3_v3fl(r_jacobian[2], data->n0_minus_n2, x[0]);
754  madd_v3_v3fl(r_jacobian[2], data->n1_minus_n2, x[1]);
755 }
756 
757 /* Clamp barycentric weights to the triangle. */
758 static void target_project_tri_clamp(float x[3])
759 {
760  if (x[0] < 0.0f) {
761  x[0] = 0.0f;
762  }
763  if (x[1] < 0.0f) {
764  x[1] = 0.0f;
765  }
766  if (x[0] + x[1] > 1.0f) {
767  x[0] = x[0] / (x[0] + x[1]);
768  x[1] = 1.0f - x[0];
769  }
770 }
771 
772 /* Correct the Newton's method step to keep the coordinates within the triangle. */
773 static bool target_project_tri_correct(void *UNUSED(userdata),
774  const float x[3],
775  float step[3],
776  float x_next[3])
777 {
778  /* Insignificant correction threshold */
779  const float epsilon = 1e-5f;
780  /* Dot product threshold for checking if step is 'clearly' pointing outside. */
781  const float dir_epsilon = 0.5f;
782  bool fixed = false, locked = false;
783 
784  /* The barycentric coordinate domain is a triangle bounded by
785  * the X and Y axes, plus the x+y=1 diagonal. First, clamp the
786  * movement against the diagonal. Note that step is subtracted. */
787  float sum = x[0] + x[1];
788  float sstep = -(step[0] + step[1]);
789 
790  if (sum + sstep > 1.0f) {
791  float ldist = 1.0f - sum;
792 
793  /* If already at the boundary, slide along it. */
794  if (ldist < epsilon * (float)M_SQRT2) {
795  float step_len = len_v2(step);
796 
797  /* Abort if the solution is clearly outside the domain. */
798  if (step_len > epsilon && sstep > step_len * dir_epsilon * (float)M_SQRT2) {
799  return false;
800  }
801 
802  /* Project the new position onto the diagonal. */
803  add_v2_fl(step, (sum + sstep - 1.0f) * 0.5f);
804  fixed = locked = true;
805  }
806  else {
807  /* Scale a significant step down to arrive at the boundary. */
808  mul_v3_fl(step, ldist / sstep);
809  fixed = true;
810  }
811  }
812 
813  /* Weight 0 and 1 boundary checks - along axis. */
814  for (int i = 0; i < 2; i++) {
815  if (step[i] > x[i]) {
816  /* If already at the boundary, slide along it. */
817  if (x[i] < epsilon) {
818  float step_len = len_v2(step);
819 
820  /* Abort if the solution is clearly outside the domain. */
821  if (step_len > epsilon && (locked || step[i] > step_len * dir_epsilon)) {
822  return false;
823  }
824 
825  /* Reset precision errors to stay at the boundary. */
826  step[i] = x[i];
827  fixed = true;
828  }
829  else {
830  /* Scale a significant step down to arrive at the boundary. */
831  mul_v3_fl(step, x[i] / step[i]);
832  fixed = true;
833  }
834  }
835  }
836 
837  /* Recompute and clamp the new coordinates after step correction. */
838  if (fixed) {
839  sub_v3_v3v3(x_next, x, step);
840  target_project_tri_clamp(x_next);
841  }
842 
843  return true;
844 }
845 
846 static bool target_project_solve_point_tri(const float *vtri_co[3],
847  const float vtri_no[3][3],
848  const float point_co[3],
849  const float hit_co[3],
850  float hit_dist_sq,
851  float r_hit_co[3],
852  float r_hit_no[3])
853 {
854  float x[3], tmp[3];
855  float dist = sqrtf(hit_dist_sq);
856  float magnitude_estimate = dist + len_manhattan_v3(vtri_co[0]) + len_manhattan_v3(vtri_co[1]) +
857  len_manhattan_v3(vtri_co[2]);
858  float epsilon = magnitude_estimate * 1.0e-6f;
859 
860  /* Initial solution vector: barycentric weights plus distance along normal. */
861  interp_weights_tri_v3(x, UNPACK3(vtri_co), hit_co);
862 
863  interp_v3_v3v3v3(r_hit_no, UNPACK3(vtri_no), x);
864  sub_v3_v3v3(tmp, point_co, hit_co);
865 
866  x[2] = (dot_v3v3(tmp, r_hit_no) < 0) ? -dist : dist;
867 
868  /* Solve the equations iteratively. */
869  TargetProjectTriData tri_data = {
870  .vtri_co = vtri_co,
871  .vtri_no = vtri_no,
872  .point_co = point_co,
873  };
874 
875  sub_v3_v3v3(tri_data.n0_minus_n2, vtri_no[0], vtri_no[2]);
876  sub_v3_v3v3(tri_data.n1_minus_n2, vtri_no[1], vtri_no[2]);
877  sub_v3_v3v3(tri_data.c0_minus_c2, vtri_co[0], vtri_co[2]);
878  sub_v3_v3v3(tri_data.c1_minus_c2, vtri_co[1], vtri_co[2]);
879 
881 
882 #ifdef TRACE_TARGET_PROJECT
883  const bool trace = true;
884 #else
885  const bool trace = false;
886 #endif
887 
891  &tri_data,
892  epsilon,
893  20,
894  trace,
895  x,
896  x);
897 
898  if (ok) {
899  copy_v3_v3(r_hit_co, tri_data.co_interp);
900  copy_v3_v3(r_hit_no, tri_data.no_interp);
901 
902  return true;
903  }
904 
905  return false;
906 }
907 
908 static bool update_hit(BVHTreeNearest *nearest,
909  int index,
910  const float co[3],
911  const float hit_co[3],
912  const float hit_no[3])
913 {
914  float dist_sq = len_squared_v3v3(hit_co, co);
915 
916  if (dist_sq < nearest->dist_sq) {
917 #ifdef TRACE_TARGET_PROJECT
918  printf(
919  "#=#=#> %d (%.3f,%.3f,%.3f) %g < %g\n", index, UNPACK3(hit_co), dist_sq, nearest->dist_sq);
920 #endif
921  nearest->index = index;
922  nearest->dist_sq = dist_sq;
923  copy_v3_v3(nearest->co, hit_co);
924  normalize_v3_v3(nearest->no, hit_no);
925  return true;
926  }
927 
928  return false;
929 }
930 
931 /* Target projection on a non-manifold boundary edge -
932  * treats it like an infinitely thin cylinder. */
934  int index,
935  const float co[3],
936  BVHTreeNearest *nearest,
937  int eidx)
938 {
939  const BVHTreeFromMesh *data = &tree->treeData;
940  const MEdge *edge = &tree->mesh->medge[eidx];
941  const float *vedge_co[2] = {data->vert[edge->v1].co, data->vert[edge->v2].co};
942 
943 #ifdef TRACE_TARGET_PROJECT
944  printf("EDGE %d (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f)\n",
945  eidx,
946  UNPACK3(vedge_co[0]),
947  UNPACK3(vedge_co[1]));
948 #endif
949 
950  /* Retrieve boundary vertex IDs */
951  const int *vert_boundary_id = tree->boundary->vert_boundary_id;
952  int bid1 = vert_boundary_id[edge->v1], bid2 = vert_boundary_id[edge->v2];
953 
954  if (bid1 < 0 || bid2 < 0) {
955  return;
956  }
957 
958  /* Retrieve boundary vertex normals and align them to direction. */
959  const ShrinkwrapBoundaryVertData *boundary_verts = tree->boundary->boundary_verts;
960  float vedge_dir[2][3], dir[3];
961 
962  copy_v3_v3(vedge_dir[0], boundary_verts[bid1].normal_plane);
963  copy_v3_v3(vedge_dir[1], boundary_verts[bid2].normal_plane);
964 
965  sub_v3_v3v3(dir, vedge_co[1], vedge_co[0]);
966 
967  if (dot_v3v3(boundary_verts[bid1].direction, dir) < 0) {
968  negate_v3(vedge_dir[0]);
969  }
970  if (dot_v3v3(boundary_verts[bid2].direction, dir) < 0) {
971  negate_v3(vedge_dir[1]);
972  }
973 
974  /* Solve a quadratic equation: lerp(d0,d1,x) * (co - lerp(v0,v1,x)) = 0 */
975  float d0v0 = dot_v3v3(vedge_dir[0], vedge_co[0]), d0v1 = dot_v3v3(vedge_dir[0], vedge_co[1]);
976  float d1v0 = dot_v3v3(vedge_dir[1], vedge_co[0]), d1v1 = dot_v3v3(vedge_dir[1], vedge_co[1]);
977  float d0co = dot_v3v3(vedge_dir[0], co);
978 
979  float a = d0v1 - d0v0 + d1v0 - d1v1;
980  float b = 2 * d0v0 - d0v1 - d0co - d1v0 + dot_v3v3(vedge_dir[1], co);
981  float c = d0co - d0v0;
982  float det = b * b - 4 * a * c;
983 
984  if (det >= 0) {
985  const float epsilon = 1e-6f;
986  float sdet = sqrtf(det);
987  float hit_co[3], hit_no[3];
988 
989  for (int i = (det > 0 ? 2 : 0); i >= 0; i -= 2) {
990  float x = (-b + ((float)i - 1) * sdet) / (2 * a);
991 
992  if (x >= -epsilon && x <= 1.0f + epsilon) {
993  CLAMP(x, 0, 1);
994 
995  float vedge_no[2][3];
996  copy_v3_v3(vedge_no[0], data->vert_normals[edge->v1]);
997  copy_v3_v3(vedge_no[1], data->vert_normals[edge->v2]);
998 
999  interp_v3_v3v3(hit_co, vedge_co[0], vedge_co[1], x);
1000  interp_v3_v3v3(hit_no, vedge_no[0], vedge_no[1], x);
1001 
1002  update_hit(nearest, index, co, hit_co, hit_no);
1003  }
1004  }
1005  }
1006 }
1007 
1008 /* Target normal projection BVH callback - based on mesh_looptri_nearest_point. */
1009 static void mesh_looptri_target_project(void *userdata,
1010  int index,
1011  const float co[3],
1012  BVHTreeNearest *nearest)
1013 {
1014  const ShrinkwrapTreeData *tree = (ShrinkwrapTreeData *)userdata;
1015  const BVHTreeFromMesh *data = &tree->treeData;
1016  const MLoopTri *lt = &data->looptri[index];
1017  const MLoop *loop[3] = {
1018  &data->loop[lt->tri[0]], &data->loop[lt->tri[1]], &data->loop[lt->tri[2]]};
1019  const MVert *vtri[3] = {
1020  &data->vert[loop[0]->v], &data->vert[loop[1]->v], &data->vert[loop[2]->v]};
1021  const float *vtri_co[3] = {vtri[0]->co, vtri[1]->co, vtri[2]->co};
1022  float raw_hit_co[3], hit_co[3], hit_no[3], dist_sq, vtri_no[3][3];
1023 
1024  /* First find the closest point and bail out if it's worse than the current solution. */
1025  closest_on_tri_to_point_v3(raw_hit_co, co, UNPACK3(vtri_co));
1026  dist_sq = len_squared_v3v3(co, raw_hit_co);
1027 
1028 #ifdef TRACE_TARGET_PROJECT
1029  printf("TRIANGLE %d (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) %g %g\n",
1030  index,
1031  UNPACK3(vtri_co[0]),
1032  UNPACK3(vtri_co[1]),
1033  UNPACK3(vtri_co[2]),
1034  dist_sq,
1035  nearest->dist_sq);
1036 #endif
1037 
1038  if (dist_sq >= nearest->dist_sq) {
1039  return;
1040  }
1041 
1042  /* Decode normals */
1043  copy_v3_v3(vtri_no[0], tree->treeData.vert_normals[loop[0]->v]);
1044  copy_v3_v3(vtri_no[1], tree->treeData.vert_normals[loop[1]->v]);
1045  copy_v3_v3(vtri_no[2], tree->treeData.vert_normals[loop[2]->v]);
1046 
1047  /* Solve the equations for the triangle */
1048  if (target_project_solve_point_tri(vtri_co, vtri_no, co, raw_hit_co, dist_sq, hit_co, hit_no)) {
1049  update_hit(nearest, index, co, hit_co, hit_no);
1050  }
1051  /* Boundary edges */
1052  else if (tree->boundary && BLI_BITMAP_TEST(tree->boundary->looptri_has_boundary, index)) {
1053  const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary;
1054  int edges[3];
1055 
1056  BKE_mesh_looptri_get_real_edges(tree->mesh, lt, edges);
1057 
1058  for (int i = 0; i < 3; i++) {
1059  if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) {
1060  target_project_edge(tree, index, co, nearest, edges[i]);
1061  }
1062  }
1063  }
1064 }
1065 
1067  BVHTreeNearest *nearest,
1068  float co[3],
1069  int type)
1070 {
1071  BVHTreeFromMesh *treeData = &tree->treeData;
1072 
1074 #ifdef TRACE_TARGET_PROJECT
1075  printf("\n====== TARGET PROJECT START ======\n");
1076 #endif
1077 
1080 
1081 #ifdef TRACE_TARGET_PROJECT
1082  printf("====== TARGET PROJECT END: %d %g ======\n\n", nearest->index, nearest->dist_sq);
1083 #endif
1084 
1085  if (nearest->index < 0) {
1086  /* fallback to simple nearest */
1087  BLI_bvhtree_find_nearest(tree->bvh, co, nearest, treeData->nearest_callback, treeData);
1088  }
1089  }
1090  else {
1091  BLI_bvhtree_find_nearest(tree->bvh, co, nearest, treeData->nearest_callback, treeData);
1092  }
1093 }
1094 
1095 /*
1096  * Shrinkwrap moving vertexs to the nearest surface point on the target
1097  *
1098  * it builds a BVHTree from the target mesh and then performs a
1099  * NN matches for each vertex
1100  */
1101 static void shrinkwrap_calc_nearest_surface_point_cb_ex(void *__restrict userdata,
1102  const int i,
1103  const TaskParallelTLS *__restrict tls)
1104 {
1105  ShrinkwrapCalcCBData *data = userdata;
1106 
1107  ShrinkwrapCalcData *calc = data->calc;
1108  BVHTreeNearest *nearest = tls->userdata_chunk;
1109 
1110  float *co = calc->vertexCos[i];
1111  float tmp_co[3];
1112  float weight = BKE_defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
1113 
1114  if (calc->invert_vgroup) {
1115  weight = 1.0f - weight;
1116  }
1117 
1118  if (weight == 0.0f) {
1119  return;
1120  }
1121 
1122  /* Convert the vertex to tree coordinates */
1123  if (calc->vert) {
1124  copy_v3_v3(tmp_co, calc->vert[i].co);
1125  }
1126  else {
1127  copy_v3_v3(tmp_co, co);
1128  }
1129  BLI_space_transform_apply(&calc->local2target, tmp_co);
1130 
1131  /* Use local proximity heuristics (to reduce the nearest search)
1132  *
1133  * If we already had an hit before.. we assume this vertex is going to have a close hit to that
1134  * other vertex so we can initiate the "nearest.dist" with the expected value to that last hit.
1135  * This will lead in pruning of the search tree. */
1136  if (nearest->index != -1) {
1138  /* Heuristic doesn't work because of additional restrictions. */
1139  nearest->index = -1;
1140  nearest->dist_sq = FLT_MAX;
1141  }
1142  else {
1143  nearest->dist_sq = len_squared_v3v3(tmp_co, nearest->co);
1144  }
1145  }
1146  else {
1147  nearest->dist_sq = FLT_MAX;
1148  }
1149 
1150  BKE_shrinkwrap_find_nearest_surface(data->tree, nearest, tmp_co, calc->smd->shrinkType);
1151 
1152  /* Found the nearest vertex */
1153  if (nearest->index != -1) {
1155  NULL,
1156  calc->smd->shrinkMode,
1157  nearest->index,
1158  nearest->co,
1159  nearest->no,
1160  calc->keepDist,
1161  tmp_co,
1162  tmp_co);
1163 
1164  /* Convert the coordinates back to mesh coordinates */
1165  BLI_space_transform_invert(&calc->local2target, tmp_co);
1166  interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
1167  }
1168 }
1169 
1171  const struct SpaceTransform *transform,
1172  int looptri_idx,
1173  const float hit_co[3],
1174  const float hit_no[3],
1175  float r_no[3])
1176 {
1177  const BVHTreeFromMesh *treeData = &tree->treeData;
1178  const MLoopTri *tri = &treeData->looptri[looptri_idx];
1179  const float(*vert_normals)[3] = tree->treeData.vert_normals;
1180 
1181  /* Interpolate smooth normals if enabled. */
1182  if ((tree->mesh->mpoly[tri->poly].flag & ME_SMOOTH) != 0) {
1183  const uint32_t vert_indices[3] = {treeData->loop[tri->tri[0]].v,
1184  treeData->loop[tri->tri[1]].v,
1185  treeData->loop[tri->tri[2]].v};
1186  float w[3], no[3][3], tmp_co[3];
1187 
1188  /* Custom and auto smooth split normals. */
1189  if (tree->clnors) {
1190  copy_v3_v3(no[0], tree->clnors[tri->tri[0]]);
1191  copy_v3_v3(no[1], tree->clnors[tri->tri[1]]);
1192  copy_v3_v3(no[2], tree->clnors[tri->tri[2]]);
1193  }
1194  /* Ordinary vertex normals. */
1195  else {
1196  copy_v3_v3(no[0], vert_normals[vert_indices[0]]);
1197  copy_v3_v3(no[1], vert_normals[vert_indices[1]]);
1198  copy_v3_v3(no[2], vert_normals[vert_indices[2]]);
1199  }
1200 
1201  /* Barycentric weights from hit point. */
1202  copy_v3_v3(tmp_co, hit_co);
1203 
1204  if (transform) {
1206  }
1207 
1209  treeData->vert[vert_indices[0]].co,
1210  treeData->vert[vert_indices[1]].co,
1211  treeData->vert[vert_indices[2]].co,
1212  tmp_co);
1213 
1214  /* Interpolate using weights. */
1215  interp_v3_v3v3v3(r_no, no[0], no[1], no[2], w);
1216 
1217  if (transform) {
1219  }
1220  else {
1221  normalize_v3(r_no);
1222  }
1223  }
1224  /* Use the polygon normal if flat. */
1225  else if (tree->pnors != NULL) {
1226  copy_v3_v3(r_no, tree->pnors[tri->poly]);
1227  }
1228  /* Finally fallback to the looptri normal. */
1229  else {
1230  copy_v3_v3(r_no, hit_no);
1231  }
1232 }
1233 
1234 /* Helper for MOD_SHRINKWRAP_INSIDE, MOD_SHRINKWRAP_OUTSIDE and MOD_SHRINKWRAP_OUTSIDE_SURFACE. */
1235 static void shrinkwrap_snap_with_side(float r_point_co[3],
1236  const float point_co[3],
1237  const float hit_co[3],
1238  const float hit_no[3],
1239  float goal_dist,
1240  float forcesign,
1241  bool forcesnap)
1242 {
1243  float delta[3];
1244  sub_v3_v3v3(delta, point_co, hit_co);
1245 
1246  float dist = len_v3(delta);
1247 
1248  /* If exactly on the surface, push out along normal */
1249  if (dist < FLT_EPSILON) {
1250  if (forcesnap || goal_dist > 0) {
1251  madd_v3_v3v3fl(r_point_co, hit_co, hit_no, goal_dist * forcesign);
1252  }
1253  else {
1254  copy_v3_v3(r_point_co, hit_co);
1255  }
1256  }
1257  /* Move to the correct side if needed */
1258  else {
1259  float dsign = signf(dot_v3v3(delta, hit_no));
1260 
1261  if (forcesign == 0.0f) {
1262  forcesign = dsign;
1263  }
1264 
1265  /* If on the wrong side or too close, move to correct */
1266  if (forcesnap || dsign * dist * forcesign < goal_dist) {
1267  mul_v3_fl(delta, dsign / dist);
1268 
1269  /* At very small distance, blend in the hit normal to stabilize math. */
1270  float dist_epsilon = (fabsf(goal_dist) + len_manhattan_v3(hit_co)) * 1e-4f;
1271 
1272  if (dist < dist_epsilon) {
1273 #ifdef TRACE_TARGET_PROJECT
1274  printf("zero_factor %g = %g / %g\n", dist / dist_epsilon, dist, dist_epsilon);
1275 #endif
1276 
1277  interp_v3_v3v3(delta, hit_no, delta, dist / dist_epsilon);
1278  }
1279 
1280  madd_v3_v3v3fl(r_point_co, hit_co, delta, goal_dist * forcesign);
1281  }
1282  else {
1283  copy_v3_v3(r_point_co, point_co);
1284  }
1285  }
1286 }
1287 
1289  const struct SpaceTransform *transform,
1290  int mode,
1291  int hit_idx,
1292  const float hit_co[3],
1293  const float hit_no[3],
1294  float goal_dist,
1295  const float point_co[3],
1296  float r_point_co[3])
1297 {
1298  float tmp[3];
1299 
1300  switch (mode) {
1301  /* Offsets along the line between point_co and hit_co. */
1303  if (goal_dist != 0) {
1304  shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, 0, true);
1305  }
1306  else {
1307  copy_v3_v3(r_point_co, hit_co);
1308  }
1309  break;
1310 
1311  case MOD_SHRINKWRAP_INSIDE:
1312  shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, -1, false);
1313  break;
1314 
1316  shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, +1, false);
1317  break;
1318 
1320  if (goal_dist != 0) {
1321  shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, +1, true);
1322  }
1323  else {
1324  copy_v3_v3(r_point_co, hit_co);
1325  }
1326  break;
1327 
1328  /* Offsets along the normal */
1330  if (goal_dist != 0) {
1331  BKE_shrinkwrap_compute_smooth_normal(tree, transform, hit_idx, hit_co, hit_no, tmp);
1332  madd_v3_v3v3fl(r_point_co, hit_co, tmp, goal_dist);
1333  }
1334  else {
1335  copy_v3_v3(r_point_co, hit_co);
1336  }
1337  break;
1338 
1339  default:
1340  printf("Unknown Shrinkwrap surface snap mode: %d\n", mode);
1341  copy_v3_v3(r_point_co, hit_co);
1342  }
1343 }
1344 
1346 {
1348 
1349  /* Setup nearest */
1350  nearest.index = -1;
1351  nearest.dist_sq = FLT_MAX;
1352 
1353  /* Find the nearest vertex */
1355  .calc = calc,
1356  .tree = calc->tree,
1357  };
1358  TaskParallelSettings settings;
1360  settings.use_threading = (calc->numVerts > BKE_MESH_OMP_LIMIT);
1361  settings.userdata_chunk = &nearest;
1362  settings.userdata_chunk_size = sizeof(nearest);
1365 }
1366 
1368  const ModifierEvalContext *ctx,
1369  struct Scene *scene,
1370  Object *ob,
1371  Mesh *mesh,
1372  MDeformVert *dvert,
1373  const int defgrp_index,
1374  float (*vertexCos)[3],
1375  int numVerts)
1376 {
1377 
1378  DerivedMesh *ss_mesh = NULL;
1380 
1381  /* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) */
1382  if (smd->target == ob) {
1383  smd->target = NULL;
1384  }
1385  if (smd->auxTarget == ob) {
1386  smd->auxTarget = NULL;
1387  }
1388 
1389  /* Configure Shrinkwrap calc data */
1390  calc.smd = smd;
1391  calc.ob = ob;
1392  calc.numVerts = numVerts;
1393  calc.vertexCos = vertexCos;
1394  calc.dvert = dvert;
1395  calc.vgroup = defgrp_index;
1397 
1398  if (smd->target != NULL) {
1399  Object *ob_target = DEG_get_evaluated_object(ctx->depsgraph, smd->target);
1401 
1402  /* TODO: there might be several "bugs" with non-uniform scales matrices
1403  * because it will no longer be nearest surface, not sphere projection
1404  * because space has been deformed */
1405  BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, ob_target);
1406 
1407  /* TODO: smd->keepDist is in global units.. must change to local */
1408  calc.keepDist = smd->keepDist;
1409  }
1411 
1412  if (mesh != NULL && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) {
1413  /* Setup arrays to get vertexs positions, normals and deform weights */
1414  calc.vert = mesh->mvert;
1416 
1417  /* Using vertexs positions/normals as if a subsurface was applied */
1418  if (smd->subsurfLevels) {
1419  SubsurfModifierData ssmd = {{NULL}};
1420  ssmd.subdivType = ME_CC_SUBSURF; /* catmull clark */
1421  ssmd.levels = smd->subsurfLevels; /* levels */
1422 
1423  /* TODO: to be moved to Mesh once we are done with changes in subsurf code. */
1425 
1427  dm, &ssmd, scene, NULL, (ob->mode & OB_MODE_EDIT) ? SUBSURF_IN_EDIT_MODE : 0);
1428 
1429  if (ss_mesh) {
1430  calc.vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT);
1431  if (calc.vert) {
1432  /* TRICKY: this code assumes subsurface will have the transformed original vertices
1433  * in their original order at the end of the vert array. */
1434  calc.vert = calc.vert + ss_mesh->getNumVerts(ss_mesh) - dm->getNumVerts(dm);
1435  }
1436  }
1437 
1438  /* Just to make sure we are not leaving any memory behind */
1439  BLI_assert(ssmd.emCache == NULL);
1440  BLI_assert(ssmd.mCache == NULL);
1441 
1442  dm->release(dm);
1443  }
1444  }
1445 
1446  /* Projecting target defined - lets work! */
1448 
1449  if (BKE_shrinkwrap_init_tree(&tree, calc.target, smd->shrinkType, smd->shrinkMode, false)) {
1450  calc.tree = &tree;
1451 
1452  switch (smd->shrinkType) {
1455  TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), deform_surface);
1456  break;
1457 
1459  TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), deform_project);
1460  break;
1461 
1463  TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), deform_vertex);
1464  break;
1465  }
1466 
1468  }
1469 
1470  /* free memory */
1471  if (ss_mesh) {
1472  ss_mesh->release(ss_mesh);
1473  }
1474 }
1475 
1477  Object *ob,
1478  MDeformVert *dvert,
1479  const int defgrp_index,
1480  float (*vertexCos)[3],
1481  int numVerts)
1482 {
1483 
1485  /* Convert gpencil struct to use the same struct and function used with meshes. */
1487  smd.target = mmd->target;
1488  smd.auxTarget = mmd->aux_target;
1489  smd.keepDist = mmd->keep_dist;
1490  smd.shrinkType = mmd->shrink_type;
1491  smd.shrinkOpts = mmd->shrink_opts;
1492  smd.shrinkMode = mmd->shrink_mode;
1493  smd.projLimit = mmd->proj_limit;
1494  smd.projAxis = mmd->proj_axis;
1495 
1496  /* Configure Shrinkwrap calc data. */
1497  calc.smd = &smd;
1498  calc.ob = ob;
1499  calc.numVerts = numVerts;
1500  calc.vertexCos = vertexCos;
1501  calc.dvert = dvert;
1502  calc.vgroup = defgrp_index;
1503  calc.invert_vgroup = (mmd->flag & GP_SHRINKWRAP_INVERT_VGROUP) != 0;
1504 
1506  calc.keepDist = mmd->keep_dist;
1507  calc.tree = mmd->cache_data;
1508 
1509  switch (mmd->shrink_type) {
1512  TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), gpdeform_surface);
1513  break;
1514 
1516  TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), gpdeform_project);
1517  break;
1518 
1520  TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), gpdeform_vertex);
1521  break;
1522  }
1523 }
1524 
1526  Object *ob_source,
1527  Object *ob_target)
1528 {
1530  struct Scene *sce = CTX_data_scene(C);
1531  ShrinkwrapModifierData ssmd = {{0}};
1532  ModifierEvalContext ctx = {depsgraph, ob_source, 0};
1533  int totvert;
1534 
1535  ssmd.target = ob_target;
1538  ssmd.keepDist = 0.0f;
1539 
1540  Mesh *src_me = ob_source->data;
1541  float(*vertexCos)[3] = BKE_mesh_vert_coords_alloc(src_me, &totvert);
1542 
1543  shrinkwrapModifier_deform(&ssmd, &ctx, sce, ob_source, src_me, NULL, -1, vertexCos, totvert);
1544 
1545  BKE_mesh_vert_coords_apply(src_me, vertexCos);
1546 
1547  MEM_freeN(vertexCos);
1548 }
1549 
1550 void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
1551 {
1552  ShrinkwrapModifierData ssmd = {{0}};
1553  int totvert;
1554 
1555  ssmd.target = ob_target;
1559  ssmd.keepDist = 0.0f;
1560 
1561  /* Tolerance value to prevent artifacts on sharp edges of a mesh.
1562  * This constant and based on experimenting with different values. */
1563  const float projLimitTolerance = 5.0f;
1564  ssmd.projLimit = target_me->remesh_voxel_size * projLimitTolerance;
1565 
1566  float(*vertexCos)[3] = BKE_mesh_vert_coords_alloc(src_me, &totvert);
1567 
1569 
1570  calc.smd = &ssmd;
1571  calc.numVerts = src_me->totvert;
1572  calc.vertexCos = vertexCos;
1574  calc.vgroup = -1;
1575  calc.target = target_me;
1576  calc.keepDist = ssmd.keepDist;
1577  calc.vert = src_me->mvert;
1578  BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob_target, ob_target);
1579 
1581  if (BKE_shrinkwrap_init_tree(&tree, calc.target, ssmd.shrinkType, ssmd.shrinkMode, false)) {
1582  calc.tree = &tree;
1583  TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), deform_project);
1585  }
1586 
1587  BKE_mesh_vert_coords_apply(src_me, vertexCos);
1588 
1589  MEM_freeN(vertexCos);
1590 }
typedef float(TangentPoint)[2]
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.cc:1410
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:73
@ BVHTREE_FROM_VERTS
Definition: BKE_bvhutils.h:70
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
Definition: bvhutils.cc:1213
struct DerivedMesh * CDDM_from_mesh(struct Mesh *mesh)
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
void * CustomData_get_layer(const struct CustomData *data, int type)
support for deformation groups and hooks.
float BKE_defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index, int defgroup)
Definition: deform.c:710
const float(* BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]
#define BKE_MESH_OMP_LIMIT
Definition: BKE_mesh.h:52
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float(*vert_coords)[3])
Definition: mesh.cc:1834
const float(* BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]
void BKE_mesh_looptri_get_real_edges(const struct Mesh *mesh, const struct MLoopTri *looptri, int r_edges[3])
float(* BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3]
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.cc:94
struct Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval)
#define NULL_BVHTreeNearest
#define NULL_ShrinkwrapCalcData
struct DerivedMesh * subsurf_make_derived_from_derived(struct DerivedMesh *dm, struct SubsurfModifierData *smd, const struct Scene *scene, float(*vertCos)[3], SubsurfFlags flags)
Definition: subsurf_ccg.c:1902
@ SUBSURF_IN_EDIT_MODE
Definition: BKE_subsurf.h:39
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:64
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
#define BVH_RAYCAST_DIST_MAX
Definition: BLI_kdopbvh.h:89
int BLI_bvhtree_find_nearest_ex(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata, int flag)
Definition: BLI_kdopbvh.c:1567
@ BVH_NEAREST_OPTIMAL_ORDER
Definition: BLI_kdopbvh.h:82
int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1942
int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1616
#define M_SQRT2
Definition: BLI_math_base.h:29
MINLINE float signf(float f)
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
Definition: math_geom.c:3603
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:980
void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3])
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3])
float mat4_to_scale(const float M[4][4])
Definition: math_matrix.c:2185
void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3])
void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3])
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target)
bool BLI_newton3d_solve(Newton3D_DeltaFunc func_delta, Newton3D_JacobianFunc func_jacobian, Newton3D_CorrectionFunc func_correction, void *userdata, float epsilon, int max_iterations, bool trace, const float x_init[3], float result[3])
Solve a generic f(x) = 0 equation using Newton's method.
Definition: math_solvers.c:150
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
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 normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
Definition: math_vector.c:160
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_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
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v2_fl(float r[2], float f)
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
#define UNUSED(x)
#define UNPACK3(a)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ CD_MVERT
@ GP_SHRINKWRAP_INVERT_VGROUP
@ ME_CC_SUBSURF
@ ME_AUTOSMOOTH
@ ME_SMOOTH
#define MOD_SHRINKWRAP_CULL_TARGET_MASK
@ MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR
@ MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE
@ MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR
@ MOD_SHRINKWRAP_CULL_TARGET_BACKFACE
@ MOD_SHRINKWRAP_INVERT_VGROUP
@ MOD_SHRINKWRAP_INVERT_CULL_TARGET
@ MOD_SHRINKWRAP_TARGET_PROJECT
@ MOD_SHRINKWRAP_NEAREST_VERTEX
@ MOD_SHRINKWRAP_PROJECT
@ MOD_SHRINKWRAP_NEAREST_SURFACE
@ MOD_SHRINKWRAP_ON_SURFACE
@ MOD_SHRINKWRAP_OUTSIDE
@ MOD_SHRINKWRAP_INSIDE
@ MOD_SHRINKWRAP_ABOVE_SURFACE
@ MOD_SHRINKWRAP_OUTSIDE_SURFACE
@ MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS
@ MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS
@ MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS
@ MOD_SHRINKWRAP_PROJECT_OVER_NORMAL
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
_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 type
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
Utility defines for timing/benchmarks.
#define C
Definition: RandGen.cpp:25
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
static T sum(const btAlignedObjectArray< T > &items)
CCL_NAMESPACE_BEGIN struct Options options
Scene scene
const Depsgraph * depsgraph
void * tree
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
static double epsilon
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
struct ShrinkwrapCalcData ShrinkwrapCalcData
static void target_project_edge(const ShrinkwrapTreeData *tree, int index, const float co[3], BVHTreeNearest *nearest, int eidx)
Definition: shrinkwrap.c:933
static void target_project_tri_clamp(float x[3])
Definition: shrinkwrap.c:758
static bool target_project_solve_point_tri(const float *vtri_co[3], const float vtri_no[3][3], const float point_co[3], const float hit_co[3], float hit_dist_sq, float r_hit_co[3], float r_hit_no[3])
Definition: shrinkwrap.c:846
void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data)
Definition: shrinkwrap.c:147
static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
Definition: shrinkwrap.c:398
static ShrinkwrapBoundaryData * shrinkwrap_build_boundary_data(struct Mesh *mesh)
Definition: shrinkwrap.c:192
struct ShrinkwrapCalcCBData ShrinkwrapCalcCBData
static void mesh_looptri_target_project(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition: shrinkwrap.c:1009
void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree, BVHTreeNearest *nearest, float co[3], int type)
Definition: shrinkwrap.c:1066
void shrinkwrapGpencilModifier_deform(ShrinkwrapGpencilModifierData *mmd, Object *ob, MDeformVert *dvert, const int defgrp_index, float(*vertexCos)[3], int numVerts)
Definition: shrinkwrap.c:1476
static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
Definition: shrinkwrap.c:1345
static bool update_hit(BVHTreeNearest *nearest, int index, const float co[3], const float hit_co[3], const float hit_no[3])
Definition: shrinkwrap.c:908
static void shrinkwrap_snap_with_side(float r_point_co[3], const float point_co[3], const float hit_co[3], const float hit_no[3], float goal_dist, float forcesign, bool forcesnap)
Definition: shrinkwrap.c:1235
bool BKE_shrinkwrap_project_normal(char options, const float vert[3], const float dir[3], const float ray_radius, const SpaceTransform *transf, ShrinkwrapTreeData *tree, BVHTreeRayHit *hit)
Definition: shrinkwrap.c:419
static void target_project_tri_deviation(void *userdata, const float x[3], float r_delta[3])
Definition: shrinkwrap.c:732
static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata, signed char *status, int index, const float edge_dir[3], signed char side)
Definition: shrinkwrap.c:169
static void shrinkwrap_calc_nearest_vertex_cb_ex(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict tls)
Definition: shrinkwrap.c:336
struct TargetProjectTriData TargetProjectTriData
void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C, Object *ob_source, Object *ob_target)
Definition: shrinkwrap.c:1525
static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict tls)
Definition: shrinkwrap.c:494
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
Definition: shrinkwrap.c:1550
void BKE_shrinkwrap_compute_smooth_normal(const struct ShrinkwrapTreeData *tree, const struct SpaceTransform *transform, int looptri_idx, const float hit_co[3], const float hit_no[3], float r_no[3])
Definition: shrinkwrap.c:1170
#define TIMEIT_BENCH(expr, id)
Definition: shrinkwrap.c:51
bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
Definition: shrinkwrap.c:90
void BKE_shrinkwrap_compute_boundary_data(struct Mesh *mesh)
Definition: shrinkwrap.c:323
static void target_project_tri_jacobian(void *userdata, const float x[3], float r_jacobian[3][3])
Definition: shrinkwrap.c:745
bool BKE_shrinkwrap_init_tree(ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals)
Definition: shrinkwrap.c:97
void BKE_shrinkwrap_discard_boundary_data(struct Mesh *mesh)
Definition: shrinkwrap.c:152
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, const ModifierEvalContext *ctx, struct Scene *scene, Object *ob, Mesh *mesh, MDeformVert *dvert, const int defgrp_index, float(*vertexCos)[3], int numVerts)
Definition: shrinkwrap.c:1367
static bool target_project_tri_correct(void *UNUSED(userdata), const float x[3], float step[3], float x_next[3])
Definition: shrinkwrap.c:773
static void shrinkwrap_calc_nearest_surface_point_cb_ex(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict tls)
Definition: shrinkwrap.c:1101
static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
Definition: shrinkwrap.c:616
void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree, const struct SpaceTransform *transform, int mode, int hit_idx, const float hit_co[3], const float hit_no[3], float goal_dist, const float point_co[3], float r_point_co[3])
Definition: shrinkwrap.c:1288
unsigned int uint32_t
Definition: stdint.h:80
const struct MLoop * loop
Definition: BKE_bvhutils.h:61
struct BVHTree * tree
Definition: BKE_bvhutils.h:50
const struct MVert * vert
Definition: BKE_bvhutils.h:57
BVHTree_NearestPointCallback nearest_callback
Definition: BKE_bvhutils.h:53
const struct MLoopTri * looptri
Definition: BKE_bvhutils.h:62
float co[3]
Definition: BLI_kdopbvh.h:43
float no[3]
Definition: BLI_kdopbvh.h:46
float co[3]
Definition: BLI_kdopbvh.h:68
float no[3]
Definition: BLI_kdopbvh.h:70
void *(* getVertDataArray)(DerivedMesh *dm, int type)
int(* getNumVerts)(DerivedMesh *dm)
void(* release)(DerivedMesh *dm)
unsigned int poly
unsigned int tri[3]
unsigned int e
unsigned int v
float co[3]
struct ShrinkwrapBoundaryData * shrinkwrap_data
struct MEdge * medge
struct MVert * mvert
uint16_t flag
float remesh_voxel_size
int totedge
int totvert
struct MLoop * mloop
Mesh_Runtime runtime
int totpoly
int totloop
CustomData ldata
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
void * data
const int * vert_boundary_id
const ShrinkwrapBoundaryVertData * boundary_verts
const BLI_bitmap * looptri_has_boundary
const BLI_bitmap * edge_is_boundary
unsigned int num_boundary_verts
SpaceTransform * local2aux
Definition: shrinkwrap.c:87
ShrinkwrapTreeData * tree
Definition: shrinkwrap.c:83
ShrinkwrapCalcData * calc
Definition: shrinkwrap.c:81
ShrinkwrapTreeData * aux_tree
Definition: shrinkwrap.c:84
struct SpaceTransform local2target
Definition: shrinkwrap.c:72
float(* vertexCos)[3]
Definition: shrinkwrap.c:64
struct ShrinkwrapTreeData * tree
Definition: shrinkwrap.c:73
struct MVert * vert
Definition: shrinkwrap.c:62
struct Object * aux_target
Definition: shrinkwrap.c:75
ShrinkwrapModifierData * smd
Definition: shrinkwrap.c:58
struct MDeformVert * dvert
Definition: shrinkwrap.c:67
struct Mesh * target
Definition: shrinkwrap.c:71
const float(* vert_normals)[3]
Definition: shrinkwrap.c:63
struct Object * ob
Definition: shrinkwrap.c:60
struct ShrinkwrapTreeData * cache_data
const float ** vtri_co
Definition: shrinkwrap.c:720
const float * point_co
Definition: shrinkwrap.c:722
const float(* vtri_no)[3]
Definition: shrinkwrap.c:721
size_t userdata_chunk_size
Definition: BLI_task.h:169