svn merge -r 30954:31059 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / blenkernel / intern / BME_conversions.c
1 /**
2  * BME_mesh.c    jan 2007
3  *
4  *      BMesh mesh level functions.
5  *
6  * $Id$
7  *
8  * ***** BEGIN GPL LICENSE BLOCK *****
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * about this.  
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * The Original Code is Copyright (C) 2007 Blender Foundation.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): Geoffrey Bantle, Levi Schooley.
31  *
32  * ***** END GPL LICENSE BLOCK *****
33  */
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_scene_types.h"
40
41 #include "BKE_mesh.h"
42 #include "BKE_cdderivedmesh.h"
43
44 #include "BLI_edgehash.h"
45 //XXX #include "BIF_editmesh.h"
46 //XXX #include "editmesh.h"
47 #include "bmesh_private.h"
48
49 //XXX #include "BSE_edit.h"
50
51 /* XXX IMPORTANT: editmesh stuff doesn't belong in kernel! (ton) */
52
53 /*merge these functions*/
54 static void BME_DMcorners_to_loops(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f, int numCol, int numTex){
55         int i, j;
56         BME_Loop *l;
57         MTFace *texface;
58         MTexPoly *texpoly;
59         MCol *mcol;
60         MLoopCol *mloopcol;
61         MLoopUV *mloopuv;
62
63         for(i=0; i< numTex; i++){
64                 texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
65                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
66
67                 texpoly->tpage = texface[index].tpage;
68                 texpoly->flag = texface[index].flag;
69                 texpoly->transp = texface[index].transp;
70                 texpoly->mode = texface[index].mode;
71                 texpoly->tile = texface[index].tile;
72                 texpoly->unwrap = texface[index].unwrap;
73
74                 j = 0;
75                 l = f->loopbase;
76                 do{
77                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
78                         mloopuv->uv[0] = texface[index].uv[j][0];
79                         mloopuv->uv[1] = texface[index].uv[j][1];
80                         j++;
81                         l = l->next;
82                 }while(l!=f->loopbase);
83         }
84
85         for(i=0; i < numCol; i++){
86                 mcol = CustomData_get_layer_n(facedata, CD_MCOL, i);
87                 j = 0;
88                 l = f->loopbase;
89                 do{
90                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
91                         mloopcol->r = mcol[(index*4)+j].r;
92                         mloopcol->g = mcol[(index*4)+j].g;
93                         mloopcol->b = mcol[(index*4)+j].b;
94                         mloopcol->a = mcol[(index*4)+j].a;
95                         j++;
96                         l = l->next;
97                 }while(l!=f->loopbase);
98         }
99 }
100
101 static void BME_DMloops_to_corners(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f,int numCol, int numTex){
102         int i, j;
103         BME_Loop *l;
104         MTFace *texface;
105         MTexPoly *texpoly;
106         MCol *mcol;
107         MLoopCol *mloopcol;
108         MLoopUV *mloopuv;
109
110         for(i=0; i < numTex; i++){
111                 texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
112                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
113                 
114                 texface[index].tpage = texpoly->tpage;
115                 texface[index].flag = texpoly->flag;
116                 texface[index].transp = texpoly->transp;
117                 texface[index].mode = texpoly->mode;
118                 texface[index].tile = texpoly->tile;
119                 texface[index].unwrap = texpoly->unwrap;
120
121                 j = 0;
122                 l = f->loopbase;
123                 do{
124                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
125                         texface[index].uv[j][0] = mloopuv->uv[0];
126                         texface[index].uv[j][1] = mloopuv->uv[1];
127                         j++;
128                         l = l->next;
129                 }while(l!=f->loopbase);
130
131         }
132         for(i=0; i < numCol; i++){
133                 mcol = CustomData_get_layer_n(facedata,CD_MCOL, i);
134                 j = 0;
135                 l = f->loopbase;
136                 do{
137                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
138                         mcol[(index*4) + j].r = mloopcol->r;
139                         mcol[(index*4) + j].g = mloopcol->g;
140                         mcol[(index*4) + j].b = mloopcol->b;
141                         mcol[(index*4) + j].a = mloopcol->a;
142                         j++;
143                         l = l->next;
144                 }while(l!=f->loopbase);
145         }
146 }
147
148
149 static void BME_corners_to_loops(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){
150         int i, j;
151         BME_Loop *l;
152         MTFace *texface;
153         MTexPoly *texpoly;
154         MCol *mcol;
155         MLoopCol *mloopcol;
156         MLoopUV *mloopuv;
157
158         for(i=0; i < numTex; i++){
159                 texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
160                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
161                 
162                 texpoly->tpage = texface->tpage;
163                 texpoly->flag = texface->flag;
164                 texpoly->transp = texface->transp;
165                 texpoly->mode = texface->mode;
166                 texpoly->tile = texface->tile;
167                 texpoly->unwrap = texface->unwrap;
168
169                 j = 0;
170                 l = f->loopbase;
171                 do{
172                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
173                         mloopuv->uv[0] = texface->uv[j][0];
174                         mloopuv->uv[1] = texface->uv[j][1];
175                         j++;
176                         l = l->next;
177                 }while(l!=f->loopbase);
178
179         }
180         for(i=0; i < numCol; i++){
181                 mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
182                 j = 0;
183                 l = f->loopbase;
184                 do{
185                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
186                         mloopcol->r = mcol[j].r;
187                         mloopcol->g = mcol[j].g;
188                         mloopcol->b = mcol[j].b;
189                         mloopcol->a = mcol[j].a;
190                         j++;
191                         l = l->next;
192                 }while(l!=f->loopbase);
193         }
194 }
195
196 static void BME_loops_to_corners(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){
197         int i, j;
198         BME_Loop *l;
199         MTFace *texface;
200         MTexPoly *texpoly;
201         MCol *mcol;
202         MLoopCol *mloopcol;
203         MLoopUV *mloopuv;
204
205         for(i=0; i < numTex; i++){
206                 texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
207                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
208                 
209                 texface->tpage = texpoly->tpage;
210                 texface->flag = texpoly->flag;
211                 texface->transp = texpoly->transp;
212                 texface->mode = texpoly->mode;
213                 texface->tile = texpoly->tile;
214                 texface->unwrap = texpoly->unwrap;
215
216                 j = 0;
217                 l = f->loopbase;
218                 do{
219                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
220                         texface->uv[j][0] = mloopuv->uv[0];
221                         texface->uv[j][1] = mloopuv->uv[1];
222                         j++;
223                         l = l->next;
224                 }while(l!=f->loopbase);
225
226         }
227         for(i=0; i < numCol; i++){
228                 mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
229                 j = 0;
230                 l = f->loopbase;
231                 do{
232                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
233                         mcol[j].r = mloopcol->r;
234                         mcol[j].g = mloopcol->g;
235                         mcol[j].b = mloopcol->b;
236                         mcol[j].a = mloopcol->a;
237                         j++;
238                         l = l->next;
239                 }while(l!=f->loopbase);
240         }
241 }
242 /*move the EditMesh conversion functions to editmesh_tools.c*/
243 BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
244         BME_Mesh *bm;
245         int allocsize[4] = {512,512,2048,512}, numTex, numCol;
246         BME_Vert *v1, *v2;
247         BME_Edge *e, *edar[4];
248         BME_Poly *f;
249
250         EditVert *eve;
251         EditEdge *eed;
252         EditFace *efa;
253
254         int len;
255         bm = BME_make_mesh(allocsize);
256
257         /*copy custom data layout*/
258         CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
259         CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
260         CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
261
262         /*copy face corner data*/
263         CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
264         /*initialize memory pools*/
265         CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
266         CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
267         CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
268         CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
269         /*needed later*/
270         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
271         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
272
273         BME_model_begin(bm);
274         /*add verts*/
275         eve= em->verts.first;
276         while(eve) {
277                 v1 = BME_MV(bm,eve->co);
278                 VECCOPY(v1->no,eve->no);
279                 v1->flag = eve->f;
280                 v1->h = eve->h;
281                 v1->bweight = eve->bweight;
282                 /*Copy Custom Data*/
283                 CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v1->data);
284                 eve->tmp.v = (EditVert*)v1;
285                 eve = eve->next;
286         }
287         
288         /*add edges*/
289         eed= em->edges.first;
290         while(eed) {
291                 v1 = (BME_Vert*)eed->v1->tmp.v;
292                 v2 = (BME_Vert*)eed->v2->tmp.v;
293                 e = BME_ME(bm, v1, v2);
294                 e->crease = eed->crease;
295                 e->bweight = eed->bweight;
296                 e->flag = eed->f & SELECT;
297                 if(eed->sharp) e->flag |= ME_SHARP;
298                 if(eed->seam) e->flag |= ME_SEAM;
299                 //XXX if(eed->h & EM_FGON) e->flag |= ME_FGON;
300                 if(eed->h & 1) e->flag |= ME_HIDE;
301                 eed->tmp.e = (EditEdge*)e;
302                 CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data);
303                 eed = eed->next;
304         }
305         /*add faces.*/
306         efa= em->faces.first;
307         while(efa) {
308                 if(efa->v4) len = 4;
309                 else len = 3;
310                 
311                 edar[0] = (BME_Edge*)efa->e1->tmp.e;
312                 edar[1] = (BME_Edge*)efa->e2->tmp.e;
313                 edar[2] = (BME_Edge*)efa->e3->tmp.e;
314                 if(len == 4){
315                         edar[3] = (BME_Edge*)efa->e4->tmp.e;
316                 }
317                 
318                 /*find v1 and v2*/
319                 v1 = (BME_Vert*)efa->v1->tmp.v;
320                 v2 = (BME_Vert*)efa->v2->tmp.v;
321                 
322                 f = BME_MF(bm,v1,v2,edar,len);
323                 f->mat_nr = efa->mat_nr;
324                 f->flag = efa->flag;
325                 if(efa->h) {
326                         f->flag |= ME_HIDE;
327                         f->flag &= ~ME_FACE_SEL;
328                 }
329                 else {
330                         if(efa->f & 1) f->flag |= ME_FACE_SEL;
331                         else f->flag &= ~ME_FACE_SEL;
332                 }
333                 CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data);
334                 BME_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
335                 efa = efa->next;
336         }
337         BME_model_end(bm);
338         return bm;
339 }
340 /* adds the geometry in the bmesh to editMesh (does not free editMesh)
341  * if td != NULL, the transdata will be mapped to the EditVert's co */
342 void BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td, EditMesh *em) {
343         BME_Vert *v1;
344         BME_Edge *e;
345         BME_Poly *f;
346         
347         BME_TransData *vtd;
348
349         EditVert *eve1, *eve2, *eve3, *eve4, **evlist;
350         EditEdge *eed;
351         EditFace *efa;
352
353         int totvert, len, i, numTex, numCol;
354
355         if (em == NULL) return;
356
357         CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
358         CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0);
359         CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0);
360         CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0);
361         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
362         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
363
364
365         /* convert to EditMesh */
366         /* make editverts */
367         totvert = BLI_countlist(&(bm->verts));
368         evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist");
369         for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) {
370                 v1->tflag1 = i;
371                 eve1 = NULL; //XXX addvertlist(v1->co,NULL);
372                 if (td && (vtd = BME_get_transdata(td,v1))) {
373                         vtd->loc = eve1->co;
374                 }
375                 eve1->keyindex = i;
376                 evlist[i]= eve1;
377                 eve1->f = (unsigned char)v1->flag;
378                 eve1->h = (unsigned char)v1->h;
379                 eve1->bweight = v1->bweight;
380                 CustomData_em_copy_data(&bm->vdata, &em->vdata, v1->data, &eve1->data);
381         }
382         
383         /* make edges */
384         for (e=bm->edges.first;e;e=e->next) {
385                 if(0) { //XXX if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
386                         eed= NULL; //XXX addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
387                         eed->crease = e->crease;
388                         eed->bweight = e->bweight;
389                         if(e->flag & ME_SEAM) eed->seam = 1;
390                         if(e->flag & ME_SHARP) eed->sharp = 1;
391                         if(e->flag & SELECT) eed->f |= SELECT;
392                         //XXX if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
393                         if(e->flag & ME_HIDE) eed->h |= 1;
394                         if(em->selectmode==SCE_SELECT_EDGE) { 
395                                 ; //XXX EM_select_edge(eed, eed->f & SELECT);
396                         }
397                         CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data);
398                 }
399         }
400
401         /* make faces */
402         for (f=bm->polys.first;f;f=f->next) {
403                 len = BME_cycle_length(f->loopbase);
404                 if (len==3 || len==4) {
405                         eve1= evlist[f->loopbase->v->tflag1];
406                         eve2= evlist[f->loopbase->next->v->tflag1];
407                         eve3= evlist[f->loopbase->next->next->v->tflag1];
408                         if (len == 4) {
409                                 eve4= evlist[f->loopbase->prev->v->tflag1];
410                         }
411                         else {
412                                 eve4= NULL;
413                         }
414
415                         efa = NULL; //XXX addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
416                         efa->mat_nr = (unsigned char)f->mat_nr;
417                         efa->flag= f->flag & ~ME_HIDE;
418                         if(f->flag & ME_FACE_SEL) {
419                                 efa->f |= SELECT;
420                         }
421                         if(f->flag & ME_HIDE) efa->h= 1;
422                         // XXX flag depricated
423                         // if((G.f & G_FACESELECT) && (efa->f & SELECT))
424                                 //XXX EM_select_face(efa, 1); /* flush down */
425                         CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data);
426                         BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex);
427                 }
428         }
429
430         MEM_freeN(evlist);
431
432 }
433
434 /* Adds the geometry found in dm to bm
435   */
436 BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
437 {
438         
439         BME_Mesh *bm;
440         int allocsize[4] = {512,512,2048,512};
441         MVert *mvert, *mv;
442         MEdge *medge, *me;
443         MFace *mface, *mf;
444         int totface,totedge,totvert,i,len, numTex, numCol;
445         BME_Vert *v1=NULL,*v2=NULL, **vert_array;
446         BME_Edge *e=NULL;
447         BME_Poly *f=NULL;
448         
449         EdgeHash *edge_hash = BLI_edgehash_new();
450
451         bm = BME_make_mesh(allocsize);
452         /*copy custom data layout*/
453         CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
454         CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
455         CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
456
457         /*copy face corner data*/
458         CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
459         /*initialize memory pools*/
460         CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
461         CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
462         CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
463         CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
464         /*needed later*/
465         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
466         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
467
468         totvert = dm->getNumVerts(dm);
469         totedge = dm->getNumEdges(dm);
470         totface = dm->getNumFaces(dm);
471         mvert = dm->getVertArray(dm);
472         medge = dm->getEdgeArray(dm);
473         mface = dm->getFaceArray(dm);
474
475         vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");
476
477         BME_model_begin(bm);
478         /*add verts*/
479         for(i=0,mv = mvert; i < totvert;i++,mv++){
480                 v1 = BME_MV(bm,mv->co);
481                 vert_array[i] = v1;
482                 v1->flag = mv->flag;
483                 v1->bweight = mv->bweight/255.0f;
484                 CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v1->data);
485         }
486         /*add edges*/
487         for(i=0,me = medge; i < totedge;i++,me++){
488                 v1 = vert_array[me->v1];
489                 v2 = vert_array[me->v2];
490                 e = BME_ME(bm, v1, v2);
491                 e->crease = me->crease/255.0f;
492                 e->bweight = me->bweight/255.0f;
493                 e->flag = (unsigned char)me->flag;
494                 BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
495                 CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->data);
496         }
497         /*add faces.*/
498         for(i=0,mf = mface; i < totface;i++,mf++){
499                 BME_Edge *edar[4];
500                 if(mf->v4) len = 4;
501                 else len = 3;
502                 
503                 edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
504                 edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
505                 if(len == 4){
506                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
507                         edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
508                 }
509                 else
510                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
511                 
512                 /*find v1 and v2*/
513                 v1 = vert_array[mf->v1];
514                 v2 = vert_array[mf->v2];
515                 
516                 f = BME_MF(bm,v1,v2,edar,len);
517                 f->mat_nr = mf->mat_nr;
518                 f->flag = mf->flag;
519                 CustomData_to_bmesh_block(&dm->faceData,&bm->pdata,i,&f->data);
520                 BME_DMcorners_to_loops(bm, &dm->faceData,i,f, numCol,numTex);
521         }
522         
523         BME_model_end(bm);
524         BLI_edgehash_free(edge_hash, NULL);
525         MEM_freeN(vert_array);
526         return bm;
527 }
528
529 DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
530 {
531         MFace *mface, *mf;
532         MEdge *medge, *me;
533         MVert *mvert, *mv;
534         int totface,totedge,totvert,i,bmeshok,len, numTex, numCol;
535
536         BME_Vert *v1=NULL;
537         BME_Edge *e=NULL, *oe=NULL;
538         BME_Poly *f=NULL;
539         
540         DerivedMesh *result;
541         EdgeHash *edge_hash = BLI_edgehash_new();
542
543         totvert = BLI_countlist(&(bm->verts));
544         totedge = 0;
545         
546         /*we cannot have double edges in a derived mesh!*/
547         for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i;
548         for(e=bm->edges.first; e; e=e->next){
549                 oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1);
550                 if(!oe){
551                         totedge++;
552                         BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e);
553                         e->tflag2 = 1;
554                 }
555                 else{
556                         e->tflag2 = 0;
557                 }
558         }
559         
560         /*count quads and tris*/
561         totface = 0;
562         bmeshok = 1;
563         for(f=bm->polys.first;f;f=f->next){
564                 len = BME_cycle_length(f->loopbase);
565                 if(len == 3 || len == 4) totface++;
566         }
567         
568         /*convert back to mesh*/
569         result = CDDM_from_template(dm,totvert,totedge,totface);
570         CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
571         CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
572         CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
573         CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface);
574         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
575         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
576
577
578         /*Make Verts*/
579         mvert = CDDM_get_verts(result);
580         for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){
581                 VECCOPY(mv->co,v1->co);
582                 mv->flag = (unsigned char)v1->flag;
583                 mv->bweight = (char)(255.0*v1->bweight);
584                 CustomData_from_bmesh_block(&bm->vdata, &result->vertData, &v1->data, i);
585         }
586         medge = CDDM_get_edges(result);
587         i=0;
588         for(e=bm->edges.first,me=medge;e;e=e->next){
589                 if(e->tflag2){
590                         if(e->v1->tflag1 < e->v2->tflag1){
591                                 me->v1 = e->v1->tflag1;
592                                 me->v2 = e->v2->tflag1;
593                         }
594                         else{
595                                 me->v1 = e->v2->tflag1;
596                                 me->v2 = e->v1->tflag1;
597                         }
598                 
599                         me->crease = (char)(255.0*e->crease);
600                         me->bweight = (char)(255.0*e->bweight);
601                         me->flag = e->flag;
602                         CustomData_from_bmesh_block(&bm->edata, &result->edgeData, &e->data, i);
603                         me++;
604                         i++;
605                 }
606         }
607         if(totface){
608                 mface = CDDM_get_faces(result);
609                 /*make faces*/
610                 for(i=0,f=bm->polys.first;f;f=f->next){
611                         mf = &mface[i];
612                         len = BME_cycle_length(f->loopbase);
613                         if(len==3 || len==4){
614                                 mf->v1 = f->loopbase->v->tflag1;
615                                 mf->v2 = f->loopbase->next->v->tflag1;
616                                 mf->v3 = f->loopbase->next->next->v->tflag1;
617                                 if(len == 4){
618                                         mf->v4 = f->loopbase->prev->v->tflag1;
619                                 }
620                                 /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
621                                 if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){
622                                         test_index_face(mf, NULL, i, len);
623                                 }
624                                 mf->mat_nr = (unsigned char)f->mat_nr;
625                                 mf->flag = (unsigned char)f->flag;
626                                 CustomData_from_bmesh_block(&bm->pdata, &result->faceData, &f->data, i);
627                                 BME_DMloops_to_corners(bm, &result->faceData, i, f,numCol,numTex);
628                                 i++;
629                         }
630                 }
631         }
632         BLI_edgehash_free(edge_hash, NULL);
633         return result;
634 }