-> UV and VCOL support for bevel (editmode)
[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: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
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 static void BME_corners_to_loops(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){
60         int i, j;
61         BME_Loop *l;
62         MTFace *texface;
63         MTexPoly *texpoly;
64         MCol *mcol;
65         MLoopCol *mloopcol;
66         MLoopUV *mloopuv;
67
68         for(i=0; i < numTex; i++){
69                 texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
70                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
71                 
72                 texpoly->tpage = texface->tpage;
73                 texpoly->flag = texface->flag;
74                 texpoly->transp = texface->transp;
75                 texpoly->mode = texface->mode;
76                 texpoly->tile = texface->tile;
77                 texpoly->unwrap = texface->unwrap;
78
79                 j = 0;
80                 l = f->loopbase;
81                 do{
82                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
83                         mloopuv->uv[0] = texface->uv[j][0];
84                         mloopuv->uv[1] = texface->uv[j][1];
85                         j++;
86                         l = l->next;
87                 }while(l!=f->loopbase);
88
89         }
90         for(i=0; i < numCol; i++){
91                 mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
92                 j = 0;
93                 l = f->loopbase;
94                 do{
95                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
96                         mloopcol->r = mcol[j].r;
97                         mloopcol->g = mcol[j].g;
98                         mloopcol->b = mcol[j].b;
99                         mloopcol->a = mcol[j].a;
100                         j++;
101                         l = l->next;
102                 }while(l!=f->loopbase);
103         }
104 }
105
106 static void BME_loops_to_corners(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){
107         int i, j;
108         BME_Loop *l;
109         MTFace *texface;
110         MTexPoly *texpoly;
111         MCol *mcol;
112         MLoopCol *mloopcol;
113         MLoopUV *mloopuv;
114
115         for(i=0; i < numTex; i++){
116                 texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
117                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
118                 
119                 texface->tpage = texpoly->tpage;
120                 texface->flag = texpoly->flag;
121                 texface->transp = texpoly->transp;
122                 texface->mode = texpoly->mode;
123                 texface->tile = texpoly->tile;
124                 texface->unwrap = texpoly->unwrap;
125
126                 j = 0;
127                 l = f->loopbase;
128                 do{
129                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
130                         texface->uv[j][0] = mloopuv->uv[0];
131                         texface->uv[j][1] = mloopuv->uv[1];
132                         j++;
133                         l = l->next;
134                 }while(l!=f->loopbase);
135
136         }
137         for(i=0; i < numCol; i++){
138                 mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
139                 j = 0;
140                 l = f->loopbase;
141                 do{
142                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
143                         mcol[j].r = mloopcol->r;
144                         mcol[j].g = mloopcol->g;
145                         mcol[j].b = mloopcol->b;
146                         mcol[j].a = mloopcol->a;
147                         j++;
148                         l = l->next;
149                 }while(l!=f->loopbase);
150         }
151 }
152 /*move the EditMesh conversion functions to editmesh_tools.c*/
153 BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
154         BME_Mesh *bm;
155         int allocsize[4] = {512,512,2048,512}, numTex, numCol;
156         BME_Vert *v1, *v2;
157         BME_Edge *e, *edar[4];
158         BME_Poly *f;
159
160         EditVert *eve;
161         EditEdge *eed;
162         EditFace *efa;
163
164         int len;
165         bm = BME_make_mesh(allocsize);
166
167         /*copy custom data layout*/
168         CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
169         CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
170         CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
171
172         /*copy face corner data*/
173         CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
174         /*initialize memory pools*/
175         CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
176         CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
177         CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
178         CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
179         /*needed later*/
180         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
181         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
182
183         BME_model_begin(bm);
184         /*add verts*/
185         eve= em->verts.first;
186         while(eve) {
187                 v1 = BME_MV(bm,eve->co);
188                 VECCOPY(v1->no,eve->no);
189                 v1->flag = eve->f;
190                 v1->h = eve->h;
191                 v1->bweight = eve->bweight;
192                 /*Copy Custom Data*/
193                 CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v1->data);
194                 eve->tmp.v = (EditVert*)v1;
195                 eve = eve->next;
196         }
197         
198         /*add edges*/
199         eed= em->edges.first;
200         while(eed) {
201                 v1 = (BME_Vert*)eed->v1->tmp.v;
202                 v2 = (BME_Vert*)eed->v2->tmp.v;
203                 e = BME_ME(bm, v1, v2);
204                 e->crease = eed->crease;
205                 e->bweight = eed->bweight;
206                 e->flag = eed->f & SELECT;
207                 if(eed->sharp) e->flag |= ME_SHARP;
208                 if(eed->seam) e->flag |= ME_SEAM;
209                 if(eed->h & EM_FGON) e->flag |= ME_FGON;
210                 if(eed->h & 1) e->flag |= ME_HIDE;
211                 eed->tmp.e = (EditEdge*)e;
212                 CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data);
213                 eed = eed->next;
214         }
215         /*add faces.*/
216         efa= em->faces.first;
217         while(efa) {
218                 if(efa->v4) len = 4;
219                 else len = 3;
220                 
221                 edar[0] = (BME_Edge*)efa->e1->tmp.e;
222                 edar[1] = (BME_Edge*)efa->e2->tmp.e;
223                 edar[2] = (BME_Edge*)efa->e3->tmp.e;
224                 if(len == 4){
225                         edar[3] = (BME_Edge*)efa->e4->tmp.e;
226                 }
227                 
228                 /*find v1 and v2*/
229                 v1 = (BME_Vert*)efa->v1->tmp.v;
230                 v2 = (BME_Vert*)efa->v2->tmp.v;
231                 
232                 f = BME_MF(bm,v1,v2,edar,len);
233                 f->mat_nr = efa->mat_nr;
234                 f->flag = efa->flag;
235                 if(efa->h) {
236                         f->flag |= ME_HIDE;
237                         f->flag &= ~ME_FACE_SEL;
238                 }
239                 else {
240                         if(efa->f & 1) f->flag |= ME_FACE_SEL;
241                         else f->flag &= ~ME_FACE_SEL;
242                 }
243                 CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data);
244                 BME_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
245                 efa = efa->next;
246         }
247         BME_model_end(bm);
248         return bm;
249 }
250 /* adds the geometry in the bmesh to G.editMesh (does not free G.editMesh)
251  * if td != NULL, the transdata will be mapped to the EditVert's co */
252 EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) {
253         BME_Vert *v1;
254         BME_Edge *e;
255         BME_Poly *f;
256         
257         BME_TransData *vtd;
258
259         EditMesh *em;
260         EditVert *eve1, *eve2, *eve3, *eve4, **evlist;
261         EditEdge *eed;
262         EditFace *efa;
263
264         int totvert, len, i, numTex, numCol;
265
266         em = G.editMesh;
267
268         if (em == NULL) return NULL;
269
270
271         CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
272         CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0);
273         CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0);
274         CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
275         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
276         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
277
278
279         /* convert to EditMesh */
280         /* make editverts */
281         totvert = BLI_countlist(&(bm->verts));
282         evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist");
283         for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) {
284                 v1->tflag1 = i;
285                 eve1 = addvertlist(v1->co,NULL);
286                 if (td && (vtd = BME_get_transdata(td,v1))) {
287                         vtd->loc = eve1->co;
288                 }
289                 eve1->keyindex = i;
290                 evlist[i]= eve1;
291                 eve1->f = (unsigned char)v1->flag;
292                 eve1->h = (unsigned char)v1->h;
293                 eve1->bweight = v1->bweight;
294                 CustomData_em_copy_data(&bm->vdata, &em->vdata, v1->data, &eve1->data);
295         }
296         
297         /* make edges */
298         for (e=bm->edges.first;e;e=e->next) {
299                 if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
300                         eed= addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
301                         eed->crease = e->crease;
302                         eed->bweight = e->bweight;
303                         if(e->flag & ME_SEAM) eed->seam = 1;
304                         if(e->flag & ME_SHARP) eed->sharp = 1;
305                         if(e->flag & SELECT) eed->f |= SELECT;
306                         if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
307                         if(e->flag & ME_HIDE) eed->h |= 1;
308                         if(G.scene->selectmode==SCE_SELECT_EDGE) 
309                                 EM_select_edge(eed, eed->f & SELECT);
310                 
311                         CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data);
312                 }
313         }
314
315         /* make faces */
316         for (f=bm->polys.first;f;f=f->next) {
317                 len = BME_cycle_length(f->loopbase);
318                 if (len==3 || len==4) {
319                         eve1= evlist[f->loopbase->v->tflag1];
320                         eve2= evlist[f->loopbase->next->v->tflag1];
321                         eve3= evlist[f->loopbase->next->next->v->tflag1];
322                         if (len == 4) {
323                                 eve4= evlist[f->loopbase->prev->v->tflag1];
324                         }
325                         else {
326                                 eve4= NULL;
327                         }
328
329                         efa = addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
330                         efa->mat_nr = (unsigned char)f->mat_nr;
331                         efa->flag= f->flag & ~ME_HIDE;
332                         if(f->flag & ME_FACE_SEL) {
333                                 efa->f |= SELECT;
334                         }
335                         if(f->flag & ME_HIDE) efa->h= 1;
336                         if((G.f & G_FACESELECT) && (efa->f & SELECT))
337                                 EM_select_face(efa, 1); /* flush down */
338                         CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data);
339                         BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex);
340                 }
341         }
342
343         MEM_freeN(evlist);
344
345         countall();
346
347         return em;
348 }
349
350 /* Adds the geometry found in dm to bm
351   */
352 BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
353 {
354         
355         BME_Mesh *bm;
356         int allocsize[4] = {512,512,2048,512};
357         MVert *mvert, *mv;
358         MEdge *medge, *me;
359         MFace *mface, *mf;
360         int totface,totedge,totvert,i,len;
361         BME_Vert *v1=NULL,*v2=NULL, **vert_array;
362         BME_Edge *e=NULL;
363         BME_Poly *f=NULL;
364         
365         EdgeHash *edge_hash = BLI_edgehash_new();
366
367         bm = BME_make_mesh(allocsize);
368         totvert = dm->getNumVerts(dm);
369         totedge = dm->getNumEdges(dm);
370         totface = dm->getNumFaces(dm);
371         mvert = dm->getVertArray(dm);
372         medge = dm->getEdgeArray(dm);
373         mface = dm->getFaceArray(dm);
374
375         vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");
376
377         BME_model_begin(bm);
378         /*add verts*/
379         for(i=0,mv = mvert; i < totvert;i++,mv++){
380                 v1 = BME_MV(bm,mv->co);
381                 vert_array[i] = v1;
382                 v1->flag = mv->flag;
383                 v1->bweight = mv->bweight/255.0f;
384         }
385         /*add edges*/
386         for(i=0,me = medge; i < totedge;i++,me++){
387                 v1 = vert_array[me->v1];
388                 v2 = vert_array[me->v2];
389                 e = BME_ME(bm, v1, v2);
390                 e->crease = me->crease/255.0f;
391                 e->bweight = me->bweight/255.0f;
392                 e->flag = (unsigned char)me->flag;
393                 BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
394         }
395         /*add faces.*/
396         for(i=0,mf = mface; i < totface;i++,mf++){
397                 BME_Edge *edar[4];
398                 if(mf->v4) len = 4;
399                 else len = 3;
400                 
401                 edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
402                 edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
403                 if(len == 4){
404                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
405                         edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
406                 }
407                 else
408                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
409                 
410                 /*find v1 and v2*/
411                 v1 = vert_array[mf->v1];
412                 v2 = vert_array[mf->v2];
413                 
414                 f = BME_MF(bm,v1,v2,edar,len);
415                 f->mat_nr = mf->mat_nr;
416                 f->flag = mf->flag;
417         }
418         
419         BME_model_end(bm);
420         BLI_edgehash_free(edge_hash, NULL);
421         MEM_freeN(vert_array);
422         return bm;
423 }
424
425 DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
426 {
427         MFace *mface, *mf;
428         MEdge *medge, *me;
429         MVert *mvert, *mv;
430         int totface,totedge,totvert,i,bmeshok,len;
431
432         BME_Vert *v1=NULL;
433         BME_Edge *e=NULL, *oe=NULL;
434         BME_Poly *f=NULL;
435         
436         DerivedMesh *result;
437         EdgeHash *edge_hash = BLI_edgehash_new();
438
439         totvert = BLI_countlist(&(bm->verts));
440         totedge = 0;
441         
442         /*we cannot have double edges in a derived mesh!*/
443         for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i;
444         for(e=bm->edges.first; e; e=e->next){
445                 oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1);
446                 if(!oe){
447                         totedge++;
448                         BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e);
449                         e->tflag2 = 1;
450                 }
451                 else{
452                         e->tflag2 = 0;
453                 }
454         }
455         
456         /*count quads and tris*/
457         totface = 0;
458         bmeshok = 1;
459         for(f=bm->polys.first;f;f=f->next){
460                 len = BME_cycle_length(f->loopbase);
461                 if(len == 3 || len == 4) totface++;
462         }
463         
464         /*convert back to mesh*/
465         result = CDDM_from_template(dm,totvert,totedge,totface);
466         /*Make Verts*/
467         mvert = CDDM_get_verts(result);
468         for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){
469                 VECCOPY(mv->co,v1->co);
470                 mv->flag = (unsigned char)v1->flag;
471                 mv->bweight = (char)(255.0*v1->bweight);
472         }
473         medge = CDDM_get_edges(result);
474         i=0;
475         for(e=bm->edges.first,me=medge;e;e=e->next){
476                 if(e->tflag2){
477                         if(e->v1->tflag1 < e->v2->tflag1){
478                                 me->v1 = e->v1->tflag1;
479                                 me->v2 = e->v2->tflag1;
480                         }
481                         else{
482                                 me->v1 = e->v2->tflag1;
483                                 me->v2 = e->v1->tflag1;
484                         }
485                 
486                         me->crease = (char)(255.0*e->crease);
487                         me->bweight = (char)(255.0*e->bweight);
488                         me->flag = e->flag;
489                         me++;
490                         i++;
491                 }
492         }
493         if(totface){
494                 mface = CDDM_get_faces(result);
495                 /*make faces*/
496                 for(i=0,f=bm->polys.first;f;f=f->next){
497                         mf = &mface[i];
498                         len = BME_cycle_length(f->loopbase);
499                         if(len==3 || len==4){
500                                 mf->v1 = f->loopbase->v->tflag1;
501                                 mf->v2 = f->loopbase->next->v->tflag1;
502                                 mf->v3 = f->loopbase->next->next->v->tflag1;
503                                 if(len == 4){
504                                         mf->v4 = f->loopbase->prev->v->tflag1;
505                                 }
506                                 /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
507                                 if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){
508                                         test_index_face(mf, NULL, i, len);
509                                 }
510                                 i++;
511                                 mf->mat_nr = (unsigned char)f->mat_nr;
512                                 mf->flag = (unsigned char)f->flag;
513                         }
514                 }
515         }
516         BLI_edgehash_free(edge_hash, NULL);
517         return result;
518 }