15bc1f25bbad126093b6f6b2e714e4b1afdb5c11
[blender-staging.git] / source / blender / bmesh / operators / mesh_conv.c
1 #include <string.h>
2
3 #include "MEM_guardedalloc.h"
4
5 #include "DNA_listBase.h"
6 #include "DNA_customdata_types.h"
7 #include "DNA_mesh_types.h"
8 #include "DNA_meshdata_types.h"
9 #include "DNA_object_types.h"
10 #include "DNA_scene_types.h"
11
12 #include "BKE_customdata.h" 
13 #include "BKE_utildefines.h"
14 #include "BKE_mesh.h"
15 #include "BKE_global.h"
16 #include "BKE_DerivedMesh.h"
17 #include "BKE_cdderivedmesh.h"
18
19 #include "BLI_blenlib.h"
20 #include "BLI_edgehash.h"
21 #include "BLI_editVert.h"
22 #include "BLI_scanfill.h"
23 #include "BLI_array.h"
24
25 #include "ED_mesh.h"
26
27 #include "mesh_intern.h"
28 #include "bmesh.h"
29
30 /*
31  * MESH CONV.C
32  *
33  * This file contains functions
34  * for converting a Mesh
35  * into a Bmesh, and back again.
36  *
37 */
38
39 void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
40         Mesh *me = BMO_Get_Pnt(op, "mesh");
41         MVert *mvert;
42         MEdge *medge;
43         MLoop *ml;
44         MPoly *mpoly;
45         BMVert *v, **vt=NULL;
46         BMEdge *e, **fedges=NULL, **et = NULL;
47         BLI_array_declare(fedges);
48         BMFace *f;
49         int i, j, li, allocsize[4] = {512, 512, 2048, 512};
50
51         if (!me || !me->totvert) return; /*sanity check*/
52         
53         mvert = me->mvert;
54
55         vt = MEM_mallocN(sizeof(void**)*me->totvert, "mesh to bmesh vtable");
56
57         CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
58         CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
59         CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
60         CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
61
62         CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
63         CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
64         CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
65         CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
66
67         for (i=0; i<me->totvert; i++, mvert++) {
68                 v = BM_Make_Vert(bm, mvert->co, NULL);
69                 VECCOPY(v->no, mvert->no);
70
71                 vt[i] = v;
72                 BMINDEX_SET(v, i);
73
74                 /*this is necassary for selection counts to work properly*/
75                 if(v->head.flag & BM_SELECT) BM_Select_Vert(bm, v, 1);
76
77                 /*transfer flags*/
78                 v->head.flag = MEFlags_To_BMFlags(mvert->flag, BM_VERT);
79                 v->bweight = (float)mvert->bweight / 255.0f;
80
81                 /*Copy Custom Data*/
82                 CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
83         }
84
85         if (!me->totedge) {
86                 MEM_freeN(vt);
87                 return;
88         }
89
90         et = MEM_mallocN(sizeof(void**)*me->totedge, "mesh to bmesh etable");
91
92         medge = me->medge;
93         for (i=0; i<me->totedge; i++, medge++) {
94                 e = BM_Make_Edge(bm, vt[medge->v1], vt[medge->v2], NULL, 0);
95                 et[i] = e;
96                 
97                 /*Copy Custom Data*/
98                 CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data);
99                 
100                 e->crease = (float)medge->crease / 255.0f;
101                 e->bweight = (float)medge->bweight / 255.0f;
102
103                 /*this is necassary for selection counts to work properly*/
104                 if (e->head.flag & BM_SELECT) BM_Select(bm, e, 1);
105
106                 /*transfer flags*/
107                 e->head.flag = MEFlags_To_BMFlags(medge->flag, BM_EDGE);
108         }
109         
110         if (!me->totpoly) {
111                 MEM_freeN(vt);
112                 MEM_freeN(et);
113                 return;
114         }
115
116         mpoly = me->mpoly;
117         li = 0;
118         for (i=0; i<me->totpoly; i++, mpoly++) {
119                 BMVert *v1, *v2;
120                 BMIter iter;
121                 BMLoop *l;
122
123                 BLI_array_empty(fedges);
124                 for (j=0; j<mpoly->totloop; j++) {
125                         ml = &me->mloop[mpoly->loopstart+j];
126                         v = vt[ml->v];
127                         e = et[ml->e];
128
129                         BLI_array_growone(fedges);
130
131                         fedges[j] = e;
132                 }
133                 
134                 v1 = vt[me->mloop[mpoly->loopstart].v];
135                 v2 = vt[me->mloop[mpoly->loopstart+1].v];
136
137                 if (v1 == fedges[0]->v1) v2 = fedges[0]->v2;
138                 else {
139                         v1 = fedges[0]->v2;
140                         v2 = fedges[0]->v1;
141                 }
142
143                 f = BM_Make_Ngon(bm, v1, v2, fedges, mpoly->totloop, 0);
144
145                 if (!f) {
146                         printf("Warning! Bad face in mesh"
147                                " \"%s\" at index %d!\n", me->id.name+2, i);
148                         continue;
149                 }
150
151                 /*this is necassary for selection counts to work properly*/
152                 if (f->head.flag & BM_SELECT) BM_Select(bm, f, 1);
153
154                 /*transfer flags*/
155                 f->head.flag = MEFlags_To_BMFlags(mpoly->flag, BM_FACE);
156
157                 f->mat_nr = mpoly->mat_nr;
158                 if (i == me->act_face) bm->act_face = f;
159
160                 /*Copy over loop customdata*/
161                 BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
162                         CustomData_to_bmesh_block(&me->ldata, &bm->ldata, li, &l->head.data);
163                         li++;
164                 }
165
166                 /*Copy Custom Data*/
167                 CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data);
168         }
169
170         BLI_array_free(fedges);
171
172         MEM_freeN(vt);
173         MEM_freeN(et);
174 }
175
176
177 static void loops_to_corners(BMesh *bm, Mesh *me, int findex,
178                              BMFace *f, BMLoop *ls[3], int numTex, int numCol) 
179 {
180         BMLoop *l;
181         MTFace *texface;
182         MTexPoly *texpoly;
183         MCol *mcol;
184         MLoopCol *mloopcol;
185         MLoopUV *mloopuv;
186         int i, j;
187
188         for(i=0; i < numTex; i++){
189                 texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
190                 texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
191                 
192                 texface->tpage = texpoly->tpage;
193                 texface->flag = texpoly->flag;
194                 texface->transp = texpoly->transp;
195                 texface->mode = texpoly->mode;
196                 texface->tile = texpoly->tile;
197                 texface->unwrap = texpoly->unwrap;
198
199                 for (j=0; j<3; j++) {
200                         l = ls[j];
201                         mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
202                         texface->uv[j][0] = mloopuv->uv[0];
203                         texface->uv[j][1] = mloopuv->uv[1];
204                 }
205         }
206
207         for(i=0; i < numCol; i++){
208                 mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
209
210                 for (j=0; j<3; j++) {
211                         l = ls[j];
212                         mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
213                         mcol[j].r = mloopcol->r;
214                         mcol[j].g = mloopcol->g;
215                         mcol[j].b = mloopcol->b;
216                         mcol[j].a = mloopcol->a;
217                 }
218         }
219 }
220
221 void object_load_bmesh_exec(BMesh *bm, BMOperator *op) {
222         Object *ob = BMO_Get_Pnt(op, "object");
223         Scene *scene = BMO_Get_Pnt(op, "scene");
224         Mesh *me = ob->data;
225
226         BMO_CallOpf(bm, "bmesh_to_mesh meshptr=%p", me);
227
228         /*BMESH_TODO eventually we'll have to handle shapekeys here*/
229 }
230
231 void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
232         Mesh *me = BMO_Get_Pnt(op, "meshptr");
233         MLoop *mloop;
234         MPoly *mpoly;
235         MVert *mvert, *oldverts;
236         MEdge *medge;
237         MFace *mface;
238         BMVert *v;
239         BMEdge *e;
240         BMLoop *l;
241         BMFace *f;
242         BMIter iter, liter;
243         int i, j, ototvert, totloop, totface, numTex, numCol;
244         int dotess = !BMO_Get_Int(op, "notesselation");
245
246         numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
247         numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
248
249         /* new Vertex block */
250         if(bm->totvert==0) mvert= NULL;
251         else mvert= MEM_callocN(bm->totvert*sizeof(MVert), "loadeditbMesh vert");
252
253         /* new Edge block */
254         if(bm->totedge==0) medge= NULL;
255         else medge= MEM_callocN(bm->totedge*sizeof(MEdge), "loadeditbMesh edge");
256         
257         /*build ngon data*/
258         /* new Ngon Face block */
259         if(bm->totface==0) mpoly = NULL;
260         else mpoly= MEM_callocN(bm->totface*sizeof(MPoly), "loadeditbMesh poly");
261         
262         /*find number of loops to allocate*/
263         totloop = 0;
264         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
265                 totloop += f->len;
266         }
267
268         if (totloop==0) mloop = NULL;
269         else mloop = MEM_callocN(totloop*sizeof(MLoop), "loadeditbMesh loop");
270
271         /* lets save the old verts just in case we are actually working on
272          * a key ... we now do processing of the keys at the end */
273         oldverts= me->mvert;
274
275         /* don't free this yet */
276         CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
277
278         /* free custom data */
279         CustomData_free(&me->vdata, me->totvert);
280         CustomData_free(&me->edata, me->totedge);
281         CustomData_free(&me->fdata, me->totface);
282         CustomData_free(&me->ldata, me->totloop);
283         CustomData_free(&me->pdata, me->totpoly);
284
285         /* add new custom data */
286         me->totvert= bm->totvert;
287         me->totedge= bm->totedge;
288         me->totloop= totloop;
289         me->totpoly= bm->totface;
290
291         CustomData_copy(&bm->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
292         CustomData_copy(&bm->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
293         CustomData_copy(&bm->ldata, &me->ldata, CD_MASK_MESH, CD_CALLOC, me->totloop);
294         CustomData_copy(&bm->pdata, &me->pdata, CD_MASK_MESH, CD_CALLOC, me->totpoly);
295
296         CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
297         CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
298         CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
299         CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
300
301         i = 0;
302         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
303                 VECCOPY(mvert->co, v->co);
304
305                 mvert->no[0] = (short) (v->no[0]*32767.0f);
306                 mvert->no[1] = (short) (v->no[1]*32767.0f);
307                 mvert->no[2] = (short) (v->no[2]*32767.0f);
308                 
309                 mvert->flag = BMFlags_To_MEFlags(v);
310
311                 BMINDEX_SET(v, i);
312
313                 /*copy over customdata*/
314                 CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
315
316                 i++;
317                 mvert++;
318         }
319
320         i = 0;
321         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
322                 medge->v1 = BMINDEX_GET(e->v1);
323                 medge->v2 = BMINDEX_GET(e->v2);
324
325                 medge->flag = BMFlags_To_MEFlags(e);
326
327                 BMINDEX_SET(e, i);
328
329                 /*copy over customdata*/
330                 CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i);
331
332                 i++;
333                 medge++;
334         }
335
336         /*new scanfill tesselation code*/
337         if (dotess) {
338                 /*first counter number of faces we'll need*/
339                 totface = 0;
340                 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
341                         EditVert *eve, *lasteve = NULL, *firsteve = NULL;
342                         EditFace *efa;
343                         
344                         i = 0;
345                         BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
346                                 eve = BLI_addfillvert(l->v->co);
347                                 eve->tmp.p = l;
348                                 
349                                 BMINDEX_SET(l, i);
350
351                                 if (lasteve) {
352                                         BLI_addfilledge(lasteve, eve);
353                                 }
354
355                                 lasteve = eve;
356                                 if (!firsteve) firsteve = eve;
357
358                                 i++;
359                         }
360
361                         BLI_addfilledge(lasteve, firsteve);
362                         BLI_edgefill(0, 0);
363
364                         for (efa=fillfacebase.first; efa; efa=efa->next)
365                                 totface++;
366
367                         BLI_end_edgefill();
368                 }
369                 
370                 me->totface = totface;
371
372                 /* new tess face block */
373                 if(totface==0) mface= NULL;
374                 else mface= MEM_callocN(totface*sizeof(MFace), "loadeditbMesh face");
375
376                 CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
377                 CustomData_from_bmeshpoly(&me->fdata, &bm->pdata, &bm->ldata, totface);
378
379                 mesh_update_customdata_pointers(me);
380                 
381                 i = 0;
382                 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
383                         EditVert *eve, *lasteve = NULL, *firsteve = NULL;
384                         EditFace *efa;
385                         BMLoop *ls[3];
386                         
387                         BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
388                                 eve = BLI_addfillvert(l->v->co);
389                                 eve->tmp.p = l;
390
391                                 if (lasteve) {
392                                         BLI_addfilledge(lasteve, eve);
393                                 }
394
395                                 lasteve = eve;
396                                 if (!firsteve) firsteve = eve;
397                         }
398
399                         BLI_addfilledge(lasteve, firsteve);
400                         BLI_edgefill(0, 0);
401
402                         for (efa=fillfacebase.first; efa; efa=efa->next) {
403                                 ls[0] = efa->v1->tmp.p;
404                                 ls[1] = efa->v2->tmp.p;
405                                 ls[2] = efa->v3->tmp.p;
406                                 
407                                 /*ensure correct winding.  I believe this is
408                                   analogous to bubble sort on three elements.*/
409                                 if (BMINDEX_GET(ls[0]) > BMINDEX_GET(ls[1])) {
410                                         SWAP(BMLoop*, ls[0], ls[1]);
411                                 }
412                                 if (BMINDEX_GET(ls[1]) > BMINDEX_GET(ls[2])) {
413                                         SWAP(BMLoop*, ls[1], ls[2]);
414                                 }
415                                 if (BMINDEX_GET(ls[0]) > BMINDEX_GET(ls[1])) {
416                                         SWAP(BMLoop*, ls[0], ls[1]);
417                                 }
418
419                                 mface->mat_nr = f->mat_nr;
420                                 mface->flag = BMFlags_To_MEFlags(f);
421                                 
422                                 mface->v1 = BMINDEX_GET(ls[0]->v);
423                                 mface->v2 = BMINDEX_GET(ls[1]->v);
424                                 mface->v3 = BMINDEX_GET(ls[2]->v);
425
426                                 test_index_face(mface, &me->fdata, i, 1);
427                                 
428                                 loops_to_corners(bm, me, i, f, ls, numTex, numCol);
429                                 mface++;
430                                 i++;
431                         }
432                         BLI_end_edgefill();
433                 }
434         }
435
436         i = 0;
437         j = 0;
438         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
439                 mpoly->loopstart = j;
440                 mpoly->totloop = f->len;
441                 mpoly->mat_nr = f->mat_nr;
442                 mpoly->flag = BMFlags_To_MEFlags(f);
443
444                 l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
445                 for ( ; l; l=BMIter_Step(&liter), j++, mloop++) {
446                         mloop->e = BMINDEX_GET(l->e);
447                         mloop->v = BMINDEX_GET(l->v);
448
449                         /*copy over customdata*/
450                         CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l->head.data, j);
451                 }
452                 
453                 if (f == bm->act_face) me->act_face = i;
454
455                 /*copy over customdata*/
456                 CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i);
457
458                 i++;
459                 mpoly++;
460         }
461
462         mesh_update_customdata_pointers(me);
463 }