b8e4a7ff78dee98118900dfd501e44edaa1534ef
[blender-staging.git] / source / blender / blenkernel / intern / modifiers_bmesh.c
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
27 /** \file blender/blenkernel/intern/modifiers_bmesh.c
28  *  \ingroup bke
29  */
30
31 #include "BLI_math.h"
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_object_types.h"
36
37 #include "BLI_array.h"
38
39 #include "BKE_DerivedMesh.h"
40 #include "BKE_bmesh.h"
41 #include "BKE_tessmesh.h"
42
43 /* main function for copying DerivedMesh data into BMesh */
44 void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
45 {
46         MVert *mv, *mvert;
47         MEdge *me, *medge;
48         MPoly /* *mpoly, */ /* UNUSED */ *mp;
49         MLoop *mloop, *ml;
50         BMVert *v, **vtable, **verts = NULL;
51         BMEdge *e, **etable, **edges = NULL;
52         BMFace *f;
53         BMIter liter;
54         BLI_array_declare(verts);
55         BLI_array_declare(edges);
56         int i, j, k, totvert, totedge /* , totface */ /* UNUSED */ ;
57
58         /*merge custom data layout*/
59         CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT);
60         CustomData_bmesh_merge(&dm->edgeData, &bm->edata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_EDGE);
61         CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_LOOP);
62         CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_FACE);
63
64         totvert = dm->getNumVerts(dm);
65         totedge = dm->getNumEdges(dm);
66         /* totface = dm->getNumPolys(dm); */ /* UNUSED */
67
68         vtable = MEM_callocN(sizeof(void**) * totvert, "vert table in BMDM_Copy");
69         etable = MEM_callocN(sizeof(void**) * totedge, "edge table in BMDM_Copy");
70
71         /*do verts*/
72         mv = mvert = dm->dupVertArray(dm);
73         for (i = 0; i < totvert; i++, mv++) {
74                 v = BM_vert_create(bm, mv->co, NULL);
75                 normal_short_to_float_v3(v->no, mv->no);
76                 v->head.hflag = BM_vert_flag_from_mflag(mv->flag);
77
78                 CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data);
79                 vtable[i] = v;
80         }
81         MEM_freeN(mvert);
82
83         /*do edges*/
84         me = medge = dm->dupEdgeArray(dm);
85         for (i = 0; i < totedge; i++, me++) {
86                 e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, FALSE);
87
88                 e->head.hflag = BM_edge_flag_from_mflag(me->flag);
89
90                 CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data);
91                 etable[i] = e;
92         }
93         MEM_freeN(medge);
94
95         /*do faces*/
96         /* mpoly = mp = dm->getPolyArray(dm); */ /* UNUSED */
97         mloop = dm->getLoopArray(dm);
98         for (i = 0; i < dm->numPolyData; i++, mp++) {
99                 BMLoop *l;
100
101                 BLI_array_empty(verts);
102                 BLI_array_empty(edges);
103
104                 BLI_array_growitems(verts, mp->totloop);
105                 BLI_array_growitems(edges, mp->totloop);
106
107                 ml = mloop + mp->loopstart;
108                 for (j = 0; j < mp->totloop; j++, ml++) {
109
110                         verts[j] = vtable[ml->v];
111                         edges[j] = etable[ml->e];
112                 }
113
114                 f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, FALSE);
115
116                 if (!f)
117                         continue;
118
119                 f->head.hflag = BM_face_flag_from_mflag(mp->flag);
120                 f->mat_nr = mp->mat_nr;
121
122                 l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
123                 k = mp->loopstart;
124
125                 for (j = 0; l; l = BM_iter_step(&liter), k++) {
126                         CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data);
127                 }
128
129                 CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data);
130         }
131
132         MEM_freeN(vtable);
133         MEM_freeN(etable);
134
135         BLI_array_free(verts);
136         BLI_array_free(edges);
137 }
138
139 /* converts a cddm to a BMEditMesh.  if existing is non-NULL, the
140  * new geometry will be put in there.*/
141 BMEditMesh *DM_to_editbmesh(Object *ob, DerivedMesh *dm, BMEditMesh *existing, int do_tesselate)
142 {
143         BMEditMesh *em = existing;
144         BMesh *bm;
145
146         if (em) {
147                 bm = em->bm;
148         }
149         else {
150                 bm = BM_mesh_create(ob, &bm_mesh_allocsize_default);
151         }
152
153         DM_to_bmesh_ex(dm, bm);
154
155         if (!em) {
156                 em = BMEdit_Create(bm, do_tesselate);
157         }
158         else {
159                 if (do_tesselate) {
160                         BMEdit_RecalcTessellation(em);
161                 }
162         }
163
164         return em;
165 }
166
167 BMesh *DM_to_bmesh(Object *ob, DerivedMesh *dm)
168 {
169         BMesh *bm;
170
171         bm = BM_mesh_create(ob, &bm_mesh_allocsize_default);
172
173         DM_to_bmesh_ex(dm, bm);
174
175         return bm;
176 }