-> Bevel
[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/BL DUAL 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. The Blender
14  * Foundation also sells licenses for use in proprietary software under
15  * the Blender License.  See http://www.blender.org/BL/ for information
16  * about this.  
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  *
27  * The Original Code is Copyright (C) 2007 Blender Foundation.
28  * All rights reserved.
29  *
30  * The Original Code is: all of this file.
31  *
32  * Contributor(s): Geoffrey Bantle, Levi Schooley.
33  *
34  * ***** END GPL/BL DUAL LICENSE BLOCK *****
35  */
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_listBase.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_scene_types.h"
43
44 #include "BKE_utildefines.h"
45 #include "BKE_mesh.h"
46 #include "BKE_bmesh.h"
47 #include "BKE_global.h"
48 #include "BKE_DerivedMesh.h"
49 #include "BKE_cdderivedmesh.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_editVert.h"
53 #include "BLI_edgehash.h"
54 #include "BIF_editmesh.h"
55 #include "editmesh.h"
56 #include "bmesh_private.h"
57
58 #include "BSE_edit.h"
59
60 BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em, BME_Mesh *bm) {
61         BME_Vert *v1, *v2;
62         BME_Edge *e, *edar[4];
63         BME_Poly *f;
64
65         EditVert *eve;
66         EditEdge *eed;
67         EditFace *efa;
68
69         int len;
70
71         BME_model_begin(bm);
72         /*custom data*/
73         
74         /*add verts*/
75         CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
76         eve= em->verts.first;
77         while(eve) {
78                 v1 = BME_MV(bm,eve->co);
79                 VECCOPY(v1->no,eve->no);
80                 v1->flag = eve->f;
81                 v1->h = eve->h;
82                 v1->bweight = eve->bweight;
83
84                 /* link the verts for edge and face construction;
85                  * kind of a dangerous thing - remember to cast back to BME_Vert before using! */
86                 eve->tmp.v = (EditVert*)v1;
87
88                 CustomData_em_copy_data(&em->vdata, &bm->vdata, eve->data, &v1->data);
89                 
90                 eve = eve->next;
91         }
92         
93         /*add edges*/
94         CustomData_copy(&em->edata, &bm->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
95         eed= em->edges.first;
96         while(eed) {
97                 v1 = (BME_Vert*)eed->v1->tmp.v;
98                 v2 = (BME_Vert*)eed->v2->tmp.v;
99                 e = BME_ME(bm, v1, v2);
100                 e->crease = eed->crease;
101                 e->bweight = eed->bweight;
102                 e->flag = eed->f & SELECT;
103                 if(eed->sharp) e->flag |= ME_SHARP;
104                 if(eed->seam) e->flag |= ME_SEAM;
105                 if(eed->h & EM_FGON) e->flag |= ME_FGON;
106                 if(eed->h & 1) e->flag |= ME_HIDE;
107                 CustomData_em_copy_data(&em->edata, &bm->edata, eed->data, &e->data);
108
109                 /* link the edges for face construction;
110                  * kind of a dangerous thing - remember to cast back to BME_Edge before using! */
111                 eed->tmp.e = (EditEdge*)e;
112                 eed = eed->next;
113         }
114
115         /*add faces.*/
116         CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
117         efa= em->faces.first;
118         while(efa) {
119                 if(efa->v4) len = 4;
120                 else len = 3;
121                 
122                 edar[0] = (BME_Edge*)efa->e1->tmp.e;
123                 edar[1] = (BME_Edge*)efa->e2->tmp.e;
124                 edar[2] = (BME_Edge*)efa->e3->tmp.e;
125                 if(len == 4){
126                         edar[3] = (BME_Edge*)efa->e4->tmp.e;
127                 }
128                 
129                 /*find v1 and v2*/
130                 v1 = (BME_Vert*)efa->v1->tmp.v;
131                 v2 = (BME_Vert*)efa->v2->tmp.v;
132                 
133                 f = BME_MF(bm,v1,v2,edar,len);
134                 f->mat_nr = efa->mat_nr;
135                 f->flag = efa->flag;
136                 if(efa->h) {
137                         f->flag |= ME_HIDE;
138                         f->flag &= ~ME_FACE_SEL;
139                 }
140                 else {
141                         if(efa->f & 1) f->flag |= ME_FACE_SEL;
142                         else f->flag &= ~ME_FACE_SEL;
143                 }
144                 CustomData_em_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data);
145                 
146                 efa = efa->next;
147         }
148         BME_model_end(bm);
149         return bm;
150 }
151
152 /* adds the geometry in the bmesh to G.editMesh (does not free G.editMesh)
153  * if td != NULL, the transdata will be mapped to the EditVert's co */
154 EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) {
155         BME_Vert *v1;
156         BME_Edge *e;
157         BME_Poly *f;
158         
159         BME_TransData *vtd;
160
161         EditMesh *em;
162         EditVert *eve1, *eve2, *eve3, *eve4, **evlist;
163         EditEdge *eed;
164         EditFace *efa;
165
166         int totvert, len, i;
167
168         em = G.editMesh;
169
170         if (em == NULL) return NULL;
171
172         /* convert to EditMesh */
173         /* make editverts */
174         CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
175         totvert = BLI_countlist(&(bm->verts));
176         evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist");
177         for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) {
178                 v1->tflag1 = i;
179                 eve1 = addvertlist(v1->co,NULL);
180                 if (td && (vtd = BME_get_transdata(td,v1))) {
181                         vtd->loc = eve1->co;
182                 }
183                 eve1->keyindex = i;
184                 evlist[i]= eve1;
185                 eve1->f = (unsigned char)v1->flag;
186                 eve1->h = (unsigned char)v1->h;
187                 eve1->bweight = v1->bweight;
188                 CustomData_em_copy_data(&bm->vdata, &em->vdata, v1->data, &eve1->data);
189         }
190         
191         /* make edges */
192         CustomData_copy(&bm->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
193         for (e=bm->edges.first;e;e=e->next) {
194                 if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
195                         eed= addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
196                         eed->crease = e->crease;
197                         eed->bweight = e->bweight;
198                         if(e->flag & ME_SEAM) eed->seam = 1;
199                         if(e->flag & ME_SHARP) eed->sharp = 1;
200                         if(e->flag & SELECT) eed->f |= SELECT;
201                         if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
202                         if(e->flag & ME_HIDE) eed->h |= 1;
203                         if(G.scene->selectmode==SCE_SELECT_EDGE) 
204                                 EM_select_edge(eed, eed->f & SELECT);
205                         CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data);
206                 }
207         }
208
209         /* make faces */
210         CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
211         for (f=bm->polys.first;f;f=f->next) {
212                 len = BME_cycle_length(f->loopbase);
213                 if (len==3 || len==4) {
214                         eve1= evlist[f->loopbase->v->tflag1];
215                         eve2= evlist[f->loopbase->next->v->tflag1];
216                         eve3= evlist[f->loopbase->next->next->v->tflag1];
217                         if (len == 4) {
218                                 eve4= evlist[f->loopbase->prev->v->tflag1];
219                         }
220                         else {
221                                 eve4= NULL;
222                         }
223
224                         efa = addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
225                         CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data);
226                         efa->mat_nr = (unsigned char)f->mat_nr;
227                         efa->flag= f->flag & ~ME_HIDE;
228                         if(f->flag & ME_FACE_SEL) {
229                                 efa->f |= SELECT;
230                         }
231                         if(f->flag & ME_HIDE) efa->h= 1;
232                         if((G.f & G_FACESELECT) && (efa->f & SELECT))
233                                 EM_select_face(efa, 1); /* flush down */
234                 }
235         }
236
237         MEM_freeN(evlist);
238
239         countall();
240
241         return em;
242 }
243
244 /* Adds the geometry found in dm to bm
245  * NOTE: it does not allocate a new BME_Mesh!
246  */
247 BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm, BME_Mesh *bm)
248 {
249         MVert *mvert, *mv;
250         MEdge *medge, *me;
251         MFace *mface, *mf;
252         int totface,totedge,totvert,i,len;
253
254         BME_Vert *v1=NULL,*v2=NULL, **vert_array;
255         BME_Edge *e=NULL;
256         BME_Poly *f=NULL;
257         
258         EdgeHash *edge_hash = BLI_edgehash_new();
259         
260         totvert = dm->getNumVerts(dm);
261         totedge = dm->getNumEdges(dm);
262         totface = dm->getNumFaces(dm);
263         mvert = dm->getVertArray(dm);
264         medge = dm->getEdgeArray(dm);
265         mface = dm->getFaceArray(dm);
266
267         vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");
268
269         /*custom data*/
270         /* NOTE: I haven't tested whether or not custom data is being copied correctly */
271         CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH,
272                         CD_CALLOC, 0);
273         CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_DERIVEDMESH,
274                         CD_CALLOC, 0);
275         CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_DERIVEDMESH,
276                         CD_CALLOC, 0);
277         /*add verts*/
278         for(i=0,mv = mvert; i < totvert;i++,mv++){
279                 v1 = BME_MV(bm,mv->co);
280                 vert_array[i] = v1;
281                 v1->flag = mv->flag;
282                 v1->bweight = mv->bweight/255.0f;
283                 CustomData_to_em_block(&dm->vertData, &bm->vdata, i, &v1->data);
284         }
285         /*add edges*/
286         for(i=0,me = medge; i < totedge;i++,me++){
287                 v1 = vert_array[me->v1];
288                 v2 = vert_array[me->v2];
289                 e = BME_ME(bm, v1, v2);
290                 e->crease = me->crease/255.0f;
291                 e->bweight = me->bweight/255.0f;
292                 e->flag = (unsigned char)me->flag;
293                 BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
294                 CustomData_to_em_block(&dm->edgeData, &bm->edata, i, &e->data);
295         }
296         /*add faces.*/
297         for(i=0,mf = mface; i < totface;i++,mf++){
298                 BME_Edge *edar[4];
299                 if(mf->v4) len = 4;
300                 else len = 3;
301                 
302                 edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
303                 edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
304                 if(len == 4){
305                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
306                         edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
307                 }
308                 else
309                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
310                 
311                 /*find v1 and v2*/
312                 v1 = vert_array[mf->v1];
313                 v2 = vert_array[mf->v2];
314                 
315                 f = BME_MF(bm,v1,v2,edar,len);
316                 f->mat_nr = mf->mat_nr;
317                 f->flag = mf->flag;
318                 CustomData_to_em_block(&dm->faceData, &bm->pdata, i, &f->data);
319         }
320         
321         BLI_edgehash_free(edge_hash, NULL);
322         MEM_freeN(vert_array);
323         return bm;
324 }
325
326 DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
327 {
328         MFace *mface, *mf;
329         MEdge *medge, *me;
330         MVert *mvert, *mv;
331         int totface,totedge,totvert,i,bmeshok,len;
332
333         BME_Vert *v1=NULL;
334         BME_Edge *e=NULL, *oe=NULL;
335         BME_Poly *f=NULL;
336         
337         DerivedMesh *result;
338         EdgeHash *edge_hash = BLI_edgehash_new();
339
340         totvert = BLI_countlist(&(bm->verts));
341         totedge = 0;
342         
343         /*we cannot have double edges in a derived mesh!*/
344         for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i;
345         for(e=bm->edges.first; e; e=e->next){
346                 oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1);
347                 if(!oe){
348                         totedge++;
349                         BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e);
350                         e->tflag2 = 1;
351                 }
352                 else{
353                         e->tflag2 = 0;
354                 }
355         }
356         
357         /*count quads and tris*/
358         totface = 0;
359         bmeshok = 1;
360         for(f=bm->polys.first;f;f=f->next){
361                 len = BME_cycle_length(f->loopbase);
362                 if(len == 3 || len == 4) totface++;
363         }
364         
365         /*convert back to mesh*/
366         result = CDDM_from_template(dm,totvert,totedge,totface);
367         /*custom data*/
368         /* NOTE: I haven't tested whether or not custom data is being copied correctly */
369         CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_DERIVEDMESH,
370                         CD_CALLOC, totvert);
371         CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_DERIVEDMESH,
372                         CD_CALLOC, totedge);
373         CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_DERIVEDMESH,
374                         CD_CALLOC, totface);
375         /*Make Verts*/
376         mvert = CDDM_get_verts(result);
377         for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){
378                 VECCOPY(mv->co,v1->co);
379                 mv->flag = (unsigned char)v1->flag;
380                 mv->bweight = (char)(255.0*v1->bweight);
381                 CustomData_from_em_block(&bm->vdata, &result->vertData, v1->data, i);
382         }
383         medge = CDDM_get_edges(result);
384         i=0;
385         for(e=bm->edges.first,me=medge;e;e=e->next){
386                 if(e->tflag2){
387                         if(e->v1->tflag1 < e->v2->tflag1){
388                                 me->v1 = e->v1->tflag1;
389                                 me->v2 = e->v2->tflag1;
390                         }
391                         else{
392                                 me->v1 = e->v2->tflag1;
393                                 me->v2 = e->v1->tflag1;
394                         }
395                 
396                         me->crease = (char)(255.0*e->crease);
397                         me->bweight = (char)(255.0*e->bweight);
398                         me->flag = e->flag;
399                         CustomData_from_em_block(&bm->edata, &result->edgeData, e->data, i);
400                         me++;
401                         i++;
402                 }
403         }
404         if(totface){
405                 mface = CDDM_get_faces(result);
406                 /*make faces*/
407                 for(i=0,f=bm->polys.first;f;f=f->next){
408                         mf = &mface[i];
409                         len = BME_cycle_length(f->loopbase);
410                         if(len==3 || len==4){
411                                 mf->v1 = f->loopbase->v->tflag1;
412                                 mf->v2 = f->loopbase->next->v->tflag1;
413                                 mf->v3 = f->loopbase->next->next->v->tflag1;
414                                 if(len == 4){
415                                         mf->v4 = f->loopbase->prev->v->tflag1;
416                                 }
417                                 /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
418                                 if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){
419                                         test_index_face(mf, NULL, i, len);
420                                 }
421                                 i++;
422                                 mf->mat_nr = (unsigned char)f->mat_nr;
423                                 mf->flag = (unsigned char)f->flag;
424                                 CustomData_from_em_block(&bm->pdata, &result->faceData, f->data, i);
425                         }
426                 }
427         }
428         BLI_edgehash_free(edge_hash, NULL);
429         return result;
430 }