More DM func renames, fixing some build breaks, renaming more stuff, also seems like...
[blender.git] / source / blender / bmesh / intern / in-progress / BME_conversions.c
1 /**
2  * BME_conversions.c    August 2008
3  *
4  *      BM to Derived Mesh conversion functions.
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  * about this.  
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2007 Blender Foundation.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): Geoffrey Bantle, Levi Schooley.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  */
32
33 #include "MEM_guardedalloc.h"
34 #include "BKE_customdata.h" 
35
36 #include "DNA_listBase.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_scene_types.h"
40
41 #include "BKE_utildefines.h"
42 #include "BKE_mesh.h"
43 #include "bmesh.h"
44 #include "BKE_global.h"
45 #include "BKE_DerivedMesh.h"
46 #include "BKE_cdderivedmesh.h"
47
48 #include "BLI_blenlib.h"
49 #include "BLI_editVert.h"
50 #include "BLI_edgehash.h"
51 #include "bmesh_private.h"
52
53
54
55 /*
56  * BMESH DERIVED MESH CONVERSION FUNCTIONS
57  *
58  * The functions in this file provides
59  * methods for converting to and from
60  * a bmesh. 
61  *
62 */
63
64
65 /*
66  * DMCORNERS TO LOOPS
67  *
68  * Function to convert derived mesh per-face
69  * corner data (uvs, vertex colors), to n-gon
70  * per-loop data.
71  *
72 */
73
74 static void DMcorners_to_loops(BMMesh *bm, CustomData *facedata, int index, BMFace *f, int numCol, int numTex){
75         int i, j;
76         BMLoop *l;
77         MTFace *texface;
78         MTexPoly *texpoly;
79         MCol *mcol;
80         MLoopCol *mloopcol;
81         MLoopUV *mloopuv;
82
83         for(i=0; i< numTex; i++){
84                 texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
85                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
86
87                 texpoly->tpage = texface[index].tpage;
88                 texpoly->flag = texface[index].flag;
89                 texpoly->transp = texface[index].transp;
90                 texpoly->mode = texface[index].mode;
91                 texpoly->tile = texface[index].tile;
92                 texpoly->unwrap = texface[index].unwrap;
93
94                 j = 0;
95                 l = f->loopbase;
96                 do{
97                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
98                         mloopuv->uv[0] = texface[index].uv[j][0];
99                         mloopuv->uv[1] = texface[index].uv[j][1];
100                         j++;
101                         l = l->next;
102                 }while(l!=f->loopbase);
103         }
104
105         for(i=0; i < numCol; i++){
106                 mcol = CustomData_get_layer_n(facedata, CD_MCOL, i);
107                 j = 0;
108                 l = f->loopbase;
109                 do{
110                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
111                         mloopcol->r = mcol[(index*4)+j].r;
112                         mloopcol->g = mcol[(index*4)+j].g;
113                         mloopcol->b = mcol[(index*4)+j].b;
114                         mloopcol->a = mcol[(index*4)+j].a;
115                         j++;
116                         l = l->next;
117                 }while(l!=f->loopbase);
118         }
119 }
120
121 /*
122  * LOOPS TO DMCORNERS
123  *
124  * Function to convert n-gon per-loop data
125  * (uvs, vertex colors, ect)to derived mesh
126  * face corner data.
127  *
128 */
129
130 static void loops_to_DMcorners(BMMesh *bm, CustomData *facedata, int index, BMFace *f,int numCol, int numTex){
131         int i, j;
132         BMLoop *l;
133         MTFace *texface;
134         MTexPoly *texpoly;
135         MCol *mcol;
136         MLoopCol *mloopcol;
137         MLoopUV *mloopuv;
138
139         for(i=0; i < numTex; i++){
140                 texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
141                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
142                 
143                 texface[index].tpage = texpoly->tpage;
144                 texface[index].flag = texpoly->flag;
145                 texface[index].transp = texpoly->transp;
146                 texface[index].mode = texpoly->mode;
147                 texface[index].tile = texpoly->tile;
148                 texface[index].unwrap = texpoly->unwrap;
149
150                 j = 0;
151                 l = f->loopbase;
152                 do{
153                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
154                         texface[index].uv[j][0] = mloopuv->uv[0];
155                         texface[index].uv[j][1] = mloopuv->uv[1];
156                         j++;
157                         l = l->next;
158                 }while(l!=f->loopbase);
159
160         }
161         for(i=0; i < numCol; i++){
162                 mcol = CustomData_get_layer_n(facedata,CD_MCOL, i);
163                 j = 0;
164                 l = f->loopbase;
165                 do{
166                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
167                         mcol[(index*4) + j].r = mloopcol->r;
168                         mcol[(index*4) + j].g = mloopcol->g;
169                         mcol[(index*4) + j].b = mloopcol->b;
170                         mcol[(index*4) + j].a = mloopcol->a;
171                         j++;
172                         l = l->next;
173                 }while(l!=f->loopbase);
174         }
175 }
176
177 /*
178  * MVERT TO BMESHVERT
179  *
180  * Converts a MVert to a BMVert
181  *
182 */
183 static BMVert *mvert_to_bmeshvert(BMMesh *bm, BMVert **vert_array, int index, MVert *mv, CustomData *data)
184 {
185                 BMVert *v = NULL;
186                 
187                 v = bmesh_make_vert(bm, mv->co, NULL);
188                 vert_array[index] = v;
189                 if(mv->flag & SELECT) bmesh_set_flag(v, BMESH_SELECT);
190                 v->bweight = mv->bweight/255.0f;
191                 CustomData_to_bmesh_block(data, &bm->vdata, index, &v->data);
192         
193                 return v;
194 }
195
196 /*
197  * MEDGE TO BMESHEDGE
198  *
199  * Converts a MEdge to a BMEdge
200  *
201 */
202
203 static BMEdge *medge_to_bmeshedge(BMMesh *bm, BMVert **vert_array, int index, MEdge *me, CustomData *data, Edge_Hash *edge_hash)
204 {
205                 BMVert *v1, *v2;
206                 BMEdge *e = NULL;
207
208                 v1 = vert_array[me->v1];
209                 v2 = vert_array[me->v2];
210                 e = bmesh_make_edge(bm, v1, v2, NULL, 0);
211                 e->crease = me->crease/255.0f;
212                 e->bweight = me->bweight/255.0f;
213                 if(me->flag & 1) bmesh_set_flag(e, BMESH_SELECT);
214                 if(me->flag & ME_SEAM) bmesh_set_flag(e, BMESH_SEAM);
215                 BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
216                 CustomData_to_bmesh_block(data, &bm->edata, index, &e->data);
217
218                 return e;
219 }
220
221 /*
222  * MFACE TO BMESHFACE
223  *
224  * Converts a MFace to a BMFace.
225  * Note that this will fail on eekadoodle
226  * faces.
227  *
228 */
229
230 static BMFace *mface_to_bmeshface(BMMesh *bm, BMVert **vert_array, int index, MFace *mf, CustomData *data, Edge_Hash *edge_hash)
231 {
232                 BMVert *v1, *v2;
233                 BMEdge *edar[4];
234                 BMFace *f = NULL;
235                 int len;
236
237                 if(mf->v4) len = 4;
238                 else len = 3;
239                 
240                 edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
241                 edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
242                 if(len == 4){
243                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
244                         edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
245                 }
246                 else
247                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
248                 
249                 /*find v1 and v2*/
250                 v1 = vert_array[mf->v1];
251                 v2 = vert_array[mf->v2];
252                 
253                 f = bmesh_make_ngon(bm, v1, v2, edar, len, 0);
254                 f->mat_nr = mf->mat_nr;
255                 if(mf->flag & 1) bmesh_set_flag(f, BMESH_SELECT);
256                 if(mf->flag & ME_HIDE) bmesh_set_flag(f, BMESH_HIDDEN);
257                 CustomData_to_bmesh_block(data, &bm->pdata, index, &f->data);
258
259                 return f;
260 }
261
262 /*
263  * DERIVEDMESH TO BMESH
264  *
265  * Converts a derived mesh to a bmesh.
266  *
267 */
268
269 BMMesh *derivedmesh_to_bmesh(DerivedMesh *dm)
270 {
271         
272         BMMesh *bm;
273         BMVert **vert_array;
274         BMFace *f=NULL;
275         
276         MVert *mvert, *mv;
277         MEdge *medge, *me;
278         MFace *mface, *mf;
279         
280         int totface,totedge,totvert,i,len, numTex, numCol;
281         int allocsize[4] = {512,512,2048,512};
282         
283         EdgeHash *edge_hash = BLI_edgehash_new();
284
285         /*allocate a new bmesh*/
286         bm = bmesh_make_mesh(allocsize);
287
288         /*copy custom data layout*/
289         CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
290         CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
291         CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
292
293         /*copy face corner data*/
294         CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
295         /*initialize memory pools*/
296         CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
297         CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
298         CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
299         CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
300
301         /*needed later*/
302         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
303         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
304
305         totvert = dm->getNumVerts(dm);
306         totedge = dm->getNumEdges(dm);
307         totface = dm->getNumTessFaces(dm);
308         mvert = dm->getVertArray(dm);
309         medge = dm->getEdgeArray(dm);
310         mface = dm->getTessFaceArray(dm);
311
312         vert_array = MEM_mallocN(sizeof(BMVert *)* totvert,"derivedmesh to bmesh vertex pointer array");
313
314         bmesh_begin_edit(bm);
315         /*add verts*/
316         for(i=0, mv = mvert; i < totvert; i++, mv++)
317                 mvert_to_bmeshvert(bm, vert_array, i, mv, &dm->vertData);
318         
319         /*add edges*/
320         for(i=0, me = medge; i < totedge; i++, me++)
321                 medge_to_bmeshedge(bm, vert_array, i, me, &dm->edgeData, edge_hash);
322
323         /*add faces.*/
324         for(i=0, mf = mface; i < totface; i++, mf++){
325                 f = mface_to_bmeshface(bm, vert_array, mf, &dm->faceData, edge_hash);
326                 if(f) DMcorners_to_loops(bm, &dm->faceData, i, f, numCol, numTex);
327         }
328         
329         bmesh_end__edit(bm);
330         BLI_edgehash_free(edge_hash, NULL);
331         MEM_freeN(vert_array);
332         return bm;
333 }
334
335 static void bmeshvert_to_mvert(BMMesh *bm, BMVert *v, MVert *mv, int index, CustomData *data)
336 {
337                 copy_v3_v3(mv->co, v->co);
338                 if(bmesh_test_flag(v, BMESH_SELECT)) mv->flag |= 1;
339                 if(bmesh_test_flag(v, BMESH_HIDDEN)) mv->flag |= ME_HIDE;
340                 mv->bweight = (char)(255.0*v1->bweight);
341                 CustomData_from_bmesh_block(&bm->vdata, data, &v1->data, index);
342 }
343
344 static int bmeshedge_to_medge(BMMesh *bm, BMEdge *e, MEdge *me, int index, CustomData *data)
345 {
346         if(e->head.eflag2){
347                 if(e->v1->head.eflag1 < e->v2->head.eflag1){
348                         me->v1 = e->v1->head.eflag1;
349                         me->v2 = e->v2->head.eflag1;
350                 }
351                 else{
352                         me->v1 = e->v2->head.eflag1;
353                         me->v2 = e->v1->eflag1;
354                 }
355         
356                 me->crease = (char)(255.0*e->crease);
357                 me->bweight = (char)(255.0*e->bweight);
358                 if(bmesh_test_flag(e, BMESH_SELECT)) me->flag |= 1;
359                 if(bmesh_test_flag(e, BMESH_HIDDEN)) me->flag |= ME_HIDE;
360                 CustomData_from_bmesh_block(&bm->edata, data, &e->data, index);
361                 return 1;
362         }
363         return 0;
364 }
365
366 static int bmeshface_to_mface(BMMesh *bm, BMFace *f, MFace *mf, int index, CustomData *data)
367 {
368         if(f->len==3 || f->len==4){
369                 mf->v1 = f->loopbase->v->head.eflag1;
370                 mf->v2 = f->loopbase->next->v->head.eflag1;
371                 mf->v3 = f->loopbase->next->next->v->head.eflag1;
372                 if(len == 4){
373                         mf->v4 = f->loopbase->prev->v->head.eflag1;
374                 }
375                 /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
376                 if(mf->v3 == 0 || (f->len == 4 && mf->v4 == 0)){
377                         test_index_face(mf, NULL, index, f->len);
378                 }
379                 mf->mat_nr = (unsigned char)f->mat_nr;
380                 if(bmesh_test_flag(f, BMESH_SELECT)) mf->flag |= 1;
381                 if(bmesh_test_flag(f, BMESH_HIDDEN)) mf->flag |= ME_HIDE;
382                 CustomData_from_bmesh_block(&bm->pdata, data, &f->data, index);
383                 return 1;
384         }
385         return 0;
386 }
387
388 /*
389  * BMESH TO DERIVEDMESH
390  *
391  * Converts a bmesh to a derived mesh.
392  *
393 */
394
395 DerivedMesh *bmesh_to_derivedmesh(BMMesh *bm, DerivedMesh *dm)
396 {
397         MFace *mface = NULL, *mf = NULL;
398         MEdge *medge = NULL, *me = NULL;
399         MVert *mvert = NULL, *mv = NULL;
400         DerivedMesh *result = NULL;
401
402         BMVert *v=NULL;
403         BMEdge *e=NULL, *oe=NULL;
404         BMFace *f=NULL;
405
406         BMIter verts;
407         BMIter edges;
408         BMIter faces;
409
410         int totface = 0,totedge = 0,totvert = 0,i = 0, numTex, numCol;
411
412         EdgeHash *edge_hash = BLI_edgehash_new();
413
414         /*get element counts*/
415         totvert = bmesh_count_element(bm, BMESH_VERT);
416
417         /*store element indices. Note that the abuse of eflag here should NOT be duplicated!*/
418         for(i=0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++)
419                 v->head.eflag1 = i;
420
421         /*we cannot have double edges in a derived mesh!*/
422         for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){
423                 oe = BLI_edgehash_lookup(edge_hash,e->v1->head.eflag1, e->v2->head.eflag1);
424                 if(!oe){
425                         totedge++;
426                         BLI_edgehash_insert(edge_hash,e->v1->head.eflag1,e->v2->head.eflag1,e);
427                         e->head.eflag2 = 1;
428                 }
429                 else{
430                         e->head.eflag2 = 0;
431                 }
432         }
433
434         /*count quads and tris*/
435         for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){
436                 if(f->len == 3 || f->len == 4) totface++;
437         }
438         
439         /*Allocate derivedmesh and copy custom data*/
440         result = CDDM_from_template(dm,totvert,totedge,totface);
441         CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
442         CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
443         CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
444         CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface);
445         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
446         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
447
448         /*Make Verts*/
449         mvert = CDDM_get_verts(result);
450         for(i = 0, v = bmeshIterator_init(verts, BM_VERTS, bm, 0); v; v = bmeshIterator_step(verts), i++, mv++){
451                 bmeshvert_to_mvert(bm,v,mv,i,&result->vertData);
452         }
453
454         /*Make Edges*/
455         medge = CDDM_get_edges(result);
456         i=0;
457         for(e = bmeshIterator_init(edges, BM_EDGES, bm, 0); e; e = bmeshIterator_step(edges)){
458                 me = &medge[i];
459                 if(bmeshedge_to_medge(bm, e, me, i, &result->edgeData){
460                         me++;
461                         i++;
462                 }
463         }
464         /*Make Faces*/
465         if(totface){
466                 mface = CDDM_get_faces(result);
467                 i=0;
468                 for(f = bmeshIterator_init(faces, BM_FACES, bm, 0); f; f = bmeshIterator_step(faces)){ 
469                         mf = &mface[i];
470                         if(bmeshface_to_mface(bm, f, mf, i, &result->faceData)){
471                                 loops_to_DMcorners(bm, &result->faceData, i, f, numCol, numTex);
472                                 i++;
473                         }
474                 }
475         }
476         BLI_edgehash_free(edge_hash, NULL);
477         return result;
478 }