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