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