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