bmo_normals.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * ***** BEGIN GPL LICENSE BLOCK *****
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software Foundation,
  16. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * Contributor(s): Joseph Eagar, Campbell Barton
  19. *
  20. * ***** END GPL LICENSE BLOCK *****
  21. */
  22. /** \file blender/bmesh/operators/bmo_normals.c
  23. * \ingroup bmesh
  24. *
  25. * normal recalculation.
  26. */
  27. #include "MEM_guardedalloc.h"
  28. #include "BLI_math.h"
  29. #include "BLI_linklist_stack.h"
  30. #include "bmesh.h"
  31. #include "intern/bmesh_operators_private.h" /* own include */
  32. /********* righthand faces implementation ****** */
  33. #define FACE_FLAG (1 << 0)
  34. #define FACE_FLIP (1 << 1)
  35. #define FACE_TEMP (1 << 2)
  36. static bool bmo_recalc_normal_loop_filter_cb(const BMLoop *l, void *UNUSED(user_data))
  37. {
  38. return BM_edge_is_manifold(l->e);
  39. }
  40. /**
  41. * This uses a more comprehensive test to see if the furthest face from the center
  42. * is pointing towards the center or not.
  43. *
  44. * A simple test could just check the dot product of the faces-normal and the direction from the center,
  45. * however this can fail for faces which make a sharp spike. eg:
  46. *
  47. * <pre>
  48. * +
  49. * |\ <- face
  50. * + +
  51. * \ \
  52. * \ \
  53. * \ +--------------+
  54. * \ |
  55. * \ center -> + |
  56. * \ |
  57. * +------------+
  58. * </pre>
  59. *
  60. * In the example above, the a\ face can point towards the \a center
  61. * which would end up flipping the normals inwards.
  62. *
  63. * To take these spikes into account, find the furthest face-loop-vertex.
  64. */
  65. /**
  66. * \return a face index in \a faces and set \a r_is_flip if the face is flipped away from the center.
  67. */
  68. static int recalc_face_normals_find_index(BMesh *bm, BMFace **faces, const int faces_len, bool *r_is_flip)
  69. {
  70. const float eps = FLT_EPSILON;
  71. float cent_area_accum = 0.0f;
  72. float cent[3];
  73. const float cent_fac = 1.0f / (float)faces_len;
  74. bool is_flip = false;
  75. int f_start_index;
  76. int i;
  77. /* Search for the best loop. Members are compared in-order defined here. */
  78. struct {
  79. /* Squared distance from the center to the loops vertex 'l->v'.
  80. * The normalized direction between the center and this vertex is also used for the dot-products below. */
  81. float dist_sq;
  82. /* Signed dot product using the normalized edge vector,
  83. * (best of 'l->prev->v' or 'l->next->v'). */
  84. float edge_dot;
  85. /* Unsigned dot product using the loop-normal
  86. * (sign is used to check if we need to flip) */
  87. float loop_dot;
  88. } best, test;
  89. UNUSED_VARS_NDEBUG(bm);
  90. zero_v3(cent);
  91. /* first calculate the center */
  92. for (i = 0; i < faces_len; i++) {
  93. float f_cent[3];
  94. const float f_area = BM_face_calc_area(faces[i]);
  95. BM_face_calc_center_mean_weighted(faces[i], f_cent);
  96. madd_v3_v3fl(cent, f_cent, cent_fac * f_area);
  97. cent_area_accum += f_area;
  98. BLI_assert(BMO_face_flag_test(bm, faces[i], FACE_TEMP) == 0);
  99. BLI_assert(BM_face_is_normal_valid(faces[i]));
  100. }
  101. if (cent_area_accum != 0.0f) {
  102. mul_v3_fl(cent, 1.0f / cent_area_accum);
  103. }
  104. /* Distances must start above zero,
  105. * or we can't do meaningful calculations based on the direction to the center */
  106. best.dist_sq = eps;
  107. best.edge_dot = best.loop_dot = -FLT_MAX;
  108. /* used in degenerate cases only */
  109. f_start_index = 0;
  110. /**
  111. * Find the outer-most vertex, comparing distance to the center,
  112. * then the outer-most loop attached to that vertex.
  113. *
  114. * Important this is correctly detected,
  115. * where casting a ray from the center wont hit any loops past this one.
  116. * Otherwise the result may be incorrect.
  117. */
  118. for (i = 0; i < faces_len; i++) {
  119. BMLoop *l_iter, *l_first;
  120. l_iter = l_first = BM_FACE_FIRST_LOOP(faces[i]);
  121. do {
  122. bool is_best_dist_sq;
  123. float dir[3];
  124. sub_v3_v3v3(dir, l_iter->v->co, cent);
  125. test.dist_sq = len_squared_v3(dir);
  126. is_best_dist_sq = (test.dist_sq > best.dist_sq);
  127. if (is_best_dist_sq || (test.dist_sq == best.dist_sq)) {
  128. float edge_dir_pair[2][3];
  129. mul_v3_fl(dir, 1.0f / sqrtf(test.dist_sq));
  130. sub_v3_v3v3(edge_dir_pair[0], l_iter->next->v->co, l_iter->v->co);
  131. sub_v3_v3v3(edge_dir_pair[1], l_iter->prev->v->co, l_iter->v->co);
  132. if ((normalize_v3(edge_dir_pair[0]) > eps) &&
  133. (normalize_v3(edge_dir_pair[1]) > eps))
  134. {
  135. bool is_best_edge_dot;
  136. test.edge_dot = max_ff(dot_v3v3(dir, edge_dir_pair[0]),
  137. dot_v3v3(dir, edge_dir_pair[1]));
  138. is_best_edge_dot = (test.edge_dot > best.edge_dot);
  139. if (is_best_dist_sq || is_best_edge_dot || (test.edge_dot == best.edge_dot)) {
  140. float loop_dir[3];
  141. cross_v3_v3v3(loop_dir, edge_dir_pair[0], edge_dir_pair[1]);
  142. if (normalize_v3(loop_dir) > eps) {
  143. float loop_dir_dot;
  144. /* Highly unlikely the furthest loop is also the concave part of an ngon,
  145. * but it can be contrived with _very_ non-planar faces - so better check. */
  146. if (UNLIKELY(dot_v3v3(loop_dir, l_iter->f->no) < 0.0f)) {
  147. negate_v3(loop_dir);
  148. }
  149. loop_dir_dot = dot_v3v3(dir, loop_dir);
  150. test.loop_dot = fabsf(loop_dir_dot);
  151. if (is_best_dist_sq || is_best_edge_dot || (test.loop_dot > best.loop_dot)) {
  152. best = test;
  153. f_start_index = i;
  154. is_flip = (loop_dir_dot < 0.0f);
  155. }
  156. }
  157. }
  158. }
  159. }
  160. } while ((l_iter = l_iter->next) != l_first);
  161. }
  162. *r_is_flip = is_flip;
  163. return f_start_index;
  164. }
  165. /**
  166. * Given an array of faces, recalculate their normals.
  167. * this functions assumes all faces in the array are connected by edges.
  168. *
  169. * \param bm
  170. * \param faces Array of connected faces.
  171. * \param faces_len Length of \a faces
  172. * \param oflag Flag to check before doing the actual face flipping.
  173. */
  174. static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int faces_len, const short oflag)
  175. {
  176. int i, f_start_index;
  177. const short oflag_flip = oflag | FACE_FLIP;
  178. bool is_flip;
  179. BMFace *f;
  180. BLI_LINKSTACK_DECLARE(fstack, BMFace *);
  181. f_start_index = recalc_face_normals_find_index(bm, faces, faces_len, &is_flip);
  182. if (is_flip) {
  183. BMO_face_flag_enable(bm, faces[f_start_index], FACE_FLIP);
  184. }
  185. /* now that we've found our starting face, make all connected faces
  186. * have the same winding. this is done recursively, using a manual
  187. * stack (if we use simple function recursion, we'd end up overloading
  188. * the stack on large meshes). */
  189. BLI_LINKSTACK_INIT(fstack);
  190. BLI_LINKSTACK_PUSH(fstack, faces[f_start_index]);
  191. BMO_face_flag_enable(bm, faces[f_start_index], FACE_TEMP);
  192. while ((f = BLI_LINKSTACK_POP(fstack))) {
  193. const bool flip_state = BMO_face_flag_test_bool(bm, f, FACE_FLIP);
  194. BMLoop *l_iter, *l_first;
  195. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  196. do {
  197. BMLoop *l_other = l_iter->radial_next;
  198. if ((l_other != l_iter) && bmo_recalc_normal_loop_filter_cb(l_iter, NULL)) {
  199. if (!BMO_face_flag_test(bm, l_other->f, FACE_TEMP)) {
  200. BMO_face_flag_enable(bm, l_other->f, FACE_TEMP);
  201. BMO_face_flag_set(bm, l_other->f, FACE_FLIP, (l_other->v == l_iter->v) != flip_state);
  202. BLI_LINKSTACK_PUSH(fstack, l_other->f);
  203. }
  204. }
  205. } while ((l_iter = l_iter->next) != l_first);
  206. }
  207. BLI_LINKSTACK_FREE(fstack);
  208. /* apply flipping to oflag'd faces */
  209. for (i = 0; i < faces_len; i++) {
  210. if (BMO_face_flag_test(bm, faces[i], oflag_flip) == oflag_flip) {
  211. BM_face_normal_flip(bm, faces[i]);
  212. }
  213. BMO_face_flag_disable(bm, faces[i], FACE_TEMP);
  214. }
  215. }
  216. /*
  217. * put normal to the outside, and set the first direction flags in edges
  218. *
  219. * then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces
  220. * this is in fact the 'select connected'
  221. *
  222. * in case all faces were not done: start over with 'find the ultimate ...' */
  223. void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op)
  224. {
  225. int *groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totface, __func__);
  226. BMFace **faces_grp = MEM_mallocN(sizeof(*faces_grp) * bm->totface, __func__);
  227. int (*group_index)[2];
  228. const int group_tot = BM_mesh_calc_face_groups(
  229. bm, groups_array, &group_index,
  230. bmo_recalc_normal_loop_filter_cb, NULL,
  231. 0, BM_EDGE);
  232. int i;
  233. BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG);
  234. BM_mesh_elem_table_ensure(bm, BM_FACE);
  235. for (i = 0; i < group_tot; i++) {
  236. const int fg_sta = group_index[i][0];
  237. const int fg_len = group_index[i][1];
  238. int j;
  239. bool is_calc = false;
  240. for (j = 0; j < fg_len; j++) {
  241. faces_grp[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
  242. if (is_calc == false) {
  243. is_calc = BMO_face_flag_test_bool(bm, faces_grp[j], FACE_FLAG);
  244. }
  245. }
  246. if (is_calc) {
  247. bmo_recalc_face_normals_array(bm, faces_grp, fg_len, FACE_FLAG);
  248. }
  249. }
  250. MEM_freeN(faces_grp);
  251. MEM_freeN(groups_array);
  252. MEM_freeN(group_index);
  253. }