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