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