08483711c45bf95adeddc120e050f3ed4c5979ef
[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
37 #include "DNA_listBase.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "BKE_utildefines.h"
43 #include "BKE_mesh.h"
44 #include "BKE_bmesh.h"
45 #include "BKE_global.h"
46 #include "BKE_DerivedMesh.h"
47 #include "BKE_cdderivedmesh.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_editVert.h"
51 #include "BLI_edgehash.h"
52 #include "BIF_editmesh.h"
53 #include "editmesh.h"
54 #include "bmesh_private.h"
55
56 #include "BSE_edit.h"
57
58 BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
59         BME_Mesh *bm;
60         int allocsize[4] = {512,512,2048,512};
61         BME_CustomDataInit *init = MEM_callocN(sizeof(BME_CustomDataInit) * 4, "Bmesh custom data init");
62         BME_Vert *v1, *v2;
63         BME_Edge *e, *edar[4];
64         BME_Poly *f;
65
66         EditVert *eve;
67         EditEdge *eed;
68         EditFace *efa;
69
70         int len;
71         bm = BME_make_mesh(allocsize,init);
72         BME_model_begin(bm);
73         
74         /*add verts*/
75         eve= em->verts.first;
76         while(eve) {
77                 v1 = BME_MV(bm,eve->co);
78                 VECCOPY(v1->no,eve->no);
79                 v1->flag = eve->f;
80                 v1->h = eve->h;
81                 v1->bweight = eve->bweight;
82
83                 /* link the verts for edge and face construction;
84                  * kind of a dangerous thing - remember to cast back to BME_Vert before using! */
85                 eve->tmp.v = (EditVert*)v1;
86                 eve = eve->next;
87         }
88         
89         /*add edges*/
90         eed= em->edges.first;
91         while(eed) {
92                 v1 = (BME_Vert*)eed->v1->tmp.v;
93                 v2 = (BME_Vert*)eed->v2->tmp.v;
94                 e = BME_ME(bm, v1, v2);
95                 e->crease = eed->crease;
96                 e->bweight = eed->bweight;
97                 e->flag = eed->f & SELECT;
98                 if(eed->sharp) e->flag |= ME_SHARP;
99                 if(eed->seam) e->flag |= ME_SEAM;
100                 if(eed->h & EM_FGON) e->flag |= ME_FGON;
101                 if(eed->h & 1) e->flag |= ME_HIDE;
102
103                 /* link the edges for face construction;
104                  * kind of a dangerous thing - remember to cast back to BME_Edge before using! */
105                 eed->tmp.e = (EditEdge*)e;
106                 eed = eed->next;
107         }
108
109         /*add faces.*/
110         efa= em->faces.first;
111         while(efa) {
112                 if(efa->v4) len = 4;
113                 else len = 3;
114                 
115                 edar[0] = (BME_Edge*)efa->e1->tmp.e;
116                 edar[1] = (BME_Edge*)efa->e2->tmp.e;
117                 edar[2] = (BME_Edge*)efa->e3->tmp.e;
118                 if(len == 4){
119                         edar[3] = (BME_Edge*)efa->e4->tmp.e;
120                 }
121                 
122                 /*find v1 and v2*/
123                 v1 = (BME_Vert*)efa->v1->tmp.v;
124                 v2 = (BME_Vert*)efa->v2->tmp.v;
125                 
126                 f = BME_MF(bm,v1,v2,edar,len);
127                 f->mat_nr = efa->mat_nr;
128                 f->flag = efa->flag;
129                 if(efa->h) {
130                         f->flag |= ME_HIDE;
131                         f->flag &= ~ME_FACE_SEL;
132                 }
133                 else {
134                         if(efa->f & 1) f->flag |= ME_FACE_SEL;
135                         else f->flag &= ~ME_FACE_SEL;
136                 }
137                 efa = efa->next;
138         }
139         BME_model_end(bm);
140         MEM_freeN(init);
141         return bm;
142 }
143
144 /* adds the geometry in the bmesh to G.editMesh (does not free G.editMesh)
145  * if td != NULL, the transdata will be mapped to the EditVert's co */
146 EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) {
147         BME_Vert *v1;
148         BME_Edge *e;
149         BME_Poly *f;
150         
151         BME_TransData *vtd;
152
153         EditMesh *em;
154         EditVert *eve1, *eve2, *eve3, *eve4, **evlist;
155         EditEdge *eed;
156         EditFace *efa;
157
158         int totvert, len, i;
159
160         em = G.editMesh;
161
162         if (em == NULL) return NULL;
163
164         /* convert to EditMesh */
165         /* make editverts */
166         totvert = BLI_countlist(&(bm->verts));
167         evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist");
168         for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) {
169                 v1->tflag1 = i;
170                 eve1 = addvertlist(v1->co,NULL);
171                 if (td && (vtd = BME_get_transdata(td,v1))) {
172                         vtd->loc = eve1->co;
173                 }
174                 eve1->keyindex = i;
175                 evlist[i]= eve1;
176                 eve1->f = (unsigned char)v1->flag;
177                 eve1->h = (unsigned char)v1->h;
178                 eve1->bweight = v1->bweight;
179         }
180         
181         /* make edges */
182         for (e=bm->edges.first;e;e=e->next) {
183                 if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
184                         eed= addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
185                         eed->crease = e->crease;
186                         eed->bweight = e->bweight;
187                         if(e->flag & ME_SEAM) eed->seam = 1;
188                         if(e->flag & ME_SHARP) eed->sharp = 1;
189                         if(e->flag & SELECT) eed->f |= SELECT;
190                         if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
191                         if(e->flag & ME_HIDE) eed->h |= 1;
192                         if(G.scene->selectmode==SCE_SELECT_EDGE) 
193                                 EM_select_edge(eed, eed->f & SELECT);
194                 }
195         }
196
197         /* make faces */
198         for (f=bm->polys.first;f;f=f->next) {
199                 len = BME_cycle_length(f->loopbase);
200                 if (len==3 || len==4) {
201                         eve1= evlist[f->loopbase->v->tflag1];
202                         eve2= evlist[f->loopbase->next->v->tflag1];
203                         eve3= evlist[f->loopbase->next->next->v->tflag1];
204                         if (len == 4) {
205                                 eve4= evlist[f->loopbase->prev->v->tflag1];
206                         }
207                         else {
208                                 eve4= NULL;
209                         }
210
211                         efa = addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
212                         efa->mat_nr = (unsigned char)f->mat_nr;
213                         efa->flag= f->flag & ~ME_HIDE;
214                         if(f->flag & ME_FACE_SEL) {
215                                 efa->f |= SELECT;
216                         }
217                         if(f->flag & ME_HIDE) efa->h= 1;
218                         if((G.f & G_FACESELECT) && (efa->f & SELECT))
219                                 EM_select_face(efa, 1); /* flush down */
220                 }
221         }
222
223         MEM_freeN(evlist);
224
225         countall();
226
227         return em;
228 }
229
230 /* Adds the geometry found in dm to bm
231   */
232 BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
233 {
234         
235         BME_Mesh *bm;
236         int allocsize[4] = {512,512,2048,512};
237         BME_CustomDataInit *init = MEM_callocN(sizeof(BME_CustomDataInit) * 4, "Bmesh custom data init");
238         MVert *mvert, *mv;
239         MEdge *medge, *me;
240         MFace *mface, *mf;
241         int totface,totedge,totvert,i,len;
242         BME_Vert *v1=NULL,*v2=NULL, **vert_array;
243         BME_Edge *e=NULL;
244         BME_Poly *f=NULL;
245         
246         EdgeHash *edge_hash = BLI_edgehash_new();
247
248         bm = BME_make_mesh(allocsize,init);
249         totvert = dm->getNumVerts(dm);
250         totedge = dm->getNumEdges(dm);
251         totface = dm->getNumFaces(dm);
252         mvert = dm->getVertArray(dm);
253         medge = dm->getEdgeArray(dm);
254         mface = dm->getFaceArray(dm);
255
256         vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");
257
258         BME_model_begin(bm);
259         /*add verts*/
260         for(i=0,mv = mvert; i < totvert;i++,mv++){
261                 v1 = BME_MV(bm,mv->co);
262                 vert_array[i] = v1;
263                 v1->flag = mv->flag;
264                 v1->bweight = mv->bweight/255.0f;
265         }
266         /*add edges*/
267         for(i=0,me = medge; i < totedge;i++,me++){
268                 v1 = vert_array[me->v1];
269                 v2 = vert_array[me->v2];
270                 e = BME_ME(bm, v1, v2);
271                 e->crease = me->crease/255.0f;
272                 e->bweight = me->bweight/255.0f;
273                 e->flag = (unsigned char)me->flag;
274                 BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
275         }
276         /*add faces.*/
277         for(i=0,mf = mface; i < totface;i++,mf++){
278                 BME_Edge *edar[4];
279                 if(mf->v4) len = 4;
280                 else len = 3;
281                 
282                 edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
283                 edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
284                 if(len == 4){
285                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
286                         edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
287                 }
288                 else
289                         edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
290                 
291                 /*find v1 and v2*/
292                 v1 = vert_array[mf->v1];
293                 v2 = vert_array[mf->v2];
294                 
295                 f = BME_MF(bm,v1,v2,edar,len);
296                 f->mat_nr = mf->mat_nr;
297                 f->flag = mf->flag;
298         }
299         
300         BME_model_end(bm);
301         BLI_edgehash_free(edge_hash, NULL);
302         MEM_freeN(vert_array);
303         MEM_freeN(init);
304         return bm;
305 }
306
307 DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
308 {
309         MFace *mface, *mf;
310         MEdge *medge, *me;
311         MVert *mvert, *mv;
312         int totface,totedge,totvert,i,bmeshok,len;
313
314         BME_Vert *v1=NULL;
315         BME_Edge *e=NULL, *oe=NULL;
316         BME_Poly *f=NULL;
317         
318         DerivedMesh *result;
319         EdgeHash *edge_hash = BLI_edgehash_new();
320
321         totvert = BLI_countlist(&(bm->verts));
322         totedge = 0;
323         
324         /*we cannot have double edges in a derived mesh!*/
325         for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i;
326         for(e=bm->edges.first; e; e=e->next){
327                 oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1);
328                 if(!oe){
329                         totedge++;
330                         BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e);
331                         e->tflag2 = 1;
332                 }
333                 else{
334                         e->tflag2 = 0;
335                 }
336         }
337         
338         /*count quads and tris*/
339         totface = 0;
340         bmeshok = 1;
341         for(f=bm->polys.first;f;f=f->next){
342                 len = BME_cycle_length(f->loopbase);
343                 if(len == 3 || len == 4) totface++;
344         }
345         
346         /*convert back to mesh*/
347         result = CDDM_from_template(dm,totvert,totedge,totface);
348         /*Make Verts*/
349         mvert = CDDM_get_verts(result);
350         for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){
351                 VECCOPY(mv->co,v1->co);
352                 mv->flag = (unsigned char)v1->flag;
353                 mv->bweight = (char)(255.0*v1->bweight);
354         }
355         medge = CDDM_get_edges(result);
356         i=0;
357         for(e=bm->edges.first,me=medge;e;e=e->next){
358                 if(e->tflag2){
359                         if(e->v1->tflag1 < e->v2->tflag1){
360                                 me->v1 = e->v1->tflag1;
361                                 me->v2 = e->v2->tflag1;
362                         }
363                         else{
364                                 me->v1 = e->v2->tflag1;
365                                 me->v2 = e->v1->tflag1;
366                         }
367                 
368                         me->crease = (char)(255.0*e->crease);
369                         me->bweight = (char)(255.0*e->bweight);
370                         me->flag = e->flag;
371                         me++;
372                         i++;
373                 }
374         }
375         if(totface){
376                 mface = CDDM_get_faces(result);
377                 /*make faces*/
378                 for(i=0,f=bm->polys.first;f;f=f->next){
379                         mf = &mface[i];
380                         len = BME_cycle_length(f->loopbase);
381                         if(len==3 || len==4){
382                                 mf->v1 = f->loopbase->v->tflag1;
383                                 mf->v2 = f->loopbase->next->v->tflag1;
384                                 mf->v3 = f->loopbase->next->next->v->tflag1;
385                                 if(len == 4){
386                                         mf->v4 = f->loopbase->prev->v->tflag1;
387                                 }
388                                 /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
389                                 if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){
390                                         test_index_face(mf, NULL, i, len);
391                                 }
392                                 i++;
393                                 mf->mat_nr = (unsigned char)f->mat_nr;
394                                 mf->flag = (unsigned char)f->flag;
395                         }
396                 }
397         }
398         BLI_edgehash_free(edge_hash, NULL);
399         return result;
400 }