Blender  V3.3
MOD_skin.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 /* Implementation based in part off the paper "B-Mesh: A Fast Modeling
8  * System for Base Meshes of 3D Articulated Shapes" (Zhongping Ji,
9  * Ligang Liu, Yigang Wang)
10  *
11  * Note that to avoid confusion with Blender's BMesh data structure,
12  * this tool is renamed as the Skin modifier.
13  *
14  * The B-Mesh paper is current available here:
15  * http://www.math.zju.edu.cn/ligangliu/CAGD/Projects/BMesh/
16  *
17  * The main missing features in this code compared to the paper are:
18  *
19  * + No mesh evolution. The paper suggests iteratively subsurfing the
20  * skin output and adapting the output to better conform with the
21  * spheres of influence surrounding each vertex.
22  *
23  * + No mesh fairing. The paper suggests re-aligning output edges to
24  * follow principal mesh curvatures.
25  *
26  * + No auxiliary balls. These would serve to influence mesh
27  * evolution, which as noted above is not implemented.
28  *
29  * The code also adds some features not present in the paper:
30  *
31  * + Loops in the input edge graph.
32  *
33  * + Concave surfaces around branch nodes. The paper does not discuss
34  * how to handle non-convex regions; this code adds a number of
35  * cleanup operations to handle many (though not all) of these
36  * cases.
37  */
38 
39 #include "MEM_guardedalloc.h"
40 
41 #include "BLI_utildefines.h"
42 
43 #include "BLI_array.h"
44 #include "BLI_bitmap.h"
45 #include "BLI_heap_simple.h"
46 #include "BLI_math.h"
47 #include "BLI_math_geom.h"
48 #include "BLI_stack.h"
49 
50 #include "BLT_translation.h"
51 
52 #include "DNA_defaults.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_modifier_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_screen_types.h"
58 
59 #include "BKE_context.h"
60 #include "BKE_deform.h"
61 #include "BKE_lib_id.h"
62 #include "BKE_mesh.h"
63 #include "BKE_mesh_mapping.h"
64 #include "BKE_modifier.h"
65 #include "BKE_screen.h"
66 
67 #include "UI_interface.h"
68 #include "UI_resources.h"
69 
70 #include "RNA_access.h"
71 #include "RNA_prototypes.h"
72 
73 #include "WM_types.h" /* For skin mark clear operator UI. */
74 
75 #include "MOD_modifiertypes.h"
76 #include "MOD_ui_common.h"
77 
78 #include "bmesh.h"
79 
80 /* -------------------------------------------------------------------- */
85 {
86  BMIter iter;
87  BMFace *f;
88  BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
89  f->no[0] = FLT_MAX;
90  }
91 }
92 
94 {
95  BMIter iter;
96  BMFace *f;
97  BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
98  if (f->no[0] == FLT_MAX) {
100  }
101  }
102 }
103 
107 static void vert_array_face_normal_update(BMVert **verts, int verts_len)
108 {
109  for (int i = 0; i < verts_len; i++) {
111  }
112 
113  for (int i = 0; i < verts_len; i++) {
115  }
116 }
117 
120 typedef struct {
121  float mat[3][3];
122  /* Vert that edge is pointing away from, no relation to
123  * MEdge.v1 */
124  int origin;
125 } EMat;
126 
127 typedef enum {
129  CAP_END = 2,
132 } SkinNodeFlag;
133 
134 typedef struct Frame {
135  /* Index in the MVert array */
137  /* Location of each corner */
138  float co[4][3];
139  /* Indicates which corners have been merged with another
140  * frame's corner (so they share an MVert index) */
141  struct {
142  /* Merge to target frame/corner (no merge if frame is null) */
143  struct Frame *frame;
144  int corner;
145  /* checked to avoid chaining.
146  * (merging when we're already been referenced), see T39775 */
148  } merge[4];
149 
150  /* For hull frames, whether each vertex is detached or not */
151  bool inside_hull[4];
152  /* Whether any part of the frame (corner or edge) is detached */
153  bool detached;
154 } Frame;
155 
156 #define MAX_SKIN_NODE_FRAMES 2
157 typedef struct {
159  int totframe;
160 
162 
163  /* Used for hulling a loop seam */
164  int seam_edges[2];
165 } SkinNode;
166 
167 typedef struct {
170  int mat_nr;
171 } SkinOutput;
172 
173 static void add_poly(SkinOutput *so, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4);
174 
175 /***************************** Convex Hull ****************************/
176 
177 static bool is_quad_symmetric(BMVert *quad[4], const SkinModifierData *smd)
178 {
179  const float threshold = 0.0001f;
180  const float threshold_squared = threshold * threshold;
181  int axis;
182 
183  for (axis = 0; axis < 3; axis++) {
184  if (smd->symmetry_axes & (1 << axis)) {
185  float a[3];
186 
187  copy_v3_v3(a, quad[0]->co);
188  a[axis] = -a[axis];
189 
190  if (len_squared_v3v3(a, quad[1]->co) < threshold_squared) {
191  copy_v3_v3(a, quad[2]->co);
192  a[axis] = -a[axis];
193  if (len_squared_v3v3(a, quad[3]->co) < threshold_squared) {
194  return 1;
195  }
196  }
197  else if (len_squared_v3v3(a, quad[3]->co) < threshold_squared) {
198  copy_v3_v3(a, quad[2]->co);
199  a[axis] = -a[axis];
200  if (len_squared_v3v3(a, quad[1]->co) < threshold_squared) {
201  return 1;
202  }
203  }
204  }
205  }
206 
207  return 0;
208 }
209 
210 /* Returns true if the quad crosses the plane of symmetry, false otherwise */
212 {
213  int axis;
214 
215  for (axis = 0; axis < 3; axis++) {
216  if (smd->symmetry_axes & (1 << axis)) {
217  bool left = false, right = false;
218  int i;
219 
220  for (i = 0; i < 4; i++) {
221  if (quad[i]->co[axis] < 0.0f) {
222  left = true;
223  }
224  else if (quad[i]->co[axis] > 0.0f) {
225  right = true;
226  }
227 
228  if (left && right) {
229  return true;
230  }
231  }
232  }
233  }
234 
235  return false;
236 }
237 
238 /* Returns true if the frame is filled by precisely two faces (and
239  * outputs those faces to fill_faces), otherwise returns false. */
240 static bool skin_frame_find_contained_faces(const Frame *frame, BMFace *fill_faces[2])
241 {
242  BMEdge *diag;
243 
244  /* See if the frame is bisected by a diagonal edge */
245  diag = BM_edge_exists(frame->verts[0], frame->verts[2]);
246  if (!diag) {
247  diag = BM_edge_exists(frame->verts[1], frame->verts[3]);
248  }
249 
250  if (diag) {
251  return BM_edge_face_pair(diag, &fill_faces[0], &fill_faces[1]);
252  }
253 
254  return false;
255 }
256 
257 /* Returns true if hull is successfully built, false otherwise */
258 static bool build_hull(SkinOutput *so, Frame **frames, int totframe)
259 {
260 #ifdef WITH_BULLET
261  BMesh *bm = so->bm;
262  BMOperator op;
263  BMIter iter;
264  BMOIter oiter;
265  BMVert *v;
266  BMFace *f;
267  BMEdge *e;
268  int i, j;
269 
271 
272  for (i = 0; i < totframe; i++) {
273  for (j = 0; j < 4; j++) {
274  BM_elem_flag_enable(frames[i]->verts[j], BM_ELEM_TAG);
275  }
276  }
277 
278  /* Deselect all faces so that only new hull output faces are
279  * selected after the operator is run */
281 
282  BMO_op_initf(
283  bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "convex_hull input=%hv", BM_ELEM_TAG);
284  BMO_op_exec(bm, &op);
285 
287  BMO_op_finish(bm, &op);
288  return false;
289  }
290 
291  /* Apply face attributes to hull output */
292  BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) {
294  if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) {
296  }
297  f->mat_nr = so->mat_nr;
298  }
299 
300  /* Mark interior frames */
301  BMO_ITER (v, &oiter, op.slots_out, "geom_interior.out", BM_VERT) {
302  for (i = 0; i < totframe; i++) {
303  Frame *frame = frames[i];
304 
305  if (!frame->detached) {
306  for (j = 0; j < 4; j++) {
307  if (frame->verts[j] == v) {
308  frame->inside_hull[j] = true;
309  frame->detached = true;
310  break;
311  }
312  }
313  }
314  }
315  }
316 
317  /* Also mark frames as interior if an edge is not in the hull */
318  for (i = 0; i < totframe; i++) {
319  Frame *frame = frames[i];
320 
321  if (!frame->detached && (!BM_edge_exists(frame->verts[0], frame->verts[1]) ||
322  !BM_edge_exists(frame->verts[1], frame->verts[2]) ||
323  !BM_edge_exists(frame->verts[2], frame->verts[3]) ||
324  !BM_edge_exists(frame->verts[3], frame->verts[0]))) {
325  frame->detached = true;
326  }
327  }
328 
329  /* Remove triangles that would fill the original frames -- skip if
330  * frame is partially detached */
332  for (i = 0; i < totframe; i++) {
333  Frame *frame = frames[i];
334  if (!frame->detached) {
335  BMFace *fill_faces[2];
336 
337  /* Check if the frame is filled by precisely two
338  * triangles. If so, delete the triangles and their shared
339  * edge. Otherwise, give up and mark the frame as
340  * detached. */
341  if (skin_frame_find_contained_faces(frame, fill_faces)) {
342  BM_elem_flag_enable(fill_faces[0], BM_ELEM_TAG);
343  BM_elem_flag_enable(fill_faces[1], BM_ELEM_TAG);
344  }
345  else {
346  frame->detached = true;
347  }
348  }
349  }
350 
351  /* Check if removing triangles above will create wire triangles,
352  * mark them too */
353  BMO_ITER (e, &oiter, op.slots_out, "geom.out", BM_EDGE) {
354  bool is_wire = true;
355  BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
356  if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
357  is_wire = false;
358  break;
359  }
360  }
361  if (is_wire) {
363  }
364  }
365 
366  BMO_op_finish(bm, &op);
367 
369 
370  return true;
371 #else
372  UNUSED_VARS(so, frames, totframe, skin_frame_find_contained_faces);
373  return false;
374 #endif
375 }
376 
377 /* Returns the average frame side length (frames are rectangular, so
378  * just the average of two adjacent edge lengths) */
379 static float frame_len(const Frame *frame)
380 {
381  return (len_v3v3(frame->co[0], frame->co[1]) + len_v3v3(frame->co[1], frame->co[2])) * 0.5f;
382 }
383 
384 static void merge_frame_corners(Frame **frames, int totframe)
385 {
386  float dist, side_a, side_b, thresh, mid[3];
387  int i, j, k, l;
388 
389  for (i = 0; i < totframe; i++) {
390  side_a = frame_len(frames[i]);
391 
392  /* For each corner of each frame... */
393  for (j = 0; j < 4; j++) {
394 
395  /* Ensure the merge target is not itself a merge target */
396  if (frames[i]->merge[j].frame) {
397  continue;
398  }
399 
400  for (k = i + 1; k < totframe; k++) {
401  BLI_assert(frames[i] != frames[k]);
402 
403  side_b = frame_len(frames[k]);
404  thresh = min_ff(side_a, side_b) / 2.0f;
405 
406  /* Compare with each corner of all other frames... */
407  for (l = 0; l < 4; l++) {
408  if (frames[k]->merge[l].frame || frames[k]->merge[l].is_target) {
409  continue;
410  }
411 
412  /* Some additional concerns that could be checked
413  * further:
414  *
415  * + Vertex coords are being used for the
416  * edge-length test, but are also being
417  * modified, might cause symmetry problems.
418  *
419  * + A frame could be merged diagonally across
420  * another, would generate a weird (bad) T
421  * junction
422  */
423 
424  /* Check if corners are near each other, where
425  * 'near' is based in the frames' minimum side
426  * length */
427  dist = len_v3v3(frames[i]->co[j], frames[k]->co[l]);
428  if (dist < thresh) {
429  mid_v3_v3v3(mid, frames[i]->co[j], frames[k]->co[l]);
430 
431  copy_v3_v3(frames[i]->co[j], mid);
432  copy_v3_v3(frames[k]->co[l], mid);
433 
434  frames[k]->merge[l].frame = frames[i];
435  frames[k]->merge[l].corner = j;
436  frames[i]->merge[j].is_target = true;
437 
438  /* Can't merge another corner into the same
439  * frame corner, so move on to frame k+1 */
440  break;
441  }
442  }
443  }
444  }
445  }
446 }
447 
449  int v, SkinNode *frames, const MeshElemMap *emap, const MEdge *medge, int *tothullframe)
450 {
451  SkinNode *f;
452  Frame **hull_frames;
453  int hull_frames_num, i;
454 
455  (*tothullframe) = emap[v].count;
456  hull_frames = MEM_calloc_arrayN(
457  (*tothullframe), sizeof(Frame *), "hull_from_frames.hull_frames");
458  hull_frames_num = 0;
459  for (i = 0; i < emap[v].count; i++) {
460  const MEdge *e = &medge[emap[v].indices[i]];
461  f = &frames[BKE_mesh_edge_other_vert(e, v)];
462  /* Can't have adjacent branch nodes yet */
463  if (f->totframe) {
464  hull_frames[hull_frames_num++] = &f->frames[0];
465  }
466  else {
467  (*tothullframe)--;
468  }
469  }
470 
471  return hull_frames;
472 }
473 
474 /**************************** Create Frames ***************************/
475 
476 static void node_frames_init(SkinNode *nf, int totframe)
477 {
478  int i;
479 
480  nf->totframe = totframe;
481  memset(nf->frames, 0, sizeof(nf->frames));
482 
483  nf->flag = 0;
484  for (i = 0; i < 2; i++) {
485  nf->seam_edges[i] = -1;
486  }
487 }
488 
489 static void create_frame(
490  Frame *frame, const float co[3], const float radius[2], const float mat[3][3], float offset)
491 {
492  float rx[3], ry[3], rz[3];
493  int i;
494 
495  mul_v3_v3fl(ry, mat[1], radius[0]);
496  mul_v3_v3fl(rz, mat[2], radius[1]);
497 
498  add_v3_v3v3(frame->co[3], co, ry);
499  add_v3_v3v3(frame->co[3], frame->co[3], rz);
500 
501  sub_v3_v3v3(frame->co[2], co, ry);
502  add_v3_v3v3(frame->co[2], frame->co[2], rz);
503 
504  sub_v3_v3v3(frame->co[1], co, ry);
505  sub_v3_v3v3(frame->co[1], frame->co[1], rz);
506 
507  add_v3_v3v3(frame->co[0], co, ry);
508  sub_v3_v3v3(frame->co[0], frame->co[0], rz);
509 
510  mul_v3_v3fl(rx, mat[0], offset);
511  for (i = 0; i < 4; i++) {
512  add_v3_v3v3(frame->co[i], frame->co[i], rx);
513  }
514 }
515 
516 static float half_v2(const float v[2])
517 {
518  return (v[0] + v[1]) * 0.5f;
519 }
520 
521 static void end_node_frames(int v,
522  SkinNode *skin_nodes,
523  const MVert *mvert,
524  const MVertSkin *nodes,
525  const MeshElemMap *emap,
526  EMat *emat)
527 {
528  const float *rad = nodes[v].radius;
529  float mat[3][3];
530 
531  if (emap[v].count == 0) {
532  float avg = half_v2(rad);
533 
534  /* For solitary nodes, just build a box (two frames) */
535  node_frames_init(&skin_nodes[v], 2);
536  skin_nodes[v].flag |= (CAP_START | CAP_END);
537 
538  /* Hardcoded basis */
539  zero_m3(mat);
540  mat[0][2] = mat[1][0] = mat[2][1] = 1;
541 
542  /* Caps */
543  create_frame(&skin_nodes[v].frames[0], mvert[v].co, rad, mat, avg);
544  create_frame(&skin_nodes[v].frames[1], mvert[v].co, rad, mat, -avg);
545  }
546  else {
547  /* For nodes with an incoming edge, create a single (capped) frame */
548  node_frames_init(&skin_nodes[v], 1);
549  skin_nodes[v].flag |= CAP_START;
550 
551  /* Use incoming edge for orientation */
552  copy_m3_m3(mat, emat[emap[v].indices[0]].mat);
553  if (emat[emap[v].indices[0]].origin != v) {
554  negate_v3(mat[0]);
555  }
556 
557  Frame *frame = &skin_nodes[v].frames[0];
558 
559  /* End frame */
560  create_frame(frame, mvert[v].co, rad, mat, 0);
561 
562  /* The caps might need to have their normals inverted. So check if they
563  * need to be flipped when creating faces. */
564  float normal[3];
565  normal_quad_v3(normal, frame->co[0], frame->co[1], frame->co[2], frame->co[3]);
566  if (dot_v3v3(mat[0], normal) < 0.0f) {
567  skin_nodes[v].flag |= FLIP_NORMAL;
568  }
569  }
570 }
571 
572 /* Returns 1 for seam, 0 otherwise */
573 static int connection_node_mat(float mat[3][3], int v, const MeshElemMap *emap, EMat *emat)
574 {
575  float axis[3], angle, ine[3][3], oute[3][3];
576  EMat *e1, *e2;
577 
578  e1 = &emat[emap[v].indices[0]];
579  e2 = &emat[emap[v].indices[1]];
580 
581  if (e1->origin != v && e2->origin == v) {
582  copy_m3_m3(ine, e1->mat);
583  copy_m3_m3(oute, e2->mat);
584  }
585  else if (e1->origin == v && e2->origin != v) {
586  copy_m3_m3(ine, e2->mat);
587  copy_m3_m3(oute, e1->mat);
588  }
589  else {
590  return 1;
591  }
592 
593  /* Get axis and angle to rotate frame by */
594  angle = angle_normalized_v3v3(ine[0], oute[0]) / 2.0f;
595  cross_v3_v3v3(axis, ine[0], oute[0]);
596  normalize_v3(axis);
597 
598  /* Build frame matrix (don't care about X axis here) */
599  copy_v3_v3(mat[0], ine[0]);
600  rotate_normalized_v3_v3v3fl(mat[1], ine[1], axis, angle);
601  rotate_normalized_v3_v3v3fl(mat[2], ine[2], axis, angle);
602 
603  return 0;
604 }
605 
606 static void connection_node_frames(int v,
607  SkinNode *skin_nodes,
608  const MVert *mvert,
609  const MVertSkin *nodes,
610  const MeshElemMap *emap,
611  EMat *emat)
612 {
613  const float *rad = nodes[v].radius;
614  float mat[3][3];
615  EMat *e1, *e2;
616 
617  if (connection_node_mat(mat, v, emap, emat)) {
618  float avg = half_v2(rad);
619 
620  /* Get edges */
621  e1 = &emat[emap[v].indices[0]];
622  e2 = &emat[emap[v].indices[1]];
623 
624  /* Handle seam separately to avoid twisting */
625  /* Create two frames, will be hulled to neighbors later */
626  node_frames_init(&skin_nodes[v], 2);
627  skin_nodes[v].flag |= SEAM_FRAME;
628 
629  copy_m3_m3(mat, e1->mat);
630  if (e1->origin != v) {
631  negate_v3(mat[0]);
632  }
633  create_frame(&skin_nodes[v].frames[0], mvert[v].co, rad, mat, avg);
634  skin_nodes[v].seam_edges[0] = emap[v].indices[0];
635 
636  copy_m3_m3(mat, e2->mat);
637  if (e2->origin != v) {
638  negate_v3(mat[0]);
639  }
640  create_frame(&skin_nodes[v].frames[1], mvert[v].co, rad, mat, avg);
641  skin_nodes[v].seam_edges[1] = emap[v].indices[1];
642 
643  return;
644  }
645 
646  /* Build regular frame */
647  node_frames_init(&skin_nodes[v], 1);
648  create_frame(&skin_nodes[v].frames[0], mvert[v].co, rad, mat, 0);
649 }
650 
652  const MVert *mvert, int verts_num, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat)
653 {
654  SkinNode *skin_nodes;
655  int v;
656 
657  skin_nodes = MEM_calloc_arrayN(verts_num, sizeof(SkinNode), "build_frames.skin_nodes");
658 
659  for (v = 0; v < verts_num; v++) {
660  if (emap[v].count <= 1) {
661  end_node_frames(v, skin_nodes, mvert, nodes, emap, emat);
662  }
663  else if (emap[v].count == 2) {
664  connection_node_frames(v, skin_nodes, mvert, nodes, emap, emat);
665  }
666  else {
667  /* Branch node generates no frames */
668  }
669  }
670 
671  return skin_nodes;
672 }
673 
674 /**************************** Edge Matrices ***************************/
675 
676 static void calc_edge_mat(float mat[3][3], const float a[3], const float b[3])
677 {
678  const float z_up[3] = {0, 0, 1};
679  float dot;
680 
681  /* X = edge direction */
682  sub_v3_v3v3(mat[0], b, a);
683  normalize_v3(mat[0]);
684 
685  dot = dot_v3v3(mat[0], z_up);
686  if (dot > -1 + FLT_EPSILON && dot < 1 - FLT_EPSILON) {
687  /* Y = Z cross x */
688  cross_v3_v3v3(mat[1], z_up, mat[0]);
689  normalize_v3(mat[1]);
690 
691  /* Z = x cross y */
692  cross_v3_v3v3(mat[2], mat[0], mat[1]);
693  normalize_v3(mat[2]);
694  }
695  else {
696  mat[1][0] = 1;
697  mat[1][1] = 0;
698  mat[1][2] = 0;
699  mat[2][0] = 0;
700  mat[2][1] = 1;
701  mat[2][2] = 0;
702  }
703 }
704 
705 typedef struct {
706  float mat[3][3];
707  int parent_v;
708  int e;
709 } EdgeStackElem;
710 
711 static void build_emats_stack(BLI_Stack *stack,
712  BLI_bitmap *visited_e,
713  EMat *emat,
714  const MeshElemMap *emap,
715  const MEdge *medge,
716  const MVertSkin *vs,
717  const MVert *mvert)
718 {
719  EdgeStackElem stack_elem;
720  float axis[3], angle;
721  int i, e, v, parent_v, parent_is_branch;
722 
723  BLI_stack_pop(stack, &stack_elem);
724  parent_v = stack_elem.parent_v;
725  e = stack_elem.e;
726 
727  /* Skip if edge already visited */
728  if (BLI_BITMAP_TEST(visited_e, e)) {
729  return;
730  }
731 
732  /* Mark edge as visited */
733  BLI_BITMAP_ENABLE(visited_e, e);
734 
735  /* Process edge */
736 
737  parent_is_branch = ((emap[parent_v].count > 2) || (vs[parent_v].flag & MVERT_SKIN_ROOT));
738 
739  v = BKE_mesh_edge_other_vert(&medge[e], parent_v);
740  emat[e].origin = parent_v;
741 
742  /* If parent is a branch node, start a new edge chain */
743  if (parent_is_branch) {
744  calc_edge_mat(emat[e].mat, mvert[parent_v].co, mvert[v].co);
745  }
746  else {
747  /* Build edge matrix guided by parent matrix */
748  sub_v3_v3v3(emat[e].mat[0], mvert[v].co, mvert[parent_v].co);
749  normalize_v3(emat[e].mat[0]);
750  angle = angle_normalized_v3v3(stack_elem.mat[0], emat[e].mat[0]);
751  cross_v3_v3v3(axis, stack_elem.mat[0], emat[e].mat[0]);
752  normalize_v3(axis);
753  rotate_normalized_v3_v3v3fl(emat[e].mat[1], stack_elem.mat[1], axis, angle);
754  rotate_normalized_v3_v3v3fl(emat[e].mat[2], stack_elem.mat[2], axis, angle);
755  }
756 
757  /* Add neighbors to stack */
758  for (i = 0; i < emap[v].count; i++) {
759  /* Add neighbors to stack */
760  copy_m3_m3(stack_elem.mat, emat[e].mat);
761  stack_elem.e = emap[v].indices[i];
762  stack_elem.parent_v = v;
763  BLI_stack_push(stack, &stack_elem);
764  }
765 }
766 
767 static EMat *build_edge_mats(const MVertSkin *vs,
768  const MVert *mvert,
769  const int verts_num,
770  const MEdge *medge,
771  const MeshElemMap *emap,
772  const int edges_num,
773  bool *has_valid_root)
774 {
775  BLI_Stack *stack;
776  EMat *emat;
777  EdgeStackElem stack_elem;
778  BLI_bitmap *visited_e;
779  int i, v;
780 
781  stack = BLI_stack_new(sizeof(stack_elem), "build_edge_mats.stack");
782 
783  visited_e = BLI_BITMAP_NEW(edges_num, "build_edge_mats.visited_e");
784  emat = MEM_calloc_arrayN(edges_num, sizeof(EMat), "build_edge_mats.emat");
785 
786  /* Edge matrices are built from the root nodes, add all roots with
787  * children to the stack */
788  for (v = 0; v < verts_num; v++) {
789  if (vs[v].flag & MVERT_SKIN_ROOT) {
790  if (emap[v].count >= 1) {
791  const MEdge *e = &medge[emap[v].indices[0]];
792  calc_edge_mat(stack_elem.mat, mvert[v].co, mvert[BKE_mesh_edge_other_vert(e, v)].co);
793  stack_elem.parent_v = v;
794 
795  /* Add adjacent edges to stack */
796  for (i = 0; i < emap[v].count; i++) {
797  stack_elem.e = emap[v].indices[i];
798  BLI_stack_push(stack, &stack_elem);
799  }
800 
801  *has_valid_root = true;
802  }
803  else if (edges_num == 0) {
804  /* Vertex-only mesh is valid, mark valid root as well (will display error otherwise). */
805  *has_valid_root = true;
806  break;
807  }
808  }
809  }
810 
811  while (!BLI_stack_is_empty(stack)) {
812  build_emats_stack(stack, visited_e, emat, emap, medge, vs, mvert);
813  }
814 
815  MEM_freeN(visited_e);
816  BLI_stack_free(stack);
817 
818  return emat;
819 }
820 
821 /************************** Input Subdivision *************************/
822 
823 /* Returns number of edge subdivisions, taking into account the radius
824  * of the endpoints and the edge length. If both endpoints are branch
825  * nodes, at least two intermediate frames are required. (This avoids
826  * having any special cases for dealing with sharing a frame between
827  * two hulls.) */
828 static int calc_edge_subdivisions(const MVert *mvert,
829  const MVertSkin *nodes,
830  const MEdge *e,
831  const int *degree)
832 {
833  /* prevent memory errors T38003. */
834 #define NUM_SUBDIVISIONS_MAX 128
835 
836  const MVertSkin *evs[2] = {&nodes[e->v1], &nodes[e->v2]};
837  float avg_radius;
838  const bool v1_branch = degree[e->v1] > 2;
839  const bool v2_branch = degree[e->v2] > 2;
840  int subdivisions_num;
841 
842  /* If either end is a branch node marked 'loose', don't subdivide
843  * the edge (or subdivide just twice if both are branches) */
844  if ((v1_branch && (evs[0]->flag & MVERT_SKIN_LOOSE)) ||
845  (v2_branch && (evs[1]->flag & MVERT_SKIN_LOOSE))) {
846  if (v1_branch && v2_branch) {
847  return 2;
848  }
849 
850  return 0;
851  }
852 
853  avg_radius = half_v2(evs[0]->radius) + half_v2(evs[1]->radius);
854 
855  if (avg_radius != 0.0f) {
856  /* possible (but unlikely) that we overflow INT_MAX */
857  float subdivisions_num_fl;
858  const float edge_len = len_v3v3(mvert[e->v1].co, mvert[e->v2].co);
859  subdivisions_num_fl = (edge_len / avg_radius);
860  if (subdivisions_num_fl < NUM_SUBDIVISIONS_MAX) {
861  subdivisions_num = (int)subdivisions_num_fl;
862  }
863  else {
864  subdivisions_num = NUM_SUBDIVISIONS_MAX;
865  }
866  }
867  else {
868  subdivisions_num = 0;
869  }
870 
871  /* If both ends are branch nodes, two intermediate nodes are
872  * required */
873  if (subdivisions_num < 2 && v1_branch && v2_branch) {
874  subdivisions_num = 2;
875  }
876 
877  return subdivisions_num;
878 
879 #undef NUM_SUBDIVISIONS_MAX
880 }
881 
882 /* Take a Mesh and subdivide its edges to keep skin nodes
883  * reasonably close. */
884 static Mesh *subdivide_base(const Mesh *orig)
885 {
886  const MEdge *e;
887  int subd_num;
888  int i, j, k, u, v;
889  float radrat;
890 
891  const MVertSkin *orignode = CustomData_get_layer(&orig->vdata, CD_MVERT_SKIN);
892  const MVert *origvert = orig->mvert;
893  const MEdge *origedge = orig->medge;
894  const MDeformVert *origdvert = orig->dvert;
895  int orig_vert_num = orig->totvert;
896  int orig_edge_num = orig->totedge;
897 
898  /* Get degree of all vertices */
899  int *degree = MEM_calloc_arrayN(orig_vert_num, sizeof(int), "degree");
900  for (i = 0; i < orig_edge_num; i++) {
901  degree[origedge[i].v1]++;
902  degree[origedge[i].v2]++;
903  }
904 
905  /* Per edge, store how many subdivisions are needed */
906  int *edge_subd = MEM_calloc_arrayN((uint)orig_edge_num, sizeof(int), "edge_subd");
907  for (i = 0, subd_num = 0; i < orig_edge_num; i++) {
908  edge_subd[i] += calc_edge_subdivisions(origvert, orignode, &origedge[i], degree);
909  BLI_assert(edge_subd[i] >= 0);
910  subd_num += edge_subd[i];
911  }
912 
913  MEM_freeN(degree);
914 
915  /* Allocate output mesh */
917  orig, orig_vert_num + subd_num, orig_edge_num + subd_num, 0, 0, 0);
918 
919  MVert *outvert = result->mvert;
920  MEdge *outedge = result->medge;
921  MVertSkin *outnode = CustomData_get_layer(&result->vdata, CD_MVERT_SKIN);
922  MDeformVert *outdvert = result->dvert;
923 
924  /* Copy original vertex data */
925  CustomData_copy_data(&orig->vdata, &result->vdata, 0, 0, orig_vert_num);
926 
927  /* Subdivide edges */
928  for (i = 0, v = orig_vert_num; i < orig_edge_num; i++) {
929  struct {
930  /* Vertex group number */
931  int def_nr;
932  float w1, w2;
933  } *vgroups = NULL, *vg;
934  int vgroups_num = 0;
935 
936  e = &origedge[i];
937 
938  if (origdvert) {
939  const MDeformVert *dv1 = &origdvert[e->v1];
940  const MDeformVert *dv2 = &origdvert[e->v2];
941  vgroups = MEM_calloc_arrayN(dv1->totweight, sizeof(*vgroups), "vgroup");
942 
943  /* Only want vertex groups used by both vertices */
944  for (j = 0; j < dv1->totweight; j++) {
945  vg = NULL;
946  for (k = 0; k < dv2->totweight; k++) {
947  if (dv1->dw[j].def_nr == dv2->dw[k].def_nr) {
948  vg = &vgroups[vgroups_num];
949  vgroups_num++;
950  break;
951  }
952  }
953 
954  if (vg) {
955  vg->def_nr = dv1->dw[j].def_nr;
956  vg->w1 = dv1->dw[j].weight;
957  vg->w2 = dv2->dw[k].weight;
958  }
959  }
960  }
961 
962  u = e->v1;
963  radrat = (half_v2(outnode[e->v2].radius) / half_v2(outnode[e->v1].radius));
964  if (isfinite(radrat)) {
965  radrat = (radrat + 1) / 2;
966  }
967  else {
968  /* Happens when skin is scaled to zero. */
969  radrat = 1.0f;
970  }
971 
972  /* Add vertices and edge segments */
973  for (j = 0; j < edge_subd[i]; j++, v++, outedge++) {
974  float r = (j + 1) / (float)(edge_subd[i] + 1);
975  float t = powf(r, radrat);
976 
977  /* Interpolate vertex coord */
978  interp_v3_v3v3(outvert[v].co, outvert[e->v1].co, outvert[e->v2].co, t);
979 
980  /* Interpolate skin radii */
981  interp_v3_v3v3(outnode[v].radius, orignode[e->v1].radius, orignode[e->v2].radius, t);
982 
983  /* Interpolate vertex group weights */
984  for (k = 0; k < vgroups_num; k++) {
985  float weight;
986 
987  vg = &vgroups[k];
988  weight = interpf(vg->w2, vg->w1, t);
989 
990  if (weight > 0) {
991  BKE_defvert_add_index_notest(&outdvert[v], vg->def_nr, weight);
992  }
993  }
994 
995  outedge->v1 = u;
996  outedge->v2 = v;
997  u = v;
998  }
999 
1000  if (vgroups) {
1001  MEM_freeN(vgroups);
1002  }
1003 
1004  /* Link up to final vertex */
1005  outedge->v1 = u;
1006  outedge->v2 = e->v2;
1007  outedge++;
1008  }
1009 
1010  MEM_freeN(edge_subd);
1011 
1012  return result;
1013 }
1014 
1015 /******************************* Output *******************************/
1016 
1017 /* Can be either quad or triangle */
1018 static void add_poly(SkinOutput *so, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4)
1019 {
1020  BMVert *verts[4] = {v1, v2, v3, v4};
1021  BMFace *f;
1022 
1023  BLI_assert(!ELEM(v1, v2, v3, v4));
1024  BLI_assert(!ELEM(v2, v3, v4));
1025  BLI_assert(v3 != v4);
1026  BLI_assert(v1 && v2 && v3);
1027 
1028  f = BM_face_create_verts(so->bm, verts, v4 ? 4 : 3, NULL, BM_CREATE_NO_DOUBLE, true);
1030  if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) {
1032  }
1033  f->mat_nr = so->mat_nr;
1034 }
1035 
1036 static void connect_frames(SkinOutput *so, BMVert *frame1[4], BMVert *frame2[4])
1037 {
1038  BMVert *q[4][4] = {
1039  {frame2[0], frame2[1], frame1[1], frame1[0]},
1040  {frame2[1], frame2[2], frame1[2], frame1[1]},
1041  {frame2[2], frame2[3], frame1[3], frame1[2]},
1042  {frame2[3], frame2[0], frame1[0], frame1[3]},
1043  };
1044  int i;
1045  bool swap;
1046 
1047  /* Check if frame normals need swap */
1048 #if 0
1049  {
1050  /* simple method, works mostly */
1051  float p[3], no[3];
1052  sub_v3_v3v3(p, q[3][0]->co, q[0][0]->co);
1053  normal_quad_v3(no, q[0][0]->co, q[0][1]->co, q[0][2]->co, q[0][3]->co);
1054  swap = dot_v3v3(no, p) > 0;
1055  }
1056 #else
1057  {
1058  /* comprehensive method, accumulate flipping of all faces */
1059  float cent_sides[4][3];
1060  float cent[3];
1061  float dot = 0.0f;
1062 
1063  for (i = 0; i < 4; i++) {
1064  mid_v3_v3v3v3v3(cent_sides[i], UNPACK4_EX(, q[i], ->co));
1065  }
1066  mid_v3_v3v3v3v3(cent, UNPACK4(cent_sides));
1067 
1068  for (i = 0; i < 4; i++) {
1069  float p[3], no[3];
1070  normal_quad_v3(no, UNPACK4_EX(, q[i], ->co));
1071  sub_v3_v3v3(p, cent, cent_sides[i]);
1072  dot += dot_v3v3(no, p);
1073  }
1074 
1075  swap = dot > 0;
1076  }
1077 #endif
1078 
1079  for (i = 0; i < 4; i++) {
1080  if (swap) {
1081  add_poly(so, q[i][3], q[i][2], q[i][1], q[i][0]);
1082  }
1083  else {
1084  add_poly(so, q[i][0], q[i][1], q[i][2], q[i][3]);
1085  }
1086  }
1087 }
1088 
1089 static void output_frames(BMesh *bm, SkinNode *sn, const MDeformVert *input_dvert)
1090 {
1091  Frame *f;
1092  int i, j;
1093 
1094  /* Output all frame verts */
1095  for (i = 0; i < sn->totframe; i++) {
1096  f = &sn->frames[i];
1097  for (j = 0; j < 4; j++) {
1098  if (!f->merge[j].frame) {
1099  BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL, BM_CREATE_NOP);
1100 
1101  if (input_dvert) {
1102  MDeformVert *dv;
1104 
1105  BLI_assert(dv->totweight == 0);
1106  BKE_defvert_copy(dv, input_dvert);
1107  }
1108  }
1109  }
1110  }
1111 }
1112 
1113 #define PRINT_HOLE_INFO 0
1114 
1115 static void calc_frame_center(float center[3], const Frame *frame)
1116 {
1117  add_v3_v3v3(center, frame->verts[0]->co, frame->verts[1]->co);
1118  add_v3_v3(center, frame->verts[2]->co);
1119  add_v3_v3(center, frame->verts[3]->co);
1120  mul_v3_fl(center, 0.25f);
1121 }
1122 
1123 /* Does crappy fan triangulation of poly, may not be so accurate for
1124  * concave faces */
1125 static int isect_ray_poly(const float ray_start[3],
1126  const float ray_dir[3],
1127  BMFace *f,
1128  float *r_lambda)
1129 {
1130  BMVert *v, *v_first = NULL, *v_prev = NULL;
1131  BMIter iter;
1132  float best_dist = FLT_MAX;
1133  bool hit = false;
1134 
1135  BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) {
1136  if (!v_first) {
1137  v_first = v;
1138  }
1139  else if (v_prev != v_first) {
1140  float dist;
1141  bool curhit;
1142 
1143  curhit = isect_ray_tri_v3(ray_start, ray_dir, v_first->co, v_prev->co, v->co, &dist, NULL);
1144  if (curhit && dist < best_dist) {
1145  hit = true;
1146  best_dist = dist;
1147  }
1148  }
1149 
1150  v_prev = v;
1151  }
1152 
1153  *r_lambda = best_dist;
1154  return hit;
1155 }
1156 
1157 /* Reduce the face down to 'n' corners by collapsing the edges;
1158  * returns the new face.
1159  *
1160  * The orig_verts should contain the vertices of 'f'
1161  */
1162 static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, BMVert **orig_verts)
1163 {
1164  int orig_len = f->len;
1165 
1166  BLI_assert(n >= 3);
1167  BLI_assert(f->len > n);
1168  if (f->len <= n) {
1169  return f;
1170  }
1171 
1172  /* Collapse shortest edge for now */
1173  while (f->len > n) {
1174  BMFace *vf;
1175  BMEdge *shortest_edge;
1176  BMVert *v_safe, *v_merge;
1177  BMOperator op;
1178  BMIter iter;
1179  int i;
1180  BMOpSlot *slot_targetmap;
1181 
1182  shortest_edge = BM_face_find_shortest_loop(f)->e;
1183  BMO_op_initf(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts");
1184 
1185  slot_targetmap = BMO_slot_get(op.slots_in, "targetmap");
1186 
1187  /* NOTE: could probably calculate merges in one go to be
1188  * faster */
1189 
1190  v_safe = shortest_edge->v1;
1191  v_merge = shortest_edge->v2;
1192  mid_v3_v3v3(v_safe->co, v_safe->co, v_merge->co);
1193  BMO_slot_map_elem_insert(&op, slot_targetmap, v_merge, v_safe);
1194  BMO_op_exec(bm, &op);
1195  BMO_op_finish(bm, &op);
1196 
1197  /* Find the new face */
1198  f = NULL;
1199  BM_ITER_ELEM (vf, &iter, v_safe, BM_FACES_OF_VERT) {
1200  bool wrong_face = false;
1201 
1202  for (i = 0; i < orig_len; i++) {
1203  if (orig_verts[i] == v_merge) {
1204  orig_verts[i] = NULL;
1205  }
1206  else if (orig_verts[i] && !BM_vert_in_face(orig_verts[i], vf)) {
1207  wrong_face = true;
1208  break;
1209  }
1210  }
1211 
1212  if (!wrong_face) {
1213  f = vf;
1214  break;
1215  }
1216  }
1217 
1218  BLI_assert(f);
1219  }
1220 
1221  return f;
1222 }
1223 
1224 /* Choose a good face to merge the frame with, used in case the frame
1225  * is completely inside the hull. */
1227 {
1228  BMFace *f, *isect_target_face, *center_target_face;
1229  BMIter iter;
1230  float frame_center[3];
1231  float frame_normal[3];
1232  float best_isect_dist = FLT_MAX;
1233  float best_center_dist = FLT_MAX;
1234 
1235  calc_frame_center(frame_center, frame);
1236  normal_quad_v3(frame_normal,
1237  frame->verts[3]->co,
1238  frame->verts[2]->co,
1239  frame->verts[1]->co,
1240  frame->verts[0]->co);
1241 
1242  /* Use a line intersection test and nearest center test against
1243  * all faces */
1244  isect_target_face = center_target_face = NULL;
1245  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
1246  float dist, poly_center[3];
1247  int hit;
1248 
1249  /* Intersection test */
1250  hit = isect_ray_poly(frame_center, frame_normal, f, &dist);
1251  if (hit && dist < best_isect_dist) {
1252  isect_target_face = f;
1253  best_isect_dist = dist;
1254  }
1255 
1256  /* Nearest test */
1257  BM_face_calc_center_median(f, poly_center);
1258  dist = len_v3v3(frame_center, poly_center);
1259  if (dist < best_center_dist) {
1260  center_target_face = f;
1261  best_center_dist = dist;
1262  }
1263  }
1264 
1265  f = isect_target_face;
1266  if (!f || best_center_dist < best_isect_dist / 2) {
1267  f = center_target_face;
1268  }
1269 
1270  /* This case is unlikely now, but could still happen. Should look
1271  * into splitting edges to make new faces. */
1272 #if PRINT_HOLE_INFO
1273  if (!f) {
1274  printf("no good face found\n");
1275  }
1276 #endif
1277 
1278  return f;
1279 }
1280 
1281 /* Use edge-length heuristic to choose from eight possible polygon bridges */
1282 static void skin_choose_quad_bridge_order(BMVert *a[4], BMVert *b[4], int best_order[4])
1283 {
1284  int orders[8][4];
1285  float shortest_len;
1286  int i, j;
1287 
1288  /* Enumerate all valid orderings */
1289  for (i = 0; i < 4; i++) {
1290  for (j = 0; j < 4; j++) {
1291  orders[i][j] = (j + i) % 4;
1292  orders[i + 4][j] = 3 - ((j + i) % 4);
1293  }
1294  }
1295 
1296  shortest_len = FLT_MAX;
1297  for (i = 0; i < 8; i++) {
1298  float len = 0;
1299 
1300  /* Get total edge length for this configuration */
1301  for (j = 0; j < 4; j++) {
1302  len += len_squared_v3v3(a[j]->co, b[orders[i][j]]->co);
1303  }
1304 
1305  if (len < shortest_len) {
1306  shortest_len = len;
1307  memcpy(best_order, orders[i], sizeof(int[4]));
1308  }
1309  }
1310 }
1311 
1312 static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_face)
1313 {
1314  BMFace *f;
1315  BMVert *verts[4];
1316  BMVert **vert_buf = NULL;
1317  BLI_array_declare(vert_buf);
1318  BMOIter oiter;
1319  BMOperator op;
1320  int i, best_order[4];
1321  BMOpSlot *slot_targetmap;
1322 
1323  BLI_assert(split_face->len >= 3);
1324 
1325  /* Extrude the split face */
1327  BM_elem_flag_enable(split_face, BM_ELEM_TAG);
1328  BMO_op_initf(bm,
1329  &op,
1331  "extrude_discrete_faces faces=%hf",
1332  BM_ELEM_TAG);
1333  BMO_op_exec(bm, &op);
1334 
1335  /* Update split face (should only be one new face created
1336  * during extrusion) */
1337  split_face = NULL;
1338  BMO_ITER (f, &oiter, op.slots_out, "faces.out", BM_FACE) {
1339  BLI_assert(!split_face);
1340  split_face = f;
1341  }
1342 
1343  BMO_op_finish(bm, &op);
1344 
1345  if (split_face->len == 3) {
1346  BMEdge *longest_edge;
1347 
1348  /* Need at least four ring edges, so subdivide longest edge if
1349  * face is a triangle */
1350  longest_edge = BM_face_find_longest_loop(split_face)->e;
1351 
1353  BM_elem_flag_enable(longest_edge, BM_ELEM_TAG);
1354 
1355  BMO_op_callf(bm,
1357  "subdivide_edges edges=%he cuts=%i quad_corner_type=%i",
1358  BM_ELEM_TAG,
1359  1,
1361  }
1362  else if (split_face->len > 4) {
1363  /* Maintain a dynamic vert array containing the split_face's
1364  * vertices, avoids frequent allocs in collapse_face_corners() */
1365  if (BLI_array_len(vert_buf) < split_face->len) {
1366  BLI_array_grow_items(vert_buf, (split_face->len - BLI_array_len(vert_buf)));
1367  }
1368 
1369  /* Get split face's verts */
1370  BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)vert_buf, split_face->len);
1371 
1372  /* Earlier edge split operations may have turned some quads
1373  * into higher-degree faces */
1374  split_face = collapse_face_corners(bm, split_face, 4, vert_buf);
1375  }
1376 
1377  /* `split_face` should now be a quad. */
1378  BLI_assert(split_face->len == 4);
1379 
1380  /* Account for the highly unlikely case that it's not a quad. */
1381  if (split_face->len != 4) {
1382  /* Reuse `vert_buf` for updating normals. */
1383  BLI_array_clear(vert_buf);
1384  BLI_array_grow_items(vert_buf, split_face->len);
1385 
1386  BM_iter_as_array(bm, BM_FACES_OF_VERT, split_face, (void **)vert_buf, split_face->len);
1387 
1388  vert_array_face_normal_update(vert_buf, split_face->len);
1389  BLI_array_free(vert_buf);
1390  return;
1391  }
1392 
1393  /* Done with dynamic array. */
1394  BLI_array_free(vert_buf);
1395 
1396  /* Get split face's verts */
1397  // BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4);
1398  BM_face_as_array_vert_quad(split_face, verts);
1399  skin_choose_quad_bridge_order(verts, frame->verts, best_order);
1400 
1401  /* Delete split face and merge */
1402  BM_face_kill(bm, split_face);
1403  BMO_op_init(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts");
1404  slot_targetmap = BMO_slot_get(op.slots_in, "targetmap");
1405  for (i = 0; i < 4; i++) {
1406  BMO_slot_map_elem_insert(&op, slot_targetmap, verts[i], frame->verts[best_order[i]]);
1407  }
1408  BMO_op_exec(bm, &op);
1409  BMO_op_finish(bm, &op);
1410 
1412 }
1413 
1414 /* If the frame has some vertices that are inside the hull (detached)
1415  * and some attached, duplicate the attached vertices and take the
1416  * whole frame off the hull. */
1418 {
1419  int i, attached[4], totattached = 0;
1420 
1421  /* Get/count attached frame corners */
1422  for (i = 0; i < 4; i++) {
1423  if (!frame->inside_hull[i]) {
1424  attached[totattached++] = i;
1425  }
1426  }
1427 
1428  /* Detach everything */
1429  for (i = 0; i < totattached; i++) {
1430  BMVert **av = &frame->verts[attached[i]];
1431  (*av) = BM_vert_create(bm, (*av)->co, *av, BM_CREATE_NOP);
1432  }
1433 }
1434 
1435 static void quad_from_tris(BMEdge *e, BMFace *adj[2], BMVert *ndx[4])
1436 {
1437  BMVert *tri[2][3];
1438  BMVert *opp = NULL;
1439  int i, j;
1440 
1441  BLI_assert(adj[0]->len == 3 && adj[1]->len == 3);
1442 
1443 #if 0
1444  BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[0], (void **)tri[0], 3);
1445  BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[1], (void **)tri[1], 3);
1446 #else
1447  BM_face_as_array_vert_tri(adj[0], tri[0]);
1448  BM_face_as_array_vert_tri(adj[1], tri[1]);
1449 #endif
1450 
1451  /* Find what the second tri has that the first doesn't */
1452  for (i = 0; i < 3; i++) {
1453  if (!ELEM(tri[1][i], tri[0][0], tri[0][1], tri[0][2])) {
1454  opp = tri[1][i];
1455  break;
1456  }
1457  }
1458  BLI_assert(opp);
1459 
1460  for (i = 0, j = 0; i < 3; i++, j++) {
1461  ndx[j] = tri[0][i];
1462  /* When the triangle edge cuts across our quad-to-be,
1463  * throw in the second triangle's vertex */
1464  if ((ELEM(tri[0][i], e->v1, e->v2)) &&
1465  (tri[0][(i + 1) % 3] == e->v1 || tri[0][(i + 1) % 3] == e->v2)) {
1466  j++;
1467  ndx[j] = opp;
1468  }
1469  }
1470 }
1471 
1472 static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2])
1473 {
1474  BMVert *quad[4];
1475 
1476  quad_from_tris(e, adj, quad);
1477 
1478  add_poly(so, quad[0], quad[1], quad[2], quad[3]);
1479 }
1480 
1482 {
1483  BMIter iter;
1484  BMEdge *e;
1485  HeapSimple *heap;
1486  float score;
1487 
1488  heap = BLI_heapsimple_new();
1489 
1491 
1492  /* Build heap */
1493  BM_ITER_MESH (e, &iter, so->bm, BM_EDGES_OF_MESH) {
1494  BMFace *adj[2];
1495 
1496  /* Only care if the edge is used by exactly two triangles */
1497  if (BM_edge_face_pair(e, &adj[0], &adj[1])) {
1498  if (adj[0]->len == 3 && adj[1]->len == 3) {
1499  BMVert *quad[4];
1500 
1503 
1504  /* Construct quad using the two triangles adjacent to
1505  * the edge */
1506  quad_from_tris(e, adj, quad);
1507 
1508  /* Calculate a score for the quad, higher score for
1509  * triangles being closer to coplanar */
1510  score = ((BM_face_calc_area(adj[0]) + BM_face_calc_area(adj[1])) *
1511  dot_v3v3(adj[0]->no, adj[1]->no));
1512 
1513  /* Check if quad crosses the axis of symmetry */
1514  if (quad_crosses_symmetry_plane(quad, smd)) {
1515  /* Increase score if the triangles form a
1516  * symmetric quad, otherwise don't use it */
1517  if (is_quad_symmetric(quad, smd)) {
1518  score *= 10;
1519  }
1520  else {
1521  continue;
1522  }
1523  }
1524 
1525  /* Don't use the quad if it's concave */
1526  if (!is_quad_convex_v3(quad[0]->co, quad[1]->co, quad[2]->co, quad[3]->co)) {
1527  continue;
1528  }
1529 
1530  BLI_heapsimple_insert(heap, -score, e);
1531  }
1532  }
1533  }
1534 
1535  while (!BLI_heapsimple_is_empty(heap)) {
1536  BMFace *adj[2];
1537 
1538  e = BLI_heapsimple_pop_min(heap);
1539 
1540  if (BM_edge_face_pair(e, &adj[0], &adj[1])) {
1541  /* If both triangles still free, and if they don't already
1542  * share a border with another face, output as a quad */
1543  if (!BM_elem_flag_test(adj[0], BM_ELEM_TAG) && !BM_elem_flag_test(adj[1], BM_ELEM_TAG) &&
1544  !BM_face_share_face_check(adj[0], adj[1])) {
1545  add_quad_from_tris(so, e, adj);
1549  }
1550  }
1551  }
1552 
1553  BLI_heapsimple_free(heap, NULL);
1554 
1556 }
1557 
1558 static void skin_merge_close_frame_verts(SkinNode *skin_nodes,
1559  int verts_num,
1560  const MeshElemMap *emap,
1561  const MEdge *medge)
1562 {
1563  Frame **hull_frames;
1564  int v, tothullframe;
1565 
1566  for (v = 0; v < verts_num; v++) {
1567  /* Only check branch nodes */
1568  if (!skin_nodes[v].totframe) {
1569  hull_frames = collect_hull_frames(v, skin_nodes, emap, medge, &tothullframe);
1570  merge_frame_corners(hull_frames, tothullframe);
1571  MEM_freeN(hull_frames);
1572  }
1573  }
1574 }
1575 
1576 static void skin_update_merged_vertices(SkinNode *skin_nodes, int verts_num)
1577 {
1578  int v;
1579 
1580  for (v = 0; v < verts_num; v++) {
1581  SkinNode *sn = &skin_nodes[v];
1582  int i, j;
1583 
1584  for (i = 0; i < sn->totframe; i++) {
1585  Frame *f = &sn->frames[i];
1586 
1587  for (j = 0; j < 4; j++) {
1588  if (f->merge[j].frame) {
1589  /* Merge chaining not allowed */
1590  BLI_assert(!f->merge[j].frame->merge[f->merge[j].corner].frame);
1591 
1592  f->verts[j] = f->merge[j].frame->verts[f->merge[j].corner];
1593  }
1594  }
1595  }
1596  }
1597 }
1598 
1599 static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int verts_num)
1600 {
1601  int v;
1602 
1603  for (v = 0; v < verts_num; v++) {
1604  SkinNode *sn = &skin_nodes[v];
1605  int j;
1606 
1607  for (j = 0; j < sn->totframe; j++) {
1608  Frame *f = &sn->frames[j];
1609 
1610  if (f->detached) {
1611  BMFace *target_face;
1612 
1614 
1615  target_face = skin_hole_target_face(bm, f);
1616  if (target_face) {
1617  skin_fix_hole_no_good_verts(bm, f, target_face);
1618  }
1619  }
1620  }
1621  }
1622 }
1623 
1624 static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int verts_num)
1625 {
1626  int v;
1627 
1628  for (v = 0; v < verts_num; v++) {
1629  SkinNode *sn = &skin_nodes[v];
1630  /* Assuming here just two frames */
1631  if (sn->flag & SEAM_FRAME) {
1632  BMVert *v_order[4];
1633  int i, order[4];
1634 
1636  for (i = 0; i < 4; i++) {
1637  v_order[i] = sn->frames[1].verts[order[i]];
1638  }
1639  connect_frames(so, sn->frames[0].verts, v_order);
1640  }
1641  else if (sn->totframe == 2) {
1642  connect_frames(so, sn->frames[0].verts, sn->frames[1].verts);
1643  }
1644 
1645  if (sn->flag & CAP_START) {
1646  if (sn->flag & FLIP_NORMAL) {
1647  add_poly(so,
1648  sn->frames[0].verts[0],
1649  sn->frames[0].verts[1],
1650  sn->frames[0].verts[2],
1651  sn->frames[0].verts[3]);
1652  }
1653  else {
1654  add_poly(so,
1655  sn->frames[0].verts[3],
1656  sn->frames[0].verts[2],
1657  sn->frames[0].verts[1],
1658  sn->frames[0].verts[0]);
1659  }
1660  }
1661  if (sn->flag & CAP_END) {
1662  add_poly(so,
1663  sn->frames[1].verts[0],
1664  sn->frames[1].verts[1],
1665  sn->frames[1].verts[2],
1666  sn->frames[1].verts[3]);
1667  }
1668  }
1669 }
1670 
1672  SkinNode *skin_nodes,
1673  const MEdge *medge,
1674  int edges_num)
1675 {
1676  int e;
1677 
1678  for (e = 0; e < edges_num; e++) {
1679  SkinNode *a, *b;
1680  a = &skin_nodes[medge[e].v1];
1681  b = &skin_nodes[medge[e].v2];
1682 
1683  if (a->totframe && b->totframe) {
1684  if ((a->flag & SEAM_FRAME) || (b->flag & SEAM_FRAME)) {
1685  Frame *fr[2] = {&a->frames[0], &b->frames[0]};
1686  BMVert *v_order[4];
1687  int i, order[4];
1688 
1689  if ((a->flag & SEAM_FRAME) && (e != a->seam_edges[0])) {
1690  fr[0]++;
1691  }
1692  if ((b->flag & SEAM_FRAME) && (e != b->seam_edges[0])) {
1693  fr[1]++;
1694  }
1695 
1697  for (i = 0; i < 4; i++) {
1698  v_order[i] = fr[1]->verts[order[i]];
1699  }
1700  connect_frames(so, fr[0]->verts, v_order);
1701  }
1702  else {
1703  connect_frames(so, a->frames[0].verts, b->frames[0].verts);
1704  }
1705  }
1706  }
1707 }
1708 
1710  SkinNode *skin_nodes,
1711  int verts_num,
1712  const SkinModifierData *smd)
1713 {
1714  BMIter iter, eiter;
1715  BMVert *v;
1716  int i, j, k, skey;
1717 
1718  if (smd->branch_smoothing == 0) {
1719  return;
1720  }
1721 
1722  /* Mark all frame vertices */
1724  for (i = 0; i < verts_num; i++) {
1725  for (j = 0; j < skin_nodes[i].totframe; j++) {
1726  Frame *frame = &skin_nodes[i].frames[j];
1727 
1728  for (k = 0; k < 4; k++) {
1730  }
1731  }
1732  }
1733 
1734  /* Add temporary shapekey layer to store original coordinates */
1737  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
1739  }
1740 
1741  /* Smooth vertices, weight unmarked vertices more strongly (helps
1742  * to smooth frame vertices, but don't want to alter them too
1743  * much) */
1744  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
1745  BMEdge *e;
1746  float avg[3];
1747  float weight = smd->branch_smoothing;
1748  int totv = 1;
1749 
1751  weight *= 0.5f;
1752  }
1753 
1754  copy_v3_v3(avg, v->co);
1755  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
1756  BMVert *other = BM_edge_other_vert(e, v);
1757 
1758  add_v3_v3(avg, CustomData_bmesh_get_n(&bm->vdata, other->head.data, CD_SHAPEKEY, skey));
1759  totv++;
1760  }
1761 
1762  if (totv > 1) {
1763  mul_v3_fl(avg, 1.0f / (float)totv);
1764  interp_v3_v3v3(v->co, v->co, avg, weight);
1765  }
1766  }
1767 
1768  /* Done with original coordinates */
1770 
1771  BMFace *f;
1772  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
1774  }
1775 }
1776 
1777 /* Returns true if all hulls are successfully built, false otherwise */
1779  SkinNode *skin_nodes,
1780  int verts_num,
1781  const MeshElemMap *emap,
1782  const MEdge *medge)
1783 {
1784  bool result = true;
1785  int v;
1786 
1787  for (v = 0; v < verts_num; v++) {
1788  SkinNode *sn = &skin_nodes[v];
1789 
1790  /* Branch node hulls */
1791  if (!sn->totframe) {
1792  Frame **hull_frames;
1793  int tothullframe;
1794 
1795  hull_frames = collect_hull_frames(v, skin_nodes, emap, medge, &tothullframe);
1796  if (!build_hull(so, hull_frames, tothullframe)) {
1797  result = false;
1798  }
1799 
1800  MEM_freeN(hull_frames);
1801  }
1802  }
1803 
1804  return result;
1805 }
1806 
1807 typedef enum eSkinErrorFlag {
1809  SKIN_ERROR_HULL = (1 << 1),
1811 
1812 static BMesh *build_skin(SkinNode *skin_nodes,
1813  int verts_num,
1814  const MeshElemMap *emap,
1815  const MEdge *medge,
1816  int edges_num,
1817  const MDeformVert *input_dvert,
1818  SkinModifierData *smd,
1819  eSkinErrorFlag *r_error)
1820 {
1821  SkinOutput so;
1822  int v;
1823 
1824  so.smd = smd;
1826  &((struct BMeshCreateParams){
1827  .use_toolflags = true,
1828  }));
1829  so.mat_nr = 0;
1830 
1831  /* BMESH_TODO: bumping up the stack level (see MOD_array.c) */
1833  BMO_push(so.bm, NULL);
1834  bmesh_edit_begin(so.bm, 0);
1835 
1836  if (input_dvert) {
1838  }
1839 
1840  /* Check for mergeable frame corners around hulls before
1841  * outputting vertices */
1842  skin_merge_close_frame_verts(skin_nodes, verts_num, emap, medge);
1843 
1844  /* Write out all frame vertices to the mesh */
1845  for (v = 0; v < verts_num; v++) {
1846  if (skin_nodes[v].totframe) {
1847  output_frames(so.bm, &skin_nodes[v], input_dvert ? &input_dvert[v] : NULL);
1848  }
1849  }
1850 
1851  /* Update vertex pointers for merged frame corners */
1852  skin_update_merged_vertices(skin_nodes, verts_num);
1853 
1854  if (!skin_output_branch_hulls(&so, skin_nodes, verts_num, emap, medge)) {
1855  *r_error |= SKIN_ERROR_HULL;
1856  }
1857 
1858  /* Merge triangles here in the hope of providing better target
1859  * faces for skin_fix_hull_topology() to connect to */
1860  hull_merge_triangles(&so, smd);
1861 
1862  /* Using convex hulls may not generate a nice manifold mesh. Two
1863  * problems can occur: an input frame's edges may be inside the
1864  * hull, and/or an input frame's vertices may be inside the hull.
1865  *
1866  * General fix to produce manifold mesh: for any frame that is
1867  * partially detached, first detach it fully, then find a suitable
1868  * existing face to merge with. (Note that we do this after
1869  * creating all hull faces, but before creating any other
1870  * faces.
1871  */
1872  skin_fix_hull_topology(so.bm, skin_nodes, verts_num);
1873 
1874  skin_smooth_hulls(so.bm, skin_nodes, verts_num, smd);
1875 
1876  skin_output_end_nodes(&so, skin_nodes, verts_num);
1877  skin_output_connections(&so, skin_nodes, medge, edges_num);
1878  hull_merge_triangles(&so, smd);
1879 
1880  bmesh_edit_end(so.bm, 0);
1881  BMO_pop(so.bm);
1882 
1883  return so.bm;
1884 }
1885 
1887 {
1888  int *orig, totpoly;
1889 
1890  totpoly = mesh->totpoly;
1891  orig = CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, totpoly);
1892  copy_vn_i(orig, totpoly, ORIGINDEX_NONE);
1893 }
1894 
1895 /*
1896  * 0) Subdivide edges (in caller)
1897  * 1) Generate good edge matrices (uses root nodes)
1898  * 2) Generate node frames
1899  * 3) Output vertices and polygons from frames, connections, and hulls
1900  */
1901 static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_error)
1902 {
1903  Mesh *result;
1904  MVertSkin *nodes;
1905  BMesh *bm;
1906  EMat *emat;
1907  SkinNode *skin_nodes;
1908  MeshElemMap *emap;
1909  int *emapmem;
1910  MVert *mvert;
1911  MEdge *medge;
1912  MDeformVert *dvert;
1913  int verts_num, edges_num;
1914  bool has_valid_root = false;
1915 
1916  nodes = CustomData_get_layer(&origmesh->vdata, CD_MVERT_SKIN);
1917 
1918  mvert = origmesh->mvert;
1919  dvert = origmesh->dvert;
1920  medge = origmesh->medge;
1921  verts_num = origmesh->totvert;
1922  edges_num = origmesh->totedge;
1923 
1924  BKE_mesh_vert_edge_map_create(&emap, &emapmem, medge, verts_num, edges_num);
1925 
1926  emat = build_edge_mats(nodes, mvert, verts_num, medge, emap, edges_num, &has_valid_root);
1927  skin_nodes = build_frames(mvert, verts_num, nodes, emap, emat);
1928  MEM_freeN(emat);
1929  emat = NULL;
1930 
1931  bm = build_skin(skin_nodes, verts_num, emap, medge, edges_num, dvert, smd, r_error);
1932 
1933  MEM_freeN(skin_nodes);
1934  MEM_freeN(emap);
1935  MEM_freeN(emapmem);
1936 
1937  if (!has_valid_root) {
1938  *r_error |= SKIN_ERROR_NO_VALID_ROOT;
1939  }
1940 
1941  if (!bm) {
1942  return NULL;
1943  }
1944 
1946  BM_mesh_free(bm);
1947 
1949 
1950  return result;
1951 }
1952 
1954 {
1955  Mesh *result;
1956 
1957  /* Skin node layer is required */
1959  return mesh;
1960  }
1961 
1963  result = base_skin(mesh, smd, r_error);
1964 
1965  BKE_id_free(NULL, mesh);
1966  return result;
1967 }
1968 
1969 /**************************** Skin Modifier ***************************/
1970 
1971 static void initData(ModifierData *md)
1972 {
1973  SkinModifierData *smd = (SkinModifierData *)md;
1974 
1975  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier));
1976 
1978 
1979  /* Enable in editmode by default. */
1981 }
1982 
1984 {
1985  eSkinErrorFlag error = 0;
1987 
1991  ctx->object,
1992  md,
1993  "No valid root vertex found (you need one per mesh island you want to skin)");
1994  }
1995  if (error & SKIN_ERROR_HULL) {
1996  error &= ~SKIN_ERROR_HULL;
1997  BKE_modifier_set_error(ctx->object, md, "Hull error");
1998  }
1999  BLI_assert(error == 0);
2000 
2001  if (result == NULL) {
2002  return mesh;
2003  }
2004  return result;
2005 }
2006 
2007 static void requiredDataMask(Object *UNUSED(ob),
2008  ModifierData *UNUSED(md),
2009  CustomData_MeshMasks *r_cddata_masks)
2010 {
2011  r_cddata_masks->vmask |= CD_MASK_MVERT_SKIN | CD_MASK_MDEFORMVERT;
2012 }
2013 
2014 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
2015 {
2016  uiLayout *row;
2017  uiLayout *layout = panel->layout;
2018  int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
2019 
2020  PointerRNA ob_ptr;
2022 
2023  PointerRNA op_ptr;
2024 
2025  uiLayoutSetPropSep(layout, true);
2026 
2027  uiItemR(layout, ptr, "branch_smoothing", 0, NULL, ICON_NONE);
2028 
2029  row = uiLayoutRowWithHeading(layout, true, IFACE_("Symmetry"));
2030  uiItemR(row, ptr, "use_x_symmetry", toggles_flag, NULL, ICON_NONE);
2031  uiItemR(row, ptr, "use_y_symmetry", toggles_flag, NULL, ICON_NONE);
2032  uiItemR(row, ptr, "use_z_symmetry", toggles_flag, NULL, ICON_NONE);
2033 
2034  uiItemR(layout, ptr, "use_smooth_shade", 0, NULL, ICON_NONE);
2035 
2036  row = uiLayoutRow(layout, false);
2037  uiItemO(row, IFACE_("Create Armature"), ICON_NONE, "OBJECT_OT_skin_armature_create");
2038  uiItemO(row, NULL, ICON_NONE, "MESH_OT_customdata_skin_add");
2039 
2040  row = uiLayoutRow(layout, false);
2041  uiItemFullO(row,
2042  "OBJECT_OT_skin_loose_mark_clear",
2043  IFACE_("Mark Loose"),
2044  ICON_NONE,
2045  NULL,
2047  0,
2048  &op_ptr);
2049  RNA_enum_set(&op_ptr, "action", 0); /* SKIN_LOOSE_MARK */
2050  uiItemFullO(row,
2051  "OBJECT_OT_skin_loose_mark_clear",
2052  IFACE_("Clear Loose"),
2053  ICON_NONE,
2054  NULL,
2056  0,
2057  &op_ptr);
2058  RNA_enum_set(&op_ptr, "action", 1); /* SKIN_LOOSE_CLEAR */
2059 
2060  uiItemO(layout, IFACE_("Mark Root"), ICON_NONE, "OBJECT_OT_skin_root_mark");
2061  uiItemO(layout, IFACE_("Equalize Radii"), ICON_NONE, "OBJECT_OT_skin_radii_equalize");
2062 
2063  modifier_panel_end(layout, ptr);
2064 }
2065 
2066 static void panelRegister(ARegionType *region_type)
2067 {
2069 }
2070 
2072  /* name */ N_("Skin"),
2073  /* structName */ "SkinModifierData",
2074  /* structSize */ sizeof(SkinModifierData),
2075  /* srna */ &RNA_SkinModifier,
2076  /* type */ eModifierTypeType_Constructive,
2078  /* icon */ ICON_MOD_SKIN,
2079 
2080  /* copyData */ BKE_modifier_copydata_generic,
2081 
2082  /* deformVerts */ NULL,
2083  /* deformMatrices */ NULL,
2084  /* deformVertsEM */ NULL,
2085  /* deformMatricesEM */ NULL,
2086  /* modifyMesh */ modifyMesh,
2087  /* modifyGeometrySet */ NULL,
2088 
2089  /* initData */ initData,
2090  /* requiredDataMask */ requiredDataMask,
2091  /* freeData */ NULL,
2092  /* isDisabled */ NULL,
2093  /* updateDepsgraph */ NULL,
2094  /* dependsOnTime */ NULL,
2095  /* dependsOnNormals */ NULL,
2096  /* foreachIDLink */ NULL,
2097  /* foreachTexLink */ NULL,
2098  /* freeRuntimeData */ NULL,
2099  /* panelRegister */ panelRegister,
2100  /* blendWrite */ NULL,
2101  /* blendRead */ NULL,
2102 };
int CustomData_number_of_layers(const struct CustomData *data, int type)
@ CD_CALLOC
#define ORIGINDEX_NONE
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_bmesh_get(const struct CustomData *data, void *block, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
void * CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n)
support for deformation groups and hooks.
void BKE_defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src)
void BKE_defvert_add_index_notest(struct MDeformVert *dv, int defgroup, float weight)
Definition: deform.c:779
void BKE_id_free(struct Main *bmain, void *idv)
int BKE_mesh_edge_other_vert(const struct MEdge *e, int v)
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
struct Mesh * BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, const struct CustomData_MeshMasks *cd_mask_extra, const struct Mesh *me_settings)
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge)
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:47
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
A (mainly) macro array library.
#define BLI_array_grow_items(arr, num)
Definition: BLI_array.h:91
#define BLI_array_declare(arr)
Definition: BLI_array.h:50
#define BLI_array_len(arr)
Definition: BLI_array.h:63
#define BLI_array_clear(arr)
Definition: BLI_array.h:128
#define BLI_array_free(arr)
Definition: BLI_array.h:113
#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
A min-heap / priority queue ADT.
void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1)
HeapSimple * BLI_heapsimple_new(void) ATTR_WARN_UNUSED_RESULT
void * BLI_heapsimple_pop_min(HeapSimple *heap) ATTR_NONNULL(1)
bool BLI_heapsimple_is_empty(const HeapSimple *heap) ATTR_NONNULL(1)
void BLI_heapsimple_insert(HeapSimple *heap, float value, void *ptr) ATTR_NONNULL(1)
MINLINE float min_ff(float a, float b)
MINLINE float interpf(float a, float b, float t)
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:50
bool isect_ray_tri_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
Definition: math_geom.c:1662
bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:5750
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void zero_m3(float m[3][3])
Definition: math_matrix.c:23
void mid_v3_v3v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_vector.c:263
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], float angle)
Definition: math_vector.c:776
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
void copy_vn_i(int *array_tar, int size, int val)
Definition: math_vector.c:1223
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:445
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
Definition: stack.c:135
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
Definition: stack.c:129
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:247
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:94
#define BLI_stack_new(esize, descr)
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK4(a)
#define UNUSED_VARS(...)
#define UNPACK4_EX(pre, a, post)
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
void swap(T &a, T &b)
Definition: Common.h:19
#define CD_MASK_MDEFORMVERT
#define CD_MASK_MVERT_SKIN
@ CD_MVERT_SKIN
@ CD_MDEFORMVERT
@ CD_ORIGINDEX
@ CD_SHAPEKEY
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ MVERT_SKIN_LOOSE
@ MVERT_SKIN_ROOT
@ eModifierMode_Editmode
struct SkinModifierData SkinModifierData
@ MOD_SKIN_SMOOTH_SHADING
@ eModifierType_Skin
Object is a sort of wrapper for general info.
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble right
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
static void skin_smooth_hulls(BMesh *bm, SkinNode *skin_nodes, int verts_num, const SkinModifierData *smd)
Definition: MOD_skin.c:1709
#define NUM_SUBDIVISIONS_MAX
static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
Definition: MOD_skin.c:1481
static void connection_node_frames(int v, SkinNode *skin_nodes, const MVert *mvert, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat)
Definition: MOD_skin.c:606
static bool is_quad_symmetric(BMVert *quad[4], const SkinModifierData *smd)
Definition: MOD_skin.c:177
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition: MOD_skin.c:1983
eSkinErrorFlag
Definition: MOD_skin.c:1807
@ SKIN_ERROR_HULL
Definition: MOD_skin.c:1809
@ SKIN_ERROR_NO_VALID_ROOT
Definition: MOD_skin.c:1808
static void create_frame(Frame *frame, const float co[3], const float radius[2], const float mat[3][3], float offset)
Definition: MOD_skin.c:489
ModifierTypeInfo modifierType_Skin
Definition: MOD_skin.c:2071
static int calc_edge_subdivisions(const MVert *mvert, const MVertSkin *nodes, const MEdge *e, const int *degree)
Definition: MOD_skin.c:828
static void merge_frame_corners(Frame **frames, int totframe)
Definition: MOD_skin.c:384
static Mesh * subdivide_base(const Mesh *orig)
Definition: MOD_skin.c:884
static bool quad_crosses_symmetry_plane(BMVert *quad[4], const SkinModifierData *smd)
Definition: MOD_skin.c:211
static void end_node_frames(int v, SkinNode *skin_nodes, const MVert *mvert, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat)
Definition: MOD_skin.c:521
static void skin_merge_close_frame_verts(SkinNode *skin_nodes, int verts_num, const MeshElemMap *emap, const MEdge *medge)
Definition: MOD_skin.c:1558
static BMFace * skin_hole_target_face(BMesh *bm, Frame *frame)
Definition: MOD_skin.c:1226
static void connect_frames(SkinOutput *so, BMVert *frame1[4], BMVert *frame2[4])
Definition: MOD_skin.c:1036
static void calc_edge_mat(float mat[3][3], const float a[3], const float b[3])
Definition: MOD_skin.c:676
static void output_frames(BMesh *bm, SkinNode *sn, const MDeformVert *input_dvert)
Definition: MOD_skin.c:1089
static void skin_output_connections(SkinOutput *so, SkinNode *skin_nodes, const MEdge *medge, int edges_num)
Definition: MOD_skin.c:1671
static BMFace * collapse_face_corners(BMesh *bm, BMFace *f, int n, BMVert **orig_verts)
Definition: MOD_skin.c:1162
static bool build_hull(SkinOutput *so, Frame **frames, int totframe)
Definition: MOD_skin.c:258
static void vert_face_normal_mark_update(BMVert *v)
Definition: MOD_skin.c:93
static void node_frames_init(SkinNode *nf, int totframe)
Definition: MOD_skin.c:476
static bool skin_output_branch_hulls(SkinOutput *so, SkinNode *skin_nodes, int verts_num, const MeshElemMap *emap, const MEdge *medge)
Definition: MOD_skin.c:1778
static BMesh * build_skin(SkinNode *skin_nodes, int verts_num, const MeshElemMap *emap, const MEdge *medge, int edges_num, const MDeformVert *input_dvert, SkinModifierData *smd, eSkinErrorFlag *r_error)
Definition: MOD_skin.c:1812
static void add_poly(SkinOutput *so, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4)
Definition: MOD_skin.c:1018
static EMat * build_edge_mats(const MVertSkin *vs, const MVert *mvert, const int verts_num, const MEdge *medge, const MeshElemMap *emap, const int edges_num, bool *has_valid_root)
Definition: MOD_skin.c:767
SkinNodeFlag
Definition: MOD_skin.c:127
@ CAP_END
Definition: MOD_skin.c:129
@ CAP_START
Definition: MOD_skin.c:128
@ SEAM_FRAME
Definition: MOD_skin.c:130
@ FLIP_NORMAL
Definition: MOD_skin.c:131
static void skin_set_orig_indices(Mesh *mesh)
Definition: MOD_skin.c:1886
static SkinNode * build_frames(const MVert *mvert, int verts_num, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat)
Definition: MOD_skin.c:651
static Mesh * base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_error)
Definition: MOD_skin.c:1901
static void skin_update_merged_vertices(SkinNode *skin_nodes, int verts_num)
Definition: MOD_skin.c:1576
static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_face)
Definition: MOD_skin.c:1312
static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int verts_num)
Definition: MOD_skin.c:1624
static void requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md), CustomData_MeshMasks *r_cddata_masks)
Definition: MOD_skin.c:2007
static void vert_array_face_normal_update(BMVert **verts, int verts_len)
Definition: MOD_skin.c:107
static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2])
Definition: MOD_skin.c:1472
struct Frame Frame
Definition: frames.hpp:261
static float half_v2(const float v[2])
Definition: MOD_skin.c:516
#define MAX_SKIN_NODE_FRAMES
Definition: MOD_skin.c:156
static int connection_node_mat(float mat[3][3], int v, const MeshElemMap *emap, EMat *emat)
Definition: MOD_skin.c:573
static int isect_ray_poly(const float ray_start[3], const float ray_dir[3], BMFace *f, float *r_lambda)
Definition: MOD_skin.c:1125
static void skin_choose_quad_bridge_order(BMVert *a[4], BMVert *b[4], int best_order[4])
Definition: MOD_skin.c:1282
static void build_emats_stack(BLI_Stack *stack, BLI_bitmap *visited_e, EMat *emat, const MeshElemMap *emap, const MEdge *medge, const MVertSkin *vs, const MVert *mvert)
Definition: MOD_skin.c:711
static bool skin_frame_find_contained_faces(const Frame *frame, BMFace *fill_faces[2])
Definition: MOD_skin.c:240
static void calc_frame_center(float center[3], const Frame *frame)
Definition: MOD_skin.c:1115
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_skin.c:2014
static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int verts_num)
Definition: MOD_skin.c:1599
static void initData(ModifierData *md)
Definition: MOD_skin.c:1971
static void panelRegister(ARegionType *region_type)
Definition: MOD_skin.c:2066
static void quad_from_tris(BMEdge *e, BMFace *adj[2], BMVert *ndx[4])
Definition: MOD_skin.c:1435
static float frame_len(const Frame *frame)
Definition: MOD_skin.c:379
static Frame ** collect_hull_frames(int v, SkinNode *frames, const MeshElemMap *emap, const MEdge *medge, int *tothullframe)
Definition: MOD_skin.c:448
static Mesh * final_skin(SkinModifierData *smd, Mesh *mesh, eSkinErrorFlag *r_error)
Definition: MOD_skin.c:1953
static void vert_face_normal_mark_set(BMVert *v)
Definition: MOD_skin.c:84
static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame)
Definition: MOD_skin.c:1417
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
void uiItemFullO(uiLayout *layout, const char *opname, const char *name, int icon, struct IDProperty *properties, wmOperatorCallContext context, int flag, struct PointerRNA *r_opptr)
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
#define BM_ALL_NOLOOP
Definition: bmesh_class.h:411
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_SMOOTH
Definition: bmesh_class.h:477
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
Definition: bmesh_core.c:41
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
Definition: bmesh_core.c:464
void BM_face_kill(BMesh *bm, BMFace *f)
Definition: bmesh_core.c:828
@ BM_CREATE_NOP
Definition: bmesh_core.h:12
@ BM_CREATE_NO_DOUBLE
Definition: bmesh_core.h:14
void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype)
Definition: bmesh_delete.c:245
@ BMO_ERROR_CANCEL
Definition: bmesh_error.h:21
bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level)
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:14
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
Definition: bmesh_interp.c:922
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:839
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len)
Iterator as Array.
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_EDGE
@ BM_FACES_OF_VERT
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_FACE
@ BM_FACES_OF_MESH
@ BM_EDGES_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
const BMAllocTemplate bm_mesh_allocsize_default
Definition: bmesh_mesh.cc:23
void BM_mesh_elem_toolflags_ensure(BMesh *bm)
Definition: bmesh_mesh.cc:75
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
Definition: bmesh_mesh.cc:125
void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
Definition: bmesh_mesh.cc:272
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
BMesh End Edit.
Definition: bmesh_mesh.cc:292
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
void BMO_pop(BMesh *bm)
BMESH OPSTACK POP.
void BMO_push(BMesh *bm, BMOperator *op)
BMESH OPSTACK PUSH.
@ BMO_FLAG_RESPECT_HIDE
void BMO_op_init(BMesh *bm, BMOperator *op, int flag, const char *opname)
BMESH OPSTACK INIT OP.
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
bool BMO_op_initf(BMesh *bm, BMOperator *op, int flag, const char *fmt,...)
void BMO_op_finish(BMesh *bm, BMOperator *op)
BMESH OPSTACK FINISH OP.
bool BMO_op_callf(BMesh *bm, int flag, const char *fmt,...)
BMOpSlot * BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK GET SLOT.
#define BMO_FLAG_DEFAULTS
BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val)
@ SUBD_CORNER_STRAIGHT_CUT
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
void BM_face_normal_update(BMFace *f)
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
float BM_face_calc_area(const BMFace *f)
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b)
Definition: bmesh_query.c:951
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
Definition: bmesh_query.c:538
bool BM_face_is_normal_valid(const BMFace *f)
Definition: bmesh_query.c:2033
bool BM_vert_in_face(BMVert *v, BMFace *f)
Definition: bmesh_query.c:306
BMLoop * BM_face_find_shortest_loop(BMFace *f)
Definition: bmesh_query.c:1487
BMLoop * BM_face_find_longest_loop(BMFace *f)
Definition: bmesh_query.c:1508
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
__forceinline BoundBox merge(const BoundBox &bbox, const float3 &pt)
Definition: boundbox.h:161
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define powf(x, y)
Definition: cuda/compat.h:103
int len
Definition: draw_manager.c:108
static float verts[][3]
GPUBatch * quad
IconTextureDrawCall normal
int count
ccl_gpu_kernel_postfix ccl_global float int int int int float threshold
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix int ccl_global int * indices
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
static int left
static void error(const char *str)
Definition: meshlaplacian.c:51
bool isfinite(uchar)
Definition: scene/image.cpp:31
static unsigned a[3]
Definition: RandGen.cpp:78
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
short mat_nr
Definition: bmesh_class.h:281
int len
Definition: bmesh_class.h:267
float no[3]
Definition: bmesh_class.h:271
void * data
Definition: bmesh_class.h:51
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:87
BMHeader head
Definition: bmesh_class.h:85
CustomData vdata
Definition: bmesh_class.h:337
Definition: MOD_skin.c:120
int origin
Definition: MOD_skin.c:124
float mat[3][3]
Definition: MOD_skin.c:121
float mat[3][3]
Definition: MOD_skin.c:706
BMVert * verts[4]
Definition: MOD_skin.c:136
uint is_target
Definition: MOD_skin.c:147
struct Frame::@1150 merge[4]
float co[4][3]
Definition: MOD_skin.c:138
bool inside_hull[4]
Definition: MOD_skin.c:151
int corner
Definition: MOD_skin.c:144
struct Frame * frame
Definition: MOD_skin.c:143
bool detached
Definition: MOD_skin.c:153
struct MDeformWeight * dw
unsigned int def_nr
unsigned int v1
unsigned int v2
float co[3]
struct MEdge * medge
CustomData vdata
struct MVert * mvert
struct MDeformVert * dvert
int totedge
int totvert
CustomData pdata
int totpoly
struct Object * object
Definition: BKE_modifier.h:141
struct uiLayout * layout
Frame frames[MAX_SKIN_NODE_FRAMES]
Definition: MOD_skin.c:158
int totframe
Definition: MOD_skin.c:159
SkinNodeFlag flag
Definition: MOD_skin.c:161
int seam_edges[2]
Definition: MOD_skin.c:164
SkinModifierData * smd
Definition: MOD_skin.c:169
int mat_nr
Definition: MOD_skin.c:170
BMesh * bm
Definition: MOD_skin.c:168
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480