Style Cleanup
[blender-staging.git] / source / blender / bmesh / intern / bmesh_to_editmesh.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  * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/bmesh/intern/bmesh_to_editmesh.c
24  *  \ingroup bmesh
25  *
26  * Unused
27  */
28
29 #if 0
30 #include "MEM_guardedalloc.h"
31 #include "BKE_customdata.h" 
32 #include "DNA_listBase.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 #include <string.h>
37 #include "BKE_utildefines.h"
38 #include "BKE_mesh.h"
39 #include "BKE_global.h"
40 #include "BKE_DerivedMesh.h"
41 #include "BKE_cdderivedmesh.h"
42
43 #include "BLI_editVert.h"
44 #include "mesh_intern.h"
45 #include "ED_mesh.h"
46
47 #include "BLI_edgehash.h"
48 #include "BLI_array.h"
49 #include "BLI_array.h"
50
51 #include "bmesh.h"
52
53 /*
54  * BMESH TO EDITMESH
55  *
56  * This file contains functions for converting 
57  * from a bmesh to an editmesh
58  *
59 */
60
61 /*
62  * LOOPS TO EDITMESH CORNERS
63  *
64  * Converts N-Gon loop (face-edge)
65  * data (UVs, Verts Colors, ect) to
66  * face corner data.
67  *
68 */
69
70 static void loops_to_editmesh_corners(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex)
71 {
72         int i, j;
73         BMLoop *l;
74         MTFace *texface;
75         MTexPoly *texpoly;
76         MCol *mcol;
77         MLoopCol *mloopcol;
78         MLoopUV *mloopuv;
79
80         for(i=0; i < numTex; i++) {
81                 texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
82                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
83                 
84                 texface->tpage = texpoly->tpage;
85                 texface->flag = texpoly->flag;
86                 texface->transp = texpoly->transp;
87                 texface->mode = texpoly->mode;
88                 texface->tile = texpoly->tile;
89                 texface->unwrap = texpoly->unwrap;
90
91                 j = 0;
92                 l = f->loopbase;
93                 do {
94                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
95                         texface->uv[j][0] = mloopuv->uv[0];
96                         texface->uv[j][1] = mloopuv->uv[1];
97                         j++;
98                         l = ((l->next));
99                 } while(l!=f->lbase);
100
101         }
102
103         for(i=0; i < numCol; i++) {
104                 mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
105                 j = 0;
106                 l = f->loopbase;
107                 do {
108                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
109                         mcol[j].r = mloopcol->r;
110                         mcol[j].g = mloopcol->g;
111                         mcol[j].b = mloopcol->b;
112                         mcol[j].a = mloopcol->a;
113                         j++;
114                         l = ((l->next));
115                 } while(l!=f->lbase);
116         }
117 }
118
119 static EditVert *bmeshvert_to_editvert(BMesh *bm, EditMesh *em, BMVert *v, int index, EditVert **evlist)
120 {
121         EditVert *eve = NULL;
122
123         v->head.eflag1 = index; /*abuse!*/
124         eve = addvertlist(em, v->co, NULL);
125         eve->keyindex = index;
126         evlist[index]= eve;
127         
128         /*copy flags*/
129         if(v->head.flag & BM_HIDDEN) eve->h = 1;
130         if (v->head.flag & BM_SELECT) eve->f |= SELECT;
131
132         eve->bweight = v->bweight;
133         CustomData_em_copy_data(&bm->vdata, &em->vdata, v->head.data, &eve->data);
134         /*copy normal*/
135         eve->no[0] = v->no[0];
136         eve->no[1] = v->no[1];
137         eve->no[2] = v->no[2];
138
139         return eve;
140 }
141
142 static void bmeshedge_to_editedge_internal(BMesh *bm, EditMesh *em, BMEdge *e, EditEdge *eed)
143 {
144         eed->crease = e->crease;
145         eed->bweight = e->bweight;
146         
147         //copy relavent flags
148         if (e->head.flag & BM_SELECT) eed->f |= SELECT;
149         if (e->head.flag & BM_SEAM) eed->seam = 1;
150         if (e->head.flag & BM_SHARP) eed->sharp = 1;
151         if (e->head.flag & BM_HIDDEN) eed->h = 1;
152         if (e->head.flag & BM_FGON) eed->h |= EM_FGON;
153
154         CustomData_em_copy_data(&bm->edata, &em->edata, e->head.data, &eed->data);
155 }
156
157 static EditEdge *bmeshedge_to_editedge(BMesh *bm, EditMesh *em, BMEdge *e, EditVert **evlist)
158 {
159         EditEdge *eed = NULL;
160
161         if(!(findedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1]))) {
162                 eed= addedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1], NULL);
163                 bmeshedge_to_editedge_internal(bm, em, e, eed);
164         }
165
166         return eed;
167 }
168
169 static EditFace *bmeshface_to_editface(BMesh *bm, EditMesh *em, BMFace *f, EditVert **evlist, int numCol, int numTex)
170 {
171         EditVert *eve1, *eve2, *eve3, *eve4;
172         EditFace *efa = NULL;
173         int len;
174         
175         len = f->len;
176
177         eve1= evlist[f->lbase->v->head.eflag1];
178         eve2= evlist[((f->lbase->next))->v->head.eflag1];
179         eve3= evlist[((f->lbase->next->next))->v->head.eflag1];
180         if (len == 4) {
181                 eve4= evlist[ ((f->lbase->prev))->v->head.eflag1];
182         }
183         else {
184                 eve4= NULL;
185         }
186         
187         if (eve1==eve2 || eve1==eve3 || eve1==eve4 || eve2==eve3 || eve3==eve4
188             || eve2==eve4) return NULL;
189
190         efa = addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
191         if (!efa) return NULL;
192
193         bmeshedge_to_editedge_internal(bm, em, f->lbase->e, efa->e1);
194         bmeshedge_to_editedge_internal(bm, em, ((f->lbase->next))->e, efa->e2);
195         bmeshedge_to_editedge_internal(bm, em, ((f->lbase->next->next))->e, efa->e3);
196         if(eve4)
197                 bmeshedge_to_editedge_internal(bm, em, ((f->lbase->prev))->e, efa->e4);
198
199         efa->mat_nr = (unsigned char)f->mat_nr;
200
201         /*Copy normal*/
202         efa->n[0] = f->no[0];
203         efa->n[1] = f->no[1];
204         efa->n[2] = f->no[2];
205         
206         //copy relavent original flags
207         if (f->head.flag & BM_SELECT) efa->f |= SELECT;
208         if (f->head.flag & BM_HIDDEN) efa->h = 1;
209         if (f->head.flag & BM_SMOOTH) efa->flag |= ME_SMOOTH;
210         if (f->head.flag & BM_ACTIVE) EM_set_actFace(em, efa);
211
212         CustomData_em_copy_data(&bm->pdata, &em->fdata, f->head.data, &efa->data);
213         loops_to_editmesh_corners(bm, &em->fdata, efa->data, f, numCol,numTex);
214         
215         return efa;
216 }
217
218 EditMesh *bmesh_to_editmesh_intern(BMesh *bm) 
219 {
220         BMVert *v;
221         BMEdge *e;
222         BMFace *f;
223
224         BMIter verts;
225         BMIter edges;
226         BMIter faces;
227
228         EditMesh *em;
229         EditVert *eve, **evlist;
230
231         int totvert, i, numTex, numCol, flag;
232
233         em = MEM_callocN(sizeof(EditMesh), "EditMesh from bmesh");
234
235         em->selectmode = bm->selectmode;
236
237         flag = CD_MASK_BMESH & ~CD_MASK_MTEXPOLY;
238
239         CustomData_copy(&bm->vdata, &em->vdata, flag, CD_CALLOC, 0);
240         CustomData_copy(&bm->edata, &em->edata, flag, CD_CALLOC, 0);
241         CustomData_copy(&bm->pdata, &em->fdata, flag, CD_CALLOC, 0);
242         CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0);
243         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
244         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
245
246         totvert = BM_Count_Element(bm, BM_VERT);
247         evlist= MEM_mallocN(totvert*sizeof(EditVert *),"evlist");
248
249         /* make vertices */
250         for(i=0, v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts), i++) 
251                 eve = bmeshvert_to_editvert(bm, em, v, i, evlist);
252
253         /* make edges */
254         for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
255                 bmeshedge_to_editedge(bm, em, e, evlist);
256
257         /* make faces */
258         for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
259                 bmeshface_to_editface(bm, em, f, evlist, numCol, numTex);
260                         
261         MEM_freeN(evlist);
262
263         EM_fgon_flags(em);
264
265         EM_nvertices_selected(em);
266         EM_nedges_selected(em);
267         EM_nfaces_selected(em);
268
269         return em;
270 }
271
272 void bmesh2edit_exec(BMesh *bmesh, BMOperator *op)
273 {
274         BMO_Set_Pnt(op, "emout", bmesh_to_editmesh_intern(bmesh));
275 }
276
277 #define FACE_NGON       1
278
279 void bmesh_make_fgons_exec(BMesh *bmesh, BMOperator *op)
280 {
281         BMOperator triop;
282         BMFace *face;
283         BMIter iter, liter;
284         BMEdge *edge;
285         BMLoop *l, *nl;
286         BMOpSlot *eout;
287         int i, trifan = BMO_Get_Int(op, "trifan");
288
289         if (!trifan) BMO_Init_Op(&triop, "triangulate");
290         
291         /* instead of properly tesselate, just make a triangle fan, this
292          * should make bmesh -> editmesh -> bmesh conversions always properly
293          * work. */
294         for (face = BMIter_New(&iter, bmesh, BM_FACES_OF_MESH, NULL); face; face=BMIter_Step(&iter)) {
295                 if (face->len > 4) {
296                         BMO_SetFlag(bmesh, face, FACE_NGON);
297                         if (trifan) {
298                                 while (face->len > 4) {
299                                         face = BM_Split_Face(bmesh, face, 
300                                                 face->lbase->v, 
301                                                 (face->lbase->next->next)->v,
302                                                 &nl, NULL);
303                                         BM_SetHFlag(nl->e, BM_FGON);
304                                 }
305                         }
306                 }
307         }
308
309         if (!trifan) {
310                 BMO_Flag_To_Slot(bmesh, &triop, "faces", FACE_NGON, BM_FACE);
311                 BMO_Exec_Op(bmesh, &triop);
312
313                 eout = BMO_GetSlot(&triop, "edgeout");
314                 for (i=0; i<eout->len; i++) {
315                         edge = ((BMEdge**)eout->data.buf)[i];
316                         edge->head.flag |= BM_FGON;
317                         face = BMIter_New(&iter, bmesh, BM_FACES_OF_EDGE, edge);
318                         
319                         for (; face; face=BMIter_Step(&iter)) {
320                                 face->head.flag |= BM_NONORMCALC;
321                         }
322                 }
323
324                 BMO_Finish_Op(bmesh, &triop);
325         }
326 }
327
328 EditMesh *bmesh_to_editmesh(BMesh *bmesh)
329 {
330         BMOperator conv, makefgon;
331         EditMesh *em;
332         
333         /*first fgon-afy the mesh*/
334         BMO_Init_Op(&makefgon, "makefgon");
335         BMO_Set_Int(&makefgon, "trifan", 1);
336         BMO_Exec_Op(bmesh, &makefgon);
337         BMO_Finish_Op(bmesh, &makefgon);
338
339         BMO_Init_Op(&conv, "bmesh_to_editmesh");
340         BMO_Exec_Op(bmesh, &conv);
341         em = BMO_Get_Pnt(&conv, "emout");
342         BMO_Finish_Op(bmesh, &conv);
343         
344         return em;
345 }
346 #endif