Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* | 1 /* |
2 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "BLI_math.h" | 26 #include "BLI_math.h" |
27 #include "BLI_utildefines.h" | 27 #include "BLI_utildefines.h" |
28 | 28 |
29 #include "bmesh.h" | 29 #include "bmesh.h" |
30 #include "intern/bmesh_operators_private.h" | 30 #include "intern/bmesh_operators_private.h" |
31 | 31 |
32 enum { | 32 enum { |
33 SYMM_OUTPUT_GEOM = (1 << 0) | 33 SYMM_OUTPUT_GEOM = (1 << 0) |
34 }; | 34 }; |
35 | 35 |
36 /* Note: don't think there's much need to having these user-adjustable? */ | 36 /* Note: don't think there's much need to make these user-adjustable? */ |
37 #define SYMM_AXIS_THRESHOLD 0.001f | 37 #define SYMM_AXIS_THRESHOLD 0.00002f |
38 #define SYMM_VERT_THRESHOLD 0.001f | 38 #define SYMM_VERT_THRESHOLD 0.00002f |
brechtvl
2012/10/12 10:47:24
I think these values are quite high, mirror for tr
| |
39 | 39 |
40 typedef enum { | 40 typedef enum { |
41 /* Coordinate lies on the side being copied from */ | 41 /* Coordinate lies on the side being copied from */ |
42 SYMM_SIDE_KEEP, | 42 SYMM_SIDE_KEEP, |
43 /* Coordinate lies on the side being copied from and within the | 43 /* Coordinate lies on the side being copied from and within the |
44 * axis threshold */ | 44 * axis threshold */ |
45 SYMM_SIDE_AXIS, | 45 SYMM_SIDE_AXIS, |
46 /* Coordinate lies on the side being copied to */ | 46 /* Coordinate lies on the side being copied to */ |
47 SYMM_SIDE_KILL | 47 SYMM_SIDE_KILL |
48 } SymmSide; | 48 } SymmSide; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 break; | 119 break; |
120 | 120 |
121 case SYMM_SIDE_KILL: | 121 case SYMM_SIDE_KILL: |
122 /* The vertex does not lie in the half-space bei ng | 122 /* The vertex does not lie in the half-space bei ng |
123 * copied from, nothing to do */ | 123 * copied from, nothing to do */ |
124 break; | 124 break; |
125 } | 125 } |
126 } | 126 } |
127 } | 127 } |
128 | 128 |
129 static int symm_edge_crosses_axis(const Symm *symm, const BMEdge *e) | |
130 { | |
131 const int sides[2] = {symm_co_side(symm, e->v1->co), | |
132 symm_co_side(symm, e->v2->co)} ; | |
133 | |
134 return ((sides[0] != SYMM_SIDE_AXIS) && | |
135 (sides[1] != SYMM_SIDE_AXIS) && | |
136 (sides[0] != sides[1])); | |
137 } | |
138 | |
129 /* Output edge split vertices for asymmetric edges and the edge_splits | 139 /* Output edge split vertices for asymmetric edges and the edge_splits |
130 * mapping array */ | 140 * mapping array */ |
131 static void symm_split_asymmetric_edges(Symm *symm) | 141 static void symm_split_asymmetric_edges(Symm *symm) |
132 { | 142 { |
133 BMOIter oiter; | 143 BMOIter oiter; |
134 BMEdge *e; | 144 BMEdge *e; |
135 | 145 |
136 symm->edge_split_map = BLI_ghash_ptr_new(AT); | 146 symm->edge_split_map = BLI_ghash_ptr_new(AT); |
137 | 147 |
138 BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { | 148 BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { |
139 const int sides[2] = {symm_co_side(symm, e->v1->co), | |
140 symm_co_side(symm, e-> v2->co)}; | |
141 float flipped[3]; | 149 float flipped[3]; |
142 | 150 |
143 copy_v3_v3(flipped, e->v1->co); | 151 copy_v3_v3(flipped, e->v1->co); |
144 flipped[symm->axis] = -flipped[symm->axis]; | 152 flipped[symm->axis] = -flipped[symm->axis]; |
145 | 153 |
146 » » if ((sides[0] != SYMM_SIDE_AXIS) && | 154 » » if (symm_edge_crosses_axis(symm, e) && |
147 » » » (sides[1] != SYMM_SIDE_AXIS) && | |
148 » » » (sides[0] != sides[1]) && | |
149 (!compare_v3v3(e->v2->co, flipped, SYMM_VERT_THRESHOLD)) ) | 155 (!compare_v3v3(e->v2->co, flipped, SYMM_VERT_THRESHOLD)) ) |
150 { | 156 { |
151 /* Endpoints lie on opposite sides and are asymmetric */ | 157 /* Endpoints lie on opposite sides and are asymmetric */ |
152 | 158 |
153 BMVert *v; | 159 BMVert *v; |
154 » » » float lambda, edge_dir[3], co[3]; | 160 » » » float lambda = 0, edge_dir[3], co[3]; |
155 float plane_co[3][3][3] = { | 161 float plane_co[3][3][3] = { |
156 /* axis == 0 */ | 162 /* axis == 0 */ |
157 {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}}, | 163 {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}}, |
158 /* axis == 1 */ | 164 /* axis == 1 */ |
159 {{0, 0, 0}, {1, 0, 0}, {0, 0, 1}}, | 165 {{0, 0, 0}, {1, 0, 0}, {0, 0, 1}}, |
160 /* axis == 2 */ | 166 /* axis == 2 */ |
161 {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}}, | 167 {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}}, |
162 }; | 168 }; |
163 int r; | 169 int r; |
164 | 170 |
165 /* Find intersection of edge with symmetry plane */ | 171 /* Find intersection of edge with symmetry plane */ |
166 sub_v3_v3v3(edge_dir, e->v2->co, e->v1->co); | 172 sub_v3_v3v3(edge_dir, e->v2->co, e->v1->co); |
167 normalize_v3(edge_dir); | 173 normalize_v3(edge_dir); |
168 r = isect_ray_plane_v3(e->v1->co, | 174 r = isect_ray_plane_v3(e->v1->co, |
169 edge_dir, | 175 edge_dir, |
170 plane_co[symm ->axis][0], | 176 plane_co[symm ->axis][0], |
171 plane_co[symm ->axis][1], | 177 plane_co[symm ->axis][1], |
172 plane_co[symm ->axis][2], | 178 plane_co[symm ->axis][2], |
173 &lambda, TRUE ); | 179 &lambda, TRUE ); |
174 BLI_assert(r); | 180 BLI_assert(r); |
brechtvl
2012/10/12 10:47:24
I have a feeling there is a corner case where r =
| |
175 | 181 |
176 madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda); | 182 madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda); |
177 co[symm->axis] = 0; | 183 co[symm->axis] = 0; |
178 | 184 |
179 /* Edge is asymmetric, split it with a new vertex */ | 185 /* Edge is asymmetric, split it with a new vertex */ |
180 v = BM_vert_create(symm->bm, co, e->v1); | 186 v = BM_vert_create(symm->bm, co, e->v1); |
181 BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM); | 187 BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM); |
182 BLI_ghash_insert(symm->edge_split_map, e, v); | 188 BLI_ghash_insert(symm->edge_split_map, e, v); |
183 } | 189 } |
184 } | 190 } |
185 } | 191 } |
186 | 192 |
187 static void symm_mirror_edges(Symm *symm) | 193 static void symm_mirror_edges(Symm *symm) |
188 { | 194 { |
189 BMOIter oiter; | 195 BMOIter oiter; |
190 BMEdge *e; | 196 BMEdge *e; |
191 | 197 |
192 BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { | 198 BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { |
193 BMVert *v1 = NULL, *v2 = NULL; | 199 BMVert *v1 = NULL, *v2 = NULL; |
194 BMEdge *e_new; | 200 BMEdge *e_new; |
195 | 201 |
196 » » if (BLI_ghash_haskey(symm->vert_symm_map, e->v1)) | 202 » » v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1); |
brechtvl
2012/10/12 10:47:24
This could call ghash_lookup without ghash_haskey
| |
197 » » » v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1); | 203 » » v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2); |
198 » » if (BLI_ghash_haskey(symm->vert_symm_map, e->v2)) | |
199 » » » v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2); | |
200 | 204 |
201 if (v1 && v2) { | 205 if (v1 && v2) { |
202 e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); | 206 e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); |
203 BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); | 207 BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); |
204 } | 208 } |
205 else if (v1 || v2) { | 209 else if (v1 || v2) { |
206 if (BLI_ghash_haskey(symm->edge_split_map, e)) { | 210 if (BLI_ghash_haskey(symm->edge_split_map, e)) { |
207 BMVert *v_split = BLI_ghash_lookup(symm->edge_sp lit_map, e); | 211 BMVert *v_split = BLI_ghash_lookup(symm->edge_sp lit_map, e); |
208 | 212 |
209 /* Output the keep side of the split edge */ | 213 /* Output the keep side of the split edge */ |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 BLI_array_declare(fv); | 448 BLI_array_declare(fv); |
445 BLI_array_declare(fe); | 449 BLI_array_declare(fe); |
446 | 450 |
447 BMO_ITER (f, &oiter, symm->bm, symm->op, "input", BM_FACE) { | 451 BMO_ITER (f, &oiter, symm->bm, symm->op, "input", BM_FACE) { |
448 BMIter iter; | 452 BMIter iter; |
449 BMLoop *l; | 453 BMLoop *l; |
450 int mirror_all = TRUE, ignore_all = TRUE; | 454 int mirror_all = TRUE, ignore_all = TRUE; |
451 | 455 |
452 /* Check if entire polygon can be mirrored or ignored */ | 456 /* Check if entire polygon can be mirrored or ignored */ |
453 BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { | 457 BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { |
454 » » » if (symm_co_side(symm, l->v->co) == SYMM_SIDE_KILL) | 458 » » » const SymmSide side = symm_co_side(symm, l->v->co); |
459 » » » if (side == SYMM_SIDE_KILL) | |
455 mirror_all = FALSE; | 460 mirror_all = FALSE; |
456 » » » else | 461 » » » else if (side == SYMM_SIDE_KEEP) |
457 ignore_all = FALSE; | 462 ignore_all = FALSE; |
458 } | 463 } |
459 | 464 |
460 if (mirror_all) { | 465 if (mirror_all) { |
461 int i; | 466 int i; |
462 | 467 |
463 /* Make a mirrored copy of the polygon */ | 468 /* Make a mirrored copy of the polygon */ |
464 | 469 |
465 BLI_array_empty(fv); | 470 BLI_array_empty(fv); |
466 BLI_array_empty(fe); | 471 BLI_array_empty(fe); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
596 | 601 |
597 /* Remove unused edges and vertices from the side being copied to */ | 602 /* Remove unused edges and vertices from the side being copied to */ |
598 static void symm_kill_unused(Symm *symm) | 603 static void symm_kill_unused(Symm *symm) |
599 { | 604 { |
600 BMOIter oiter; | 605 BMOIter oiter; |
601 BMEdge *e; | 606 BMEdge *e; |
602 BMVert *v; | 607 BMVert *v; |
603 | 608 |
604 /* Kill unused edges */ | 609 /* Kill unused edges */ |
605 BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { | 610 BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { |
606 » » if ((symm_co_side(symm, e->v1->co) == SYMM_SIDE_KILL) || | 611 » » const int crosses = symm_edge_crosses_axis(symm, e); |
607 » » » (symm_co_side(symm, e->v2->co) == SYMM_SIDE_KILL)) | 612 » » const int symmetric = (crosses && |
613 » » » » » » » (!BLI_ghash_haskey(sy mm->edge_split_map, e))); | |
614 | |
615 » » if (((symm_co_side(symm, e->v1->co) == SYMM_SIDE_KILL) || | |
616 » » » (symm_co_side(symm, e->v2->co) == SYMM_SIDE_KILL)) && | |
617 » » » !symmetric) | |
608 { | 618 { |
609 /* The edge might be used by a face outside the input se t */ | 619 /* The edge might be used by a face outside the input se t */ |
610 if (BM_edge_face_count(e) == 0) | 620 if (BM_edge_face_count(e) == 0) |
611 BM_edge_kill(symm->bm, e); | 621 BM_edge_kill(symm->bm, e); |
612 } | 622 } |
613 } | 623 } |
614 | 624 |
615 /* Kill unused vertices */ | 625 /* Kill unused vertices */ |
616 BMO_ITER (v, &oiter, symm->bm, symm->op, "input", BM_VERT) { | 626 BMO_ITER (v, &oiter, symm->bm, symm->op, "input", BM_VERT) { |
617 if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) { | 627 if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) { |
(...skipping 26 matching lines...) Expand all Loading... | |
644 symm_mirror_edges(&symm); | 654 symm_mirror_edges(&symm); |
645 symm_mirror_polygons(&symm); | 655 symm_mirror_polygons(&symm); |
646 symm_kill_unused(&symm); | 656 symm_kill_unused(&symm); |
647 | 657 |
648 BLI_ghash_free(symm.vert_symm_map, NULL, NULL); | 658 BLI_ghash_free(symm.vert_symm_map, NULL, NULL); |
649 BLI_ghash_free(symm.edge_split_map, NULL, NULL); | 659 BLI_ghash_free(symm.edge_split_map, NULL, NULL); |
650 | 660 |
651 BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, | 661 BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, |
652 SYMM_OUTPUT_GEOM); | 662 SYMM_OUTPUT_GEOM); |
653 } | 663 } |
LEFT | RIGHT |