bmo_planar_faces.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. * ***** END GPL LICENSE BLOCK *****
  19. */
  20. /** \file blender/bmesh/operators/bmo_planar_faces.c
  21. * \ingroup bmesh
  22. *
  23. * Iteratively flatten 4+ sided faces.
  24. */
  25. #include "MEM_guardedalloc.h"
  26. #include "BLI_math.h"
  27. #include "BLI_ghash.h"
  28. #include "bmesh.h"
  29. #include "intern/bmesh_operators_private.h" /* own include */
  30. #define ELE_VERT_ADJUST (1 << 0)
  31. #define ELE_FACE_ADJUST (1 << 1)
  32. struct VertAccum {
  33. float co[3];
  34. int co_tot;
  35. };
  36. void bmo_planar_faces_exec(BMesh *bm, BMOperator *op)
  37. {
  38. const float fac = BMO_slot_float_get(op->slots_in, "factor");
  39. const int iterations = BMO_slot_int_get(op->slots_in, "iterations");
  40. const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces");
  41. const float eps = 0.00001f;
  42. const float eps_sq = SQUARE(eps);
  43. BMOIter oiter;
  44. BMFace *f;
  45. BLI_mempool *vert_accum_pool;
  46. GHash *vaccum_map;
  47. float (*faces_center)[3];
  48. int i, iter_step, shared_vert_num;
  49. faces_center = MEM_mallocN(sizeof(*faces_center) * faces_num, __func__);
  50. shared_vert_num = 0;
  51. BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
  52. BMLoop *l_iter, *l_first;
  53. if (f->len == 3) {
  54. continue;
  55. }
  56. BM_face_calc_center_mean_weighted(f, faces_center[i]);
  57. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  58. do {
  59. if (!BMO_vert_flag_test(bm, l_iter->v, ELE_VERT_ADJUST)) {
  60. BMO_vert_flag_enable(bm, l_iter->v, ELE_VERT_ADJUST);
  61. shared_vert_num += 1;
  62. }
  63. } while ((l_iter = l_iter->next) != l_first);
  64. BMO_face_flag_enable(bm, f, ELE_FACE_ADJUST);
  65. }
  66. vert_accum_pool = BLI_mempool_create(sizeof(struct VertAccum), 0, 512, BLI_MEMPOOL_NOP);
  67. vaccum_map = BLI_ghash_ptr_new_ex(__func__, shared_vert_num);
  68. for (iter_step = 0; iter_step < iterations; iter_step++) {
  69. GHashIterator gh_iter;
  70. bool changed = false;
  71. BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
  72. BMLoop *l_iter, *l_first;
  73. float plane[4];
  74. if (!BMO_face_flag_test(bm, f, ELE_FACE_ADJUST)) {
  75. continue;
  76. }
  77. BMO_face_flag_disable(bm, f, ELE_FACE_ADJUST);
  78. BLI_assert(f->len != 3);
  79. /* keep original face data (else we 'move' the face) */
  80. #if 0
  81. BM_face_normal_update(f);
  82. BM_face_calc_center_mean_weighted(f, f_center);
  83. #endif
  84. plane_from_point_normal_v3(plane, faces_center[i], f->no);
  85. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  86. do {
  87. struct VertAccum *va;
  88. void **va_p;
  89. float co[3];
  90. if (!BLI_ghash_ensure_p(vaccum_map, l_iter->v, &va_p)) {
  91. *va_p = BLI_mempool_calloc(vert_accum_pool);
  92. }
  93. va = *va_p;
  94. closest_to_plane_normalized_v3(co, plane, l_iter->v->co);
  95. va->co_tot += 1;
  96. interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot);
  97. } while ((l_iter = l_iter->next) != l_first);
  98. }
  99. GHASH_ITER (gh_iter, vaccum_map) {
  100. BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
  101. struct VertAccum *va = BLI_ghashIterator_getValue(&gh_iter);
  102. BMIter iter;
  103. if (len_squared_v3v3(v->co, va->co) > eps_sq) {
  104. BMO_vert_flag_enable(bm, v, ELE_VERT_ADJUST);
  105. interp_v3_v3v3(v->co, v->co, va->co, fac);
  106. changed = true;
  107. }
  108. /* tag for re-calculation */
  109. BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
  110. if (f->len != 3) {
  111. BMO_face_flag_enable(bm, f, ELE_FACE_ADJUST);
  112. }
  113. }
  114. }
  115. /* if nothing changed, break out early */
  116. if (changed == false) {
  117. break;
  118. }
  119. BLI_ghash_clear(vaccum_map, NULL, NULL);
  120. BLI_mempool_clear(vert_accum_pool);
  121. }
  122. MEM_freeN(faces_center);
  123. BLI_ghash_free(vaccum_map, NULL, NULL);
  124. BLI_mempool_destroy(vert_accum_pool);
  125. }