modifiers_bmesh.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. * The Original Code is Copyright (C) 2005 by the Blender Foundation.
  19. * All rights reserved.
  20. *
  21. * Contributor(s): Joseph Eagar
  22. *
  23. * ***** END GPL LICENSE BLOCK *****
  24. *
  25. */
  26. /** \file blender/blenkernel/intern/modifiers_bmesh.c
  27. * \ingroup bke
  28. */
  29. #include "MEM_guardedalloc.h"
  30. #include "BLI_math.h"
  31. #include "BLI_alloca.h"
  32. #include "BKE_DerivedMesh.h"
  33. #include "BKE_editmesh.h"
  34. /* Static function for alloc */
  35. static BMFace *bm_face_create_from_mpoly(
  36. MPoly *mp, MLoop *ml,
  37. BMesh *bm, BMVert **vtable, BMEdge **etable)
  38. {
  39. BMVert **verts = BLI_array_alloca(verts, mp->totloop);
  40. BMEdge **edges = BLI_array_alloca(edges, mp->totloop);
  41. int j;
  42. for (j = 0; j < mp->totloop; j++, ml++) {
  43. verts[j] = vtable[ml->v];
  44. edges[j] = etable[ml->e];
  45. }
  46. return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD);
  47. }
  48. /**
  49. * The main function for copying DerivedMesh data into BMesh.
  50. *
  51. * \note The mesh may already have geometry. see 'is_init'
  52. */
  53. void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
  54. {
  55. MVert *mv, *mvert;
  56. MEdge *me, *medge;
  57. MPoly /* *mpoly, */ /* UNUSED */ *mp;
  58. MLoop *mloop;
  59. BMVert *v, **vtable;
  60. BMEdge *e, **etable;
  61. float (*face_normals)[3];
  62. BMFace *f;
  63. int i, j, totvert, totedge /* , totface */ /* UNUSED */ ;
  64. bool is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0);
  65. bool is_cddm = (dm->type == DM_TYPE_CDDM); /* duplicate the arrays for non cddm */
  66. char has_orig_htype = 0;
  67. int cd_vert_bweight_offset;
  68. int cd_edge_bweight_offset;
  69. int cd_edge_crease_offset;
  70. if (is_init == false) {
  71. /* check if we have an origflag */
  72. has_orig_htype |= CustomData_has_layer(&bm->vdata, CD_ORIGINDEX) ? BM_VERT : 0;
  73. has_orig_htype |= CustomData_has_layer(&bm->edata, CD_ORIGINDEX) ? BM_EDGE : 0;
  74. has_orig_htype |= CustomData_has_layer(&bm->pdata, CD_ORIGINDEX) ? BM_FACE : 0;
  75. }
  76. /*merge custom data layout*/
  77. CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT);
  78. CustomData_bmesh_merge(&dm->edgeData, &bm->edata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_EDGE);
  79. CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_LOOP);
  80. CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_FACE);
  81. if (is_init) {
  82. BM_mesh_cd_flag_apply(bm, dm->cd_flag);
  83. }
  84. cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
  85. cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
  86. cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
  87. totvert = dm->getNumVerts(dm);
  88. totedge = dm->getNumEdges(dm);
  89. /* totface = dm->getNumPolys(dm); */ /* UNUSED */
  90. vtable = MEM_mallocN(sizeof(*vtable) * totvert, __func__);
  91. etable = MEM_mallocN(sizeof(*etable) * totedge, __func__);
  92. /*do verts*/
  93. mv = mvert = is_cddm ? dm->getVertArray(dm) : dm->dupVertArray(dm);
  94. for (i = 0; i < totvert; i++, mv++) {
  95. v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD);
  96. normal_short_to_float_v3(v->no, mv->no);
  97. v->head.hflag = BM_vert_flag_from_mflag(mv->flag);
  98. BM_elem_index_set(v, i); /* set_inline */
  99. CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data, true);
  100. vtable[i] = v;
  101. /* add bevel weight */
  102. if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mv->bweight / 255.0f);
  103. if (UNLIKELY(has_orig_htype & BM_VERT)) {
  104. int *orig_index = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_ORIGINDEX);
  105. *orig_index = ORIGINDEX_NONE;
  106. }
  107. }
  108. if (!is_cddm) MEM_freeN(mvert);
  109. if (is_init) bm->elem_index_dirty &= ~BM_VERT;
  110. /*do edges*/
  111. me = medge = is_cddm ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm);
  112. for (i = 0; i < totedge; i++, me++) {
  113. //BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL);
  114. e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD);
  115. e->head.hflag = BM_edge_flag_from_mflag(me->flag);
  116. BM_elem_index_set(e, i); /* set_inline */
  117. CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data, true);
  118. etable[i] = e;
  119. if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)me->bweight / 255.0f);
  120. if (cd_edge_crease_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)me->crease / 255.0f);
  121. if (UNLIKELY(has_orig_htype & BM_EDGE)) {
  122. int *orig_index = CustomData_bmesh_get(&bm->edata, e->head.data, CD_ORIGINDEX);
  123. *orig_index = ORIGINDEX_NONE;
  124. }
  125. }
  126. if (!is_cddm) MEM_freeN(medge);
  127. if (is_init) bm->elem_index_dirty &= ~BM_EDGE;
  128. /* do faces */
  129. /* note: i_alt is aligned with bmesh faces which may not always align with mpolys */
  130. mp = dm->getPolyArray(dm);
  131. mloop = dm->getLoopArray(dm);
  132. face_normals = (dm->dirty & DM_DIRTY_NORMALS) ? NULL : CustomData_get_layer(&dm->polyData, CD_NORMAL);
  133. for (i = 0; i < dm->numPolyData; i++, mp++) {
  134. BMLoop *l_iter;
  135. BMLoop *l_first;
  136. f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart,
  137. bm, vtable, etable);
  138. if (UNLIKELY(f == NULL)) {
  139. continue;
  140. }
  141. f->head.hflag = BM_face_flag_from_mflag(mp->flag);
  142. BM_elem_index_set(f, bm->totface - 1); /* set_inline */
  143. f->mat_nr = mp->mat_nr;
  144. j = mp->loopstart;
  145. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  146. do {
  147. /* Save index of correspsonding MLoop */
  148. CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, j, &l_iter->head.data, true);
  149. BM_elem_index_set(l_iter, j++); /* set_inline */
  150. } while ((l_iter = l_iter->next) != l_first);
  151. CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data, true);
  152. if (calc_face_normal) {
  153. if (face_normals) {
  154. copy_v3_v3(f->no, face_normals[i]);
  155. }
  156. else {
  157. BM_face_normal_update(f);
  158. }
  159. }
  160. if (UNLIKELY(has_orig_htype & BM_FACE)) {
  161. int *orig_index = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_ORIGINDEX);
  162. *orig_index = ORIGINDEX_NONE;
  163. }
  164. }
  165. if (is_init) bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
  166. MEM_freeN(vtable);
  167. MEM_freeN(etable);
  168. }
  169. /* converts a cddm to a BMEditMesh. if existing is non-NULL, the
  170. * new geometry will be put in there.*/
  171. BMEditMesh *DM_to_editbmesh(DerivedMesh *dm, BMEditMesh *existing, const bool do_tessellate)
  172. {
  173. BMEditMesh *em = existing;
  174. BMesh *bm;
  175. if (em) {
  176. bm = em->bm;
  177. }
  178. else {
  179. bm = BM_mesh_create(
  180. &bm_mesh_allocsize_default,
  181. &((struct BMeshCreateParams){.use_toolflags = false,}));
  182. }
  183. DM_to_bmesh_ex(dm, bm, do_tessellate);
  184. if (!em) {
  185. em = BKE_editmesh_create(bm, do_tessellate);
  186. }
  187. else {
  188. if (do_tessellate) {
  189. BKE_editmesh_tessface_calc(em);
  190. }
  191. }
  192. return em;
  193. }
  194. BMesh *DM_to_bmesh(DerivedMesh *dm, const bool calc_face_normal)
  195. {
  196. BMesh *bm;
  197. const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_DM(dm);
  198. bm = BM_mesh_create(
  199. &allocsize,
  200. &((struct BMeshCreateParams){.use_toolflags = false,}));
  201. DM_to_bmesh_ex(dm, bm, calc_face_normal);
  202. return bm;
  203. }