remove redundant casts.
[blender.git] / source / blender / blenkernel / intern / editderivedmesh.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/editderivedmesh.c
29  *  \ingroup bke
30  */
31
32 #include <string.h>
33 #include <limits.h>
34 #include <math.h>
35
36 #include "GL/glew.h"
37
38 #include "BLI_utildefines.h"
39 #include "BLI_blenlib.h"
40 #include "BLI_edgehash.h"
41 #include "BLI_editVert.h"
42 #include "BLI_math.h"
43 #include "BLI_pbvh.h"
44
45 #include "BKE_cdderivedmesh.h"
46 #include "BKE_global.h"
47 #include "BKE_mesh.h"
48 #include "BKE_paint.h"
49
50
51 #include "DNA_meshdata_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_curve_types.h" /* for Curve */
54
55 #include "MEM_guardedalloc.h"
56
57 #include "GPU_buffers.h"
58 #include "GPU_draw.h"
59 #include "GPU_extensions.h"
60 #include "GPU_material.h"
61
62 /* bmesh */
63 #include "BKE_tessmesh.h"
64 #include "BLI_array.h"
65 #include "BLI_scanfill.h"
66
67 #include "bmesh.h"
68 /* end bmesh */
69
70 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
71
72
73 BMEditMesh *BMEdit_Create(BMesh *bm, int do_tesselate)
74 {
75         BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
76
77         tm->bm = bm;
78         if (do_tesselate) {
79                 BMEdit_RecalcTesselation(tm);
80         }
81
82         return tm;
83 }
84
85 BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
86 {
87         BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
88         *tm2 = *tm;
89
90         tm2->derivedCage = tm2->derivedFinal = NULL;
91
92         tm2->bm = BM_Copy_Mesh(tm->bm);
93
94         /*The tesselation is NOT calculated on the copy here,
95           because currently all the callers of this function use
96           it to make a backup copy of the BMEditMesh to restore
97           it in the case of errors in an operation. For perf
98           reasons, in that case it makes more sense to do the
99           tesselation only when/if that copy ends up getting
100           used.*/
101         tm2->looptris = NULL;
102
103         tm2->vert_index = NULL;
104         tm2->edge_index = NULL;
105         tm2->face_index = NULL;
106
107         return tm2;
108 }
109
110 static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
111 {
112         /* use this to avoid locking pthread for _every_ polygon
113          * and calling the fill function */
114 #define USE_TESSFACE_SPEEDUP
115
116         BMesh *bm = tm->bm;
117         BMLoop *(*looptris)[3]= NULL;
118         BLI_array_declare(looptris);
119         BMIter iter, liter;
120         BMFace *f;
121         BMLoop *l;
122         int i = 0, j;
123
124 #if 0
125         /* note, we could be clever and re-use this array but would need to ensure
126          * its realloced at some point, for now just free it */
127         if (tm->looptris) MEM_freeN(tm->looptris);
128
129         /* Use tm->tottri when set, this means no reallocs while transforming,
130          * (unless scanfill fails), otherwise... */
131         /* allocate the length of totfaces, avoid many small reallocs,
132          * if all faces are tri's it will be correct, quads == 2x allocs */
133         BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
134 #else
135
136         /* this means no reallocs for quad dominant models, for */
137         if ( (tm->looptris != NULL) &&
138              (tm->tottri != 0) &&
139              /* (totrti <= bm->totface * 2) would be fine for all quads,
140                   * but incase there are some ngons, still re-use the array */
141              (tm->tottri <= bm->totface * 3))
142         {
143                 looptris = tm->looptris;
144         }
145         else {
146                 if (tm->looptris) MEM_freeN(tm->looptris);
147                 BLI_array_reserve(looptris, bm->totface);
148         }
149
150 #endif
151
152         f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
153         for ( ; f; f=BMIter_Step(&iter)) {
154                 /*don't consider two-edged faces*/
155                 if (f->len < 3) {
156                         /* do nothing */
157                 }
158
159 #ifdef USE_TESSFACE_SPEEDUP
160
161                 /* no need to ensure the loop order, we know its ok */
162
163                 else if (f->len == 3) {
164                         BLI_array_growone(looptris);
165                         l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
166                         for (j=0; l; l=BMIter_Step(&liter), j++) {
167                                 looptris[i][j] = l;
168                         }
169                         i += 1;
170                 }
171                 else if (f->len == 4) {
172                         BMLoop *ltmp[4];
173                         BLI_array_growitems(looptris, 2);
174
175                         l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
176                         for (j=0; l; l=BMIter_Step(&liter), j++) {
177                                 ltmp[j] = l;
178                         }
179
180                         looptris[i][0] = ltmp[0];
181                         looptris[i][1] = ltmp[1];
182                         looptris[i][2] = ltmp[2];
183                         i += 1;
184
185                         looptris[i][0] = ltmp[0];
186                         looptris[i][1] = ltmp[2];
187                         looptris[i][2] = ltmp[3];
188                         i += 1;
189                 }
190
191 #endif /* USE_TESSFACE_SPEEDUP */
192
193                 else {
194                         EditVert *v, *lastv=NULL, *firstv=NULL;
195                         EditEdge *e;
196                         EditFace *efa;
197                         int totfilltri;
198
199                         BLI_begin_edgefill();
200                         /*scanfill time*/
201                         l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
202                         for (j=0; l; l=BMIter_Step(&liter), j++) {
203                                 /*mark order*/
204                                 BM_SetIndex(l, j); /* set_loop */
205
206                                 v = BLI_addfillvert(l->v->co);
207                                 v->tmp.p = l;
208
209                                 if (lastv) {
210                                         e = BLI_addfilledge(lastv, v);
211                                 }
212
213                                 lastv = v;
214                                 if (firstv==NULL) firstv = v;
215                         }
216
217                         /*complete the loop*/
218                         BLI_addfilledge(firstv, v);
219
220                         totfilltri = BLI_edgefill(2);
221                         BLI_array_growitems(looptris, totfilltri);
222
223                         for (efa = fillfacebase.first; efa; efa=efa->next) {
224                                 BMLoop *l1= efa->v1->tmp.p;
225                                 BMLoop *l2= efa->v2->tmp.p;
226                                 BMLoop *l3= efa->v3->tmp.p;
227
228                                 if (BM_GetIndex(l1) > BM_GetIndex(l2)) { SWAP(BMLoop*, l1, l2); }
229                                 if (BM_GetIndex(l2) > BM_GetIndex(l3)) { SWAP(BMLoop*, l2, l3); }
230                                 if (BM_GetIndex(l1) > BM_GetIndex(l2)) { SWAP(BMLoop*, l1, l2); }
231
232                                 looptris[i][0] = l1;
233                                 looptris[i][1] = l2;
234                                 looptris[i][2] = l3;
235                                 i += 1;
236                         }
237
238                         BLI_end_edgefill();
239                 }
240         }
241
242         tm->tottri = i;
243         tm->looptris = looptris;
244
245 #undef USE_TESSFACE_SPEEDUP
246
247 }
248
249 void BMEdit_RecalcTesselation(BMEditMesh *em)
250 {
251         BMEdit_RecalcTesselation_intern(em);
252
253         /* commented because editbmesh_build_data() ensures we get tessfaces */
254 #if 0
255         if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
256                 if (em->derivedFinal->recalcTesselation)
257                         em->derivedFinal->recalcTesselation(em->derivedFinal);
258         }
259         else if (em->derivedFinal) {
260                 if (em->derivedCage->recalcTesselation)
261                         em->derivedCage->recalcTesselation(em->derivedCage);
262                 if (em->derivedFinal->recalcTesselation)
263                         em->derivedFinal->recalcTesselation(em->derivedFinal);
264         }
265 #endif
266 }
267
268 void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
269 {
270         BMesh *bm = em->bm;
271         int act;
272
273         if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
274                 act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
275                 CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
276
277                 act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
278                 CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
279
280                 act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
281                 CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
282
283                 act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
284                 CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
285         }
286 }
287
288 /*does not free the BMEditMesh struct itself*/
289 void BMEdit_Free(BMEditMesh *em)
290 {
291         if (em->derivedFinal) {
292                 if (em->derivedFinal!=em->derivedCage) {
293                         em->derivedFinal->needsFree= 1;
294                         em->derivedFinal->release(em->derivedFinal);
295                 }
296                 em->derivedFinal= NULL;
297         }
298         if (em->derivedCage) {
299                 em->derivedCage->needsFree= 1;
300                 em->derivedCage->release(em->derivedCage);
301                 em->derivedCage= NULL;
302         }
303
304         if (em->looptris) MEM_freeN(em->looptris);
305
306         if (em->vert_index) MEM_freeN(em->vert_index);
307         if (em->edge_index) MEM_freeN(em->edge_index);
308         if (em->face_index) MEM_freeN(em->face_index);
309
310         if (em->bm)
311                 BM_Free_Mesh(em->bm);
312 }
313
314 /*
315 ok, basic design:
316
317 the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
318 to three loops per triangle.  the derivedmesh stores a cache of tesselations
319 for each face.  this cache will smartly update as needed (though at first
320 it'll simply be more brute force).  keeping track of face/edge counts may
321 be a small problbm.
322
323 this won't be the most efficient thing, considering that internal edges and
324 faces of tesselations are exposed.  looking up an edge by index in particular
325 is likely to be a little slow.
326 */
327
328 typedef struct EditDerivedBMesh {
329         DerivedMesh dm;
330
331         Object *ob;
332         BMEditMesh *tc;
333
334         float (*vertexCos)[3];
335         float (*vertexNos)[3];
336         float (*faceNos)[3];
337
338         /*lookup caches; these are rebuilt on dm->RecalcTesselation()
339           (or when the derivedmesh is created, of course)*/
340         BMVert **vtable;
341         BMEdge **etable;
342         BMFace **ftable;
343
344         /*private variables, for number of verts/edges/faces
345           within the above hash/table members*/
346         int tv, te, tf;
347 } EditDerivedBMesh;
348
349 static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
350 {
351         BMIter iter;
352         int a, i;
353
354         int iters[3] = {BM_VERTS_OF_MESH,
355                         BM_EDGES_OF_MESH,
356                         BM_FACES_OF_MESH};
357
358         BMHeader **iters_table[3] = {
359                 (BMHeader **)bmdm->vtable,
360                 (BMHeader **)bmdm->etable,
361                 (BMHeader **)bmdm->ftable};
362
363         bmdm->tv = bmdm->tc->bm->totvert;
364         bmdm->te = bmdm->tc->bm->totedge;
365         bmdm->tf = bmdm->tc->bm->totface;
366
367         if (bmdm->vtable) MEM_freeN(bmdm->vtable);
368         if (bmdm->etable) MEM_freeN(bmdm->etable);
369         if (bmdm->ftable) MEM_freeN(bmdm->ftable);
370
371         if (bmdm->tc->bm->totvert)
372                 bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
373         else bmdm->vtable = NULL;
374
375         if (bmdm->tc->bm->totedge)
376                 bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
377         else bmdm->etable = NULL;
378
379         if (bmdm->tc->bm->totface)
380                 bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
381         else bmdm->ftable = NULL;
382
383         for (a=0; a<3; a++) {
384                 BMHeader **table = iters_table[a];
385                 BMHeader *ele;
386
387                 ele = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
388                 for (i=0; ele; ele=BMIter_Step(&iter), i++) {
389                         table[i] = ele;
390                         BM_SetIndex(ele, i);  /* set_ok */
391                 }
392         }
393         bmdm->tc->bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
394
395 }
396
397 static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
398 {
399         /* Nothing to do: normals are already calculated and stored on the
400            BMVerts and BMFaces */
401 }
402
403 static void emDM_recalcTesselation(DerivedMesh *UNUSED(dm))
404 {
405         //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
406
407         //bmdm_recalc_lookups(bmdm);
408 }
409
410 static void emDM_foreachMappedVert(
411                 DerivedMesh *dm,
412                 void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
413                 void *userData)
414 {
415         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
416         BMVert *eve;
417         BMIter iter;
418         int i;
419
420         eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
421         for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
422                 if (bmdm->vertexCos) {
423                         func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
424                 }
425                 else {
426                         func(userData, i, eve->co, eve->no, NULL);
427                 }
428         }
429 }
430 static void emDM_foreachMappedEdge(
431                 DerivedMesh *dm,
432                 void (*func)(void *userData, int index, float *v0co, float *v1co),
433                 void *userData)
434 {
435         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
436         BMEdge *eed;
437         BMIter iter;
438         int i;
439
440         if (bmdm->vertexCos) {
441
442                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
443
444                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
445                 for (i=0; eed; i++,eed=BMIter_Step(&iter))
446                         func(userData, i,
447                                  bmdm->vertexCos[BM_GetIndex(eed->v1)],
448                                  bmdm->vertexCos[BM_GetIndex(eed->v2)]);
449         }
450         else {
451                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
452                 for (i=0; eed; i++,eed=BMIter_Step(&iter))
453                         func(userData, i, eed->v1->co, eed->v2->co);
454         }
455 }
456
457 static void emDM_drawMappedEdges(
458                 DerivedMesh *dm,
459                 int (*setDrawOptions)(void *userData, int index),
460                 void *userData)
461 {
462         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
463         BMEdge *eed;
464         BMIter iter;
465         int i;
466
467         if (bmdm->vertexCos) {
468
469                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
470
471                 glBegin(GL_LINES);
472                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
473                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
474                         if (!setDrawOptions || setDrawOptions(userData, i)) {
475                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
476                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
477                         }
478                 }
479                 glEnd();
480         }
481         else {
482                 glBegin(GL_LINES);
483                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
484                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
485                         if (!setDrawOptions || setDrawOptions(userData, i)) {
486                                 glVertex3fv(eed->v1->co);
487                                 glVertex3fv(eed->v2->co);
488                         }
489                 }
490                 glEnd();
491         }
492 }
493 static void emDM_drawEdges(
494                 DerivedMesh *dm,
495                 int UNUSED(drawLooseEdges),
496                 int UNUSED(drawAllEdges))
497 {
498         emDM_drawMappedEdges(dm, NULL, NULL);
499 }
500
501 static void emDM_drawMappedEdgesInterp(
502                 DerivedMesh *dm,
503                 int (*setDrawOptions)(void *userData, int index),
504                 void (*setDrawInterpOptions)(void *userData, int index, float t),
505                 void *userData)
506 {
507         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
508         BMEdge *eed;
509         BMIter iter;
510         int i;
511
512         if (bmdm->vertexCos) {
513
514                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
515
516                 glBegin(GL_LINES);
517                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
518                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
519                         if (!setDrawOptions || setDrawOptions(userData, i)) {
520                                 setDrawInterpOptions(userData, i, 0.0);
521                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
522                                 setDrawInterpOptions(userData, i, 1.0);
523                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
524                         }
525                 }
526                 glEnd();
527         }
528         else {
529                 glBegin(GL_LINES);
530                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
531                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
532                         if (!setDrawOptions || setDrawOptions(userData, i)) {
533                                 setDrawInterpOptions(userData, i, 0.0);
534                                 glVertex3fv(eed->v1->co);
535                                 setDrawInterpOptions(userData, i, 1.0);
536                                 glVertex3fv(eed->v2->co);
537                         }
538                 }
539                 glEnd();
540         }
541 }
542
543 static void emDM_drawUVEdges(DerivedMesh *dm)
544 {
545         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
546         BMEditMesh *em = bmdm->tc;
547         BMFace *efa;
548         BMIter iter;
549
550         glBegin(GL_LINES);
551         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
552                 BMIter liter;
553                 BMLoop *l;
554                 MLoopUV *lastluv = NULL, *firstluv = NULL;
555
556                 if (BM_TestHFlag(efa, BM_HIDDEN))
557                         continue;
558
559                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
560                         MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
561
562                         if (luv) {
563                                 if (lastluv)
564                                         glVertex2fv(luv->uv);
565                                 glVertex2fv(luv->uv);
566
567                                 lastluv = luv;
568                                 if (!firstluv)
569                                         firstluv = luv;
570                         }
571                 }
572
573                 if (lastluv) {
574                         glVertex2fv(lastluv->uv);
575                         glVertex2fv(firstluv->uv);
576                 }
577         }
578         glEnd();
579 }
580
581 static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3])
582 {
583         BMIter iter;
584         BMLoop *l;
585         int tot = 0;
586
587         zero_v3(cent);
588
589         /*simple (and stupid) median (average) based method :/ */
590
591         if (vertexCos) {
592                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
593                 for (; l; l=BMIter_Step(&iter)) {
594                         add_v3_v3(cent, vertexCos[BM_GetIndex(l->v)]);
595                         tot++;
596                 }
597         }
598         else {
599                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
600                 for (; l; l=BMIter_Step(&iter)) {
601                         add_v3_v3(cent, l->v->co);
602                         tot++;
603                 }
604         }
605
606         if (tot==0) return;
607         mul_v3_fl(cent, 1.0f/(float)tot);
608 }
609
610 static void emDM_foreachMappedFaceCenter(
611                 DerivedMesh *dm,
612                 void (*func)(void *userData, int index, float *co, float *no),
613                 void *userData)
614 {
615         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
616         BMFace *efa;
617         BMIter iter;
618         float cent[3];
619         int i;
620
621         if (bmdm->vertexCos) {
622                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
623         }
624
625         efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
626         for (i=0; efa; efa=BMIter_Step(&iter), i++) {
627                 emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
628                 func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no);
629         }
630 }
631
632 static void emDM_drawMappedFaces(
633                 DerivedMesh *dm,
634                 int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
635                 int (*setMaterial)(int, void *attribs),
636                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
637                 void *userData, int UNUSED(useColors))
638 {
639         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
640         BMFace *efa;
641         struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
642         const int tottri= bmdm->tc->tottri;
643         const int lasttri= tottri - 1; /* compare agasint this a lot */
644         int i, draw, flush;
645         const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
646
647         /* GL_ZERO is used to detect if drawing has started or not */
648         GLenum poly_prev= GL_ZERO;
649         GLenum shade_prev= GL_ZERO;
650
651         (void)setMaterial; /* UNUSED */
652
653         /* currently unused -- each original face is handled separately */
654         (void)compareDrawOptions;
655
656         if (bmdm->vertexCos) {
657                 /* add direct access */
658                 float (*vertexCos)[3]= bmdm->vertexCos;
659                 float (*vertexNos)[3]= bmdm->vertexNos;
660                 float (*faceNos)[3]=   bmdm->faceNos;
661
662                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
663
664                 for (i=0; i < tottri; i++) {
665                         BMLoop **l = looptris[i];
666                         int drawSmooth;
667
668                         efa = l[0]->f;
669                         drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
670
671                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
672                         if (draw) {
673                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
674                                 if (draw==2) { /* enabled with stipple */
675
676                                         if (poly_prev != GL_ZERO) glEnd();
677                                         poly_prev= GL_ZERO; /* force glBegin */
678
679                                         glEnable(GL_POLYGON_STIPPLE);
680                                         glPolygonStipple(stipple_quarttone);
681                                 }
682
683                                 if (skip_normals) {
684                                         if (poly_type != poly_prev) {
685                                                 if (poly_prev != GL_ZERO) glEnd();
686                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
687                                         }
688                                         glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
689                                         glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
690                                         glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
691                                 }
692                                 else {
693                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
694                                         if (shade_type != shade_prev) {
695                                                 if (poly_prev != GL_ZERO) glEnd();
696                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
697                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
698                                         }
699                                         if (poly_type != poly_prev) {
700                                                 if (poly_prev != GL_ZERO) glEnd();
701                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
702                                         }
703
704                                         if (!drawSmooth) {
705                                                 glNormal3fv(faceNos[i]);
706                                                 glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
707                                                 glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
708                                                 glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
709                                         }
710                                         else {
711                                                 glNormal3fv(vertexNos[BM_GetIndex(l[0]->v)]);
712                                                 glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
713                                                 glNormal3fv(vertexNos[BM_GetIndex(l[1]->v)]);
714                                                 glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
715                                                 glNormal3fv(vertexNos[BM_GetIndex(l[2]->v)]);
716                                                 glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
717                                         }
718                                 }
719
720                                 flush= (draw==2);
721                                 if (!skip_normals && !flush && (i != lasttri))
722                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
723
724                                 if (flush) {
725                                         glEnd();
726                                         poly_prev= GL_ZERO; /* force glBegin */
727
728                                         glDisable(GL_POLYGON_STIPPLE);
729                                 }
730                         }
731                 }
732         }
733         else {
734                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_FACE);
735
736                 for (i=0; i < tottri; i++) {
737                         BMLoop **l = looptris[i];
738                         int drawSmooth;
739
740                         efa = l[0]->f;
741                         drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
742
743                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
744                         if (draw) {
745                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
746                                 if (draw==2) { /* enabled with stipple */
747
748                                         if (poly_prev != GL_ZERO) glEnd();
749                                         poly_prev= GL_ZERO; /* force glBegin */
750
751                                         glEnable(GL_POLYGON_STIPPLE);
752                                         glPolygonStipple(stipple_quarttone);
753                                 }
754
755                                 if (skip_normals) {
756                                         if (poly_type != poly_prev) {
757                                                 if (poly_prev != GL_ZERO) glEnd();
758                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
759                                         }
760                                         glVertex3fv(l[0]->v->co);
761                                         glVertex3fv(l[1]->v->co);
762                                         glVertex3fv(l[2]->v->co);
763                                 }
764                                 else {
765                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
766                                         if (shade_type != shade_prev) {
767                                                 if (poly_prev != GL_ZERO) glEnd();
768                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
769                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
770                                         }
771                                         if (poly_type != poly_prev) {
772                                                 if (poly_prev != GL_ZERO) glEnd();
773                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
774                                         }
775
776                                         if (!drawSmooth) {
777                                                 glNormal3fv(efa->no);
778                                                 glVertex3fv(l[0]->v->co);
779                                                 glVertex3fv(l[1]->v->co);
780                                                 glVertex3fv(l[2]->v->co);
781                                         }
782                                         else {
783                                                 glNormal3fv(l[0]->v->no);
784                                                 glVertex3fv(l[0]->v->co);
785                                                 glNormal3fv(l[1]->v->no);
786                                                 glVertex3fv(l[1]->v->co);
787                                                 glNormal3fv(l[2]->v->no);
788                                                 glVertex3fv(l[2]->v->co);
789                                         }
790                                 }
791
792                                 flush= (draw==2);
793                                 if (!skip_normals && !flush && (i != lasttri)) {
794                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
795                                 }
796
797                                 if (flush) {
798                                         glEnd();
799                                         poly_prev= GL_ZERO; /* force glBegin */
800
801                                         glDisable(GL_POLYGON_STIPPLE);
802                                 }
803                         }
804                 }
805         }
806
807         /* if non zero we know a face was rendered */
808         if (poly_prev != GL_ZERO) glEnd();
809 }
810
811 static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
812                                  int has_uv, int has_col)
813 {
814         if (has_uv) {
815                 luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
816                 luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
817                 luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
818         }
819
820         if (has_col) {
821                 lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
822                 lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
823                 lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
824         }
825
826
827 }
828
829 static void emDM_drawFacesTex_common(
830                 DerivedMesh *dm,
831                 int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
832                 int (*drawParamsMapped)(void *userData, int index),
833                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
834                 void *userData)
835 {
836         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
837         BMEditMesh *em = bmdm->tc;
838         BMesh *bm= bmdm->tc->bm;
839         float (*vertexCos)[3]= bmdm->vertexCos;
840         float (*vertexNos)[3]= bmdm->vertexNos;
841         BMFace *efa;
842         MLoopUV *luv[3], dummyluv = {{0}};
843         MLoopCol *lcol[3], dummylcol = {0};
844         int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
845         int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
846
847         (void) compareDrawOptions;
848
849         luv[0] = luv[1] = luv[2] = &dummyluv;
850         lcol[0] = lcol[1] = lcol[2] = &dummylcol;
851
852         dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
853
854         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
855         glShadeModel(GL_SMOOTH);
856
857         BM_ElemIndex_Ensure(bm, BM_FACE);
858
859         if (vertexCos) {
860                 BM_ElemIndex_Ensure(bm, BM_VERT);
861
862                 glBegin(GL_TRIANGLES);
863                 for (i=0; i<em->tottri; i++) {
864                         BMLoop **ls = em->looptris[i];
865                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
866                         MTFace mtf = {{{0}}};
867                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
868                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
869                         int flag;
870
871                         efa = ls[0]->f;
872
873                         if (has_uv) {
874                                 mtf.flag = tp->flag;
875                                 mtf.tpage = tp->tpage;
876                                 mtf.transp = tp->transp;
877                                 mtf.mode = tp->mode;
878                                 mtf.tile = tp->tile;
879                                 mtf.unwrap = tp->unwrap;
880                         }
881
882                         if (drawParams)
883                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
884                         else if (drawParamsMapped)
885                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
886                         else
887                                 flag= 1;
888
889                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
890
891                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
892                                 if (!has_vcol) {
893                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
894                                 }
895
896                                 if (!drawSmooth) {
897                                         glNormal3fv(bmdm->faceNos[i]);
898
899                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
900
901                                         glTexCoord2fv(luv[0]->uv);
902                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
903                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
904
905                                         glTexCoord2fv(luv[1]->uv);
906                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
907                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
908
909                                         glTexCoord2fv(luv[2]->uv);
910                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
911                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
912                                 }
913                                 else {
914                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
915
916                                         glTexCoord2fv(luv[0]->uv);
917                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
918                                         glNormal3fv(vertexNos[BM_GetIndex(ls[0]->v)]);
919                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
920
921                                         glTexCoord2fv(luv[1]->uv);
922                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
923                                         glNormal3fv(vertexNos[BM_GetIndex(ls[1]->v)]);
924                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
925
926                                         glTexCoord2fv(luv[2]->uv);
927                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
928                                         glNormal3fv(vertexNos[BM_GetIndex(ls[2]->v)]);
929                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
930                                 }
931                         }
932                 }
933                 glEnd();
934         }
935         else {
936                 BM_ElemIndex_Ensure(bm, BM_VERT);
937
938                 for (i=0; i<em->tottri; i++) {
939                         BMLoop **ls = em->looptris[i];
940                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
941                         MTFace mtf = {{{0}}};
942                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
943                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
944                         int flag;
945
946                         efa = ls[0]->f;
947
948                         if (has_uv) {
949                                 mtf.flag = tp->flag;
950                                 mtf.tpage = tp->tpage;
951                                 mtf.transp = tp->transp;
952                                 mtf.mode = tp->mode;
953                                 mtf.tile = tp->tile;
954                                 mtf.unwrap = tp->unwrap;
955                         }
956
957                         if (drawParams)
958                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
959                         else if (drawParamsMapped)
960                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
961                         else
962                                 flag= 1;
963
964                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
965
966                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
967                                 if (!has_vcol) {
968                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
969                                 }
970
971                                 glBegin(GL_TRIANGLES);
972                                 if (!drawSmooth) {
973                                         glNormal3fv(efa->no);
974
975                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
976
977                                         if (luv[0])
978                                                 glTexCoord2fv(luv[0]->uv);
979                                         if (lcol[0])
980                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
981                                         else glColor3ub(0, 0, 0);
982                                         glVertex3fv(ls[0]->v->co);
983
984                                         if (luv[1])
985                                                 glTexCoord2fv(luv[1]->uv);
986                                         if (lcol[1])
987                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
988                                         else glColor3ub(0, 0, 0);
989                                         glVertex3fv(ls[1]->v->co);
990
991                                         if (luv[2])
992                                                 glTexCoord2fv(luv[2]->uv);
993                                         if (lcol[2])
994                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
995                                         else glColor3ub(0, 0, 0);
996                                         glVertex3fv(ls[2]->v->co);
997                                 }
998                                 else {
999                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
1000
1001                                         if (luv[0])
1002                                                 glTexCoord2fv(luv[0]->uv);
1003                                         if (lcol[0])
1004                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
1005                                         else glColor3ub(0, 0, 0);
1006                                         glNormal3fv(ls[0]->v->no);
1007                                         glVertex3fv(ls[0]->v->co);
1008
1009                                         if (luv[1])
1010                                                 glTexCoord2fv(luv[1]->uv);
1011                                         if (lcol[1])
1012                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
1013                                         else glColor3ub(0, 0, 0);
1014                                         glNormal3fv(ls[1]->v->no);
1015                                         glVertex3fv(ls[1]->v->co);
1016
1017                                         if (luv[2])
1018                                                 glTexCoord2fv(luv[2]->uv);
1019                                         if (lcol[2])
1020                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
1021                                         else glColor3ub(0, 0, 0);
1022                                         glNormal3fv(ls[2]->v->no);
1023                                         glVertex3fv(ls[2]->v->co);
1024                                 }
1025                                 glEnd();
1026                         }
1027                 }
1028         }
1029 }
1030
1031 static void emDM_drawFacesTex(
1032                 DerivedMesh *dm,
1033                 int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr),
1034                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1035                 void *userData)
1036 {
1037         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
1038 }
1039
1040 static void emDM_drawMappedFacesTex(
1041                 DerivedMesh *dm,
1042                 int (*setDrawOptions)(void *userData, int index),
1043                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1044                 void *userData)
1045 {
1046         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
1047 }
1048
1049 static void emDM_drawMappedFacesGLSL(
1050                 DerivedMesh *dm,
1051                 int (*setMaterial)(int, void *attribs),
1052                 int (*setDrawOptions)(void *userData, int index),
1053                 void *userData)
1054 {
1055         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1056         BMesh *bm= bmdm->tc->bm;
1057         BMEditMesh *em = bmdm->tc;
1058         float (*vertexCos)[3]= bmdm->vertexCos;
1059         float (*vertexNos)[3]= bmdm->vertexNos;
1060         BMFace *efa;
1061         BMLoop **ltri;
1062         DMVertexAttribs attribs;
1063         GPUVertexAttribs gattribs;
1064
1065         int i, b, matnr, new_matnr, dodraw;
1066
1067         dodraw = 0;
1068         matnr = -1;
1069
1070         memset(&attribs, 0, sizeof(attribs));
1071
1072         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1073         glShadeModel(GL_SMOOTH);
1074         BM_ElemIndex_Ensure(bm, BM_VERT | BM_FACE);
1075
1076 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1077         if (attribs.totorco) {                                                                                                          \
1078                 float *orco = attribs.orco.array[BM_GetIndex(eve)];                                             \
1079                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
1080         }                                                                                                                                                       \
1081         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1082                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1083                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
1084         }                                                                                                                                                       \
1085         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
1086                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1087                 GLubyte _col[4];                                                                                                                \
1088                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
1089                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
1090         }                                                                                                                                                       \
1091         if (attribs.tottang) {                                                                                                          \
1092                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
1093                 glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
1094         }                                                                                                                                                       \
1095         }
1096
1097
1098         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1099                 int drawSmooth;
1100
1101                 efa = ltri[0]->f;
1102                 drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
1103
1104                 if (setDrawOptions && !setDrawOptions(userData, BM_GetIndex(efa)))
1105                         continue;
1106
1107                 new_matnr = efa->mat_nr + 1;
1108                 if (new_matnr != matnr) {
1109                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1110                         if (dodraw)
1111                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1112                 }
1113
1114                 if (dodraw) {
1115                         glBegin(GL_TRIANGLES);
1116                         if (!drawSmooth) {
1117                                 if (vertexCos) glNormal3fv(bmdm->faceNos[i]);
1118                                 else glNormal3fv(efa->no);
1119
1120                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1121                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1122                                 else glVertex3fv(ltri[0]->v->co);
1123
1124                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1125                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1126                                 else glVertex3fv(ltri[1]->v->co);
1127
1128                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1129                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1130                                 else glVertex3fv(ltri[2]->v->co);
1131                         }
1132                         else {
1133                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1134                                 if (vertexCos) {
1135                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1136                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1137                                 }
1138                                 else {
1139                                         glNormal3fv(ltri[0]->v->no);
1140                                         glVertex3fv(ltri[0]->v->co);
1141                                 }
1142
1143                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1144                                 if (vertexCos) {
1145                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1146                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1147                                 }
1148                                 else {
1149                                         glNormal3fv(ltri[1]->v->no);
1150                                         glVertex3fv(ltri[1]->v->co);
1151                                 }
1152
1153                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1154                                 if (vertexCos) {
1155                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1156                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1157                                 }
1158                                 else {
1159                                         glNormal3fv(ltri[2]->v->no);
1160                                         glVertex3fv(ltri[2]->v->co);
1161                                 }
1162                         }
1163                         glEnd();
1164                 }
1165         }
1166 #undef PASSATTRIB
1167 }
1168
1169 static void emDM_drawFacesGLSL(
1170                 DerivedMesh *dm,
1171                 int (*setMaterial)(int, void *attribs))
1172 {
1173         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1174 }
1175
1176 static void emDM_drawMappedFacesMat(
1177                 DerivedMesh *dm,
1178                 void (*setMaterial)(void *userData, int, void *attribs),
1179                 int (*setFace)(void *userData, int index), void *userData)
1180 {
1181         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1182         BMesh *bm= bmdm->tc->bm;
1183         BMEditMesh *em = bmdm->tc;
1184         float (*vertexCos)[3]= bmdm->vertexCos;
1185         float (*vertexNos)[3]= bmdm->vertexNos;
1186         BMFace *efa;
1187         BMLoop **ltri;
1188         DMVertexAttribs attribs= {{{0}}};
1189         GPUVertexAttribs gattribs;
1190         int i, b, matnr, new_matnr;
1191
1192         matnr = -1;
1193
1194         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1195         glShadeModel(GL_SMOOTH);
1196
1197         BM_ElemIndex_Ensure(bm, BM_VERT);
1198
1199 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1200         if (attribs.totorco) {                                                                                                          \
1201                 float *orco = attribs.orco.array[BM_GetIndex(eve)];                                             \
1202                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
1203         }                                                                                                                                                       \
1204         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1205                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1206                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
1207         }                                                                                                                                                       \
1208         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
1209                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1210                 GLubyte _col[4];                                                                                                                \
1211                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
1212                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
1213         }                                                                                                                                                       \
1214         if (attribs.tottang) {                                                                                                          \
1215                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
1216                 glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
1217         }                                                                                                                                                       \
1218 }
1219
1220         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1221                 int drawSmooth;
1222
1223                 efa = ltri[0]->f;
1224                 drawSmooth = BM_TestHFlag(efa, BM_SMOOTH);
1225
1226                 /* face hiding */
1227                 if (setFace && !setFace(userData, BM_GetIndex(efa)))
1228                         continue;
1229
1230                 /* material */
1231                 new_matnr = efa->mat_nr + 1;
1232                 if (new_matnr != matnr) {
1233                         setMaterial(userData, matnr = new_matnr, &gattribs);
1234                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1235                 }
1236
1237                 /* face */
1238                 glBegin(GL_TRIANGLES);
1239                 if (!drawSmooth) {
1240                         if (vertexCos) glNormal3fv(bmdm->faceNos[i]);
1241                         else glNormal3fv(efa->no);
1242
1243                         PASSATTRIB(ltri[0], ltri[0]->v, 0);
1244                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1245                         else glVertex3fv(ltri[0]->v->co);
1246
1247                         PASSATTRIB(ltri[1], ltri[1]->v, 1);
1248                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1249                         else glVertex3fv(ltri[1]->v->co);
1250
1251                         PASSATTRIB(ltri[2], ltri[2]->v, 2);
1252                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1253                         else glVertex3fv(ltri[2]->v->co);
1254
1255                 }
1256                 else {
1257                         PASSATTRIB(ltri[0], ltri[0]->v, 0);
1258                         if (vertexCos) {
1259                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1260                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1261                         }
1262                         else {
1263                                 glNormal3fv(ltri[0]->v->no);
1264                                 glVertex3fv(ltri[0]->v->co);
1265                         }
1266
1267                         PASSATTRIB(ltri[1], ltri[1]->v, 1);
1268                         if (vertexCos) {
1269                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1270                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1271                         }
1272                         else {
1273                                 glNormal3fv(ltri[1]->v->no);
1274                                 glVertex3fv(ltri[1]->v->co);
1275                         }
1276
1277                         PASSATTRIB(ltri[2], ltri[2]->v, 2);
1278                         if (vertexCos) {
1279                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1280                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1281                         }
1282                         else {
1283                                 glNormal3fv(ltri[2]->v->no);
1284                                 glVertex3fv(ltri[2]->v->co);
1285                         }
1286                 }
1287                 glEnd();
1288         }
1289 #undef PASSATTRIB
1290 }
1291
1292 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1293 {
1294         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1295         BMVert *eve;
1296         BMIter iter;
1297         int i;
1298
1299         if (bmdm->tc->bm->totvert) {
1300                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1301                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1302                         if (bmdm->vertexCos) {
1303                                 DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
1304                         }
1305                         else {
1306                                 DO_MINMAX(eve->co, min_r, max_r);
1307                         }
1308                 }
1309         }
1310         else {
1311                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1312         }
1313 }
1314 static int emDM_getNumVerts(DerivedMesh *dm)
1315 {
1316         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1317
1318         return bmdm->tc->bm->totvert;
1319 }
1320
1321 static int emDM_getNumEdges(DerivedMesh *dm)
1322 {
1323         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1324
1325         return bmdm->tc->bm->totedge;
1326 }
1327
1328 static int emDM_getNumTessFaces(DerivedMesh *dm)
1329 {
1330         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1331
1332         return bmdm->tc->tottri;
1333 }
1334
1335 static int emDM_getNumLoops(DerivedMesh *dm)
1336 {
1337         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1338
1339         return bmdm->tc->bm->totloop;
1340 }
1341
1342 static int emDM_getNumPolys(DerivedMesh *dm)
1343 {
1344         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1345
1346         return bmdm->tc->bm->totface;
1347 }
1348
1349 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1350 {
1351         copy_v3_v3(vert_r->co, ev->co);
1352
1353         normal_float_to_short_v3(vert_r->no, ev->no);
1354
1355         vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1356
1357         if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1358                 vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1359         }
1360
1361         return 1;
1362 }
1363
1364 static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1365 {
1366         BMVert *ev;
1367
1368         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
1369                 printf("error in emDM_getVert.\n");
1370                 return;
1371         }
1372
1373         ev = ((EditDerivedBMesh *)dm)->vtable[index];
1374         bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r);
1375 }
1376
1377 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1378 {
1379         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1380         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1381         BMEdge *e;
1382
1383         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
1384                 printf("error in emDM_getEdge.\n");
1385                 return;
1386         }
1387
1388         e = bmdm->etable[index];
1389
1390         if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1391                 edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f);
1392         }
1393
1394         if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1395                 edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f);
1396         }
1397
1398         edge_r->flag = BM_Edge_Flag_To_MEFlag(e);
1399
1400         edge_r->v1 = BM_GetIndex(e->v1);
1401         edge_r->v2 = BM_GetIndex(e->v2);
1402 }
1403
1404 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1405 {
1406         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */
1407         BMFace *ef;
1408         BMLoop **l;
1409
1410         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
1411                 printf("error in emDM_getTessFace.\n");
1412                 return;
1413         }
1414
1415         l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
1416
1417         ef = l[0]->f;
1418
1419         face_r->mat_nr = (unsigned char) ef->mat_nr;
1420         face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1421
1422         face_r->v1 = BM_GetIndex(l[0]->v);
1423         face_r->v2 = BM_GetIndex(l[1]->v);
1424         face_r->v3 = BM_GetIndex(l[2]->v);
1425         face_r->v4 = 0;
1426
1427         test_index_face(face_r, NULL, 0, 3);
1428 }
1429
1430 static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1431 {
1432         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1433         BMVert *ev;
1434         BMIter iter;
1435
1436         ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1437         for ( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
1438                 copy_v3_v3(vert_r->co, ev->co);
1439
1440                 normal_float_to_short_v3(vert_r->no, ev->no);
1441
1442                 vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1443
1444                 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1445                         vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1446                 }
1447         }
1448 }
1449
1450 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1451 {
1452         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1453         BMEdge *ee;
1454         BMIter iter;
1455         int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1456         int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1457
1458         BM_ElemIndex_Ensure(bm, BM_VERT);
1459
1460         ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1461         for ( ; ee; ee=BMIter_Step(&iter), edge_r++) {
1462                 if (has_bweight) {
1463                         edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f);
1464                 }
1465
1466                 if (has_crease) {
1467                         edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f);
1468                 }
1469
1470                 edge_r->flag = BM_Edge_Flag_To_MEFlag(ee);
1471
1472                 edge_r->v1 = BM_GetIndex(ee->v1);
1473                 edge_r->v2 = BM_GetIndex(ee->v2);
1474         }
1475 }
1476
1477 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
1478 {
1479         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1480         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1481         BMFace *ef;
1482         BMLoop **l;
1483         int i;
1484
1485         BM_ElemIndex_Ensure(bm, BM_VERT);
1486
1487         for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
1488                 l = bmdm->tc->looptris[i];
1489                 ef = l[0]->f;
1490
1491                 face_r->mat_nr = (unsigned char) ef->mat_nr;
1492
1493                 face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1494
1495                 face_r->v1 = BM_GetIndex(l[0]->v);
1496                 face_r->v2 = BM_GetIndex(l[1]->v);
1497                 face_r->v3 = BM_GetIndex(l[2]->v);
1498                 face_r->v4 = 0;
1499
1500                 test_index_face(face_r, NULL, 0, 3);
1501         }
1502 }
1503
1504
1505 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1506 {
1507         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1508         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1509         BMIter iter, liter;
1510         BMFace *f;
1511         BMLoop *l;
1512
1513         BM_ElemIndex_Ensure(bm, BM_VERT | BM_EDGE);
1514
1515         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1516                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
1517                         loop_r->v = BM_GetIndex(l->v);
1518                         loop_r->e = BM_GetIndex(l->e);
1519                         loop_r++;
1520                 }
1521         }
1522 }
1523
1524 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1525 {
1526         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1527         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1528         BMIter iter;
1529         BMFace *f;
1530         int i;
1531
1532         i = 0;
1533         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1534                 poly_r->flag = BM_Face_Flag_To_MEFlag(f);
1535                 poly_r->loopstart = i;
1536                 poly_r->totloop = f->len;
1537                 poly_r->mat_nr = f->mat_nr;
1538
1539                 poly_r++;
1540                 i += f->len;
1541         }
1542 }
1543
1544 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1545 {
1546         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1547         BMesh *bm= bmdm->tc->bm;
1548         BMFace *efa;
1549         char *data, *bmdata;
1550         void *datalayer;
1551         int index /*, offset*/ /*UNUSED */, size, i;
1552
1553         datalayer = DM_get_tessface_data_layer(dm, type);
1554         if (datalayer)
1555                 return datalayer;
1556
1557         /* layers are store per face for editmesh, we convert to a tbmporary
1558          * data layer array in the derivedmesh when these are requested */
1559         if (type == CD_MTFACE || type == CD_MCOL) {
1560                 index = CustomData_get_layer_index(&bm->pdata, type);
1561
1562                 if (index != -1) {
1563                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1564                         size = CustomData_sizeof(type);
1565
1566                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1567                         index = CustomData_get_layer_index(&dm->faceData, type);
1568                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1569
1570                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1571                         for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
1572                                 efa = bmdm->tc->looptris[i][0]->f;
1573                                 /*BMESH_TODO: need to still add tface data,
1574                                   derived from the loops.*/
1575                                 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
1576                                 memcpy(data, bmdata, size);
1577                         }
1578                 }
1579         }
1580
1581         return datalayer;
1582 }
1583
1584 static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1585 {
1586         EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1587         BMVert *eve;
1588         BMIter iter;
1589         int i;
1590
1591         i= 0;
1592         BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
1593                 if (emdm->vertexCos) {
1594                         copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1595                 }
1596                 else {
1597                         copy_v3_v3(cos_r[i], eve->co);
1598                 }
1599
1600                 i++;
1601         }
1602 }
1603
1604 static void emDM_release(DerivedMesh *dm)
1605 {
1606         EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1607
1608         if (DM_release(dm)) {
1609                 if (bmdm->vertexCos) {
1610                         MEM_freeN(bmdm->vertexCos);
1611                         MEM_freeN(bmdm->vertexNos);
1612                         MEM_freeN(bmdm->faceNos);
1613                 }
1614
1615                 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
1616                 if (bmdm->etable) MEM_freeN(bmdm->etable);
1617                 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
1618
1619                 MEM_freeN(bmdm);
1620         }
1621 }
1622
1623 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1624 {
1625         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1626
1627         return &bmdm->tc->bm->vdata;
1628 }
1629
1630 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1631 {
1632         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1633
1634         return &bmdm->tc->bm->edata;
1635 }
1636
1637 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1638 {
1639         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1640
1641         return &bmdm->dm.faceData;
1642 }
1643
1644 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1645 {
1646         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1647
1648         return &bmdm->tc->bm->ldata;
1649 }
1650
1651 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1652 {
1653         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1654
1655         return &bmdm->tc->bm->pdata;
1656 }
1657
1658
1659 DerivedMesh *getEditDerivedBMesh(
1660                 BMEditMesh *em,
1661                 Object *UNUSED(ob),
1662                 float (*vertexCos)[3])
1663 {
1664         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1665         BMesh *bm = em->bm;
1666
1667         bmdm->tc = em;
1668
1669         DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
1670                  em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1671
1672         CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
1673
1674         bmdm->dm.getVertCos = emDM_getVertCos;
1675         bmdm->dm.getMinMax = emDM_getMinMax;
1676
1677         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1678         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1679         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1680         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1681         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1682
1683         bmdm->dm.getNumVerts = emDM_getNumVerts;
1684         bmdm->dm.getNumEdges = emDM_getNumEdges;
1685         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1686         bmdm->dm.getNumLoops = emDM_getNumLoops;
1687         bmdm->dm.getNumPolys = emDM_getNumPolys;
1688
1689         bmdm->dm.getVert = emDM_getVert;
1690         bmdm->dm.getEdge = emDM_getEdge;
1691         bmdm->dm.getTessFace = emDM_getTessFace;
1692         bmdm->dm.copyVertArray = emDM_copyVertArray;
1693         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1694         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1695         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1696         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1697
1698         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1699
1700         bmdm->dm.calcNormals = emDM_calcNormals;
1701         bmdm->dm.recalcTesselation = emDM_recalcTesselation;
1702
1703         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1704         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1705         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1706
1707         bmdm->dm.drawEdges = emDM_drawEdges;
1708         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1709         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1710         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1711         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1712         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1713         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1714         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1715         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1716         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1717
1718         bmdm->dm.release = emDM_release;
1719
1720         bmdm->vertexCos = vertexCos;
1721
1722         if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1723                 BMIter iter;
1724                 BMVert *eve;
1725                 int i;
1726
1727                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1728
1729                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1730                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1731                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1732                                                          CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1733         }
1734
1735         if (vertexCos) {
1736                 BMVert *eve;
1737                 BMIter iter;
1738                 int totface = bmdm->tc->tottri;
1739                 int i;
1740
1741                 BM_ElemIndex_Ensure(bm, BM_VERT);
1742
1743                 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
1744                 bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
1745
1746                 for (i=0; i<bmdm->tc->tottri; i++) {
1747                         BMLoop **l = bmdm->tc->looptris[i];
1748                         float *v1 = vertexCos[BM_GetIndex(l[0]->v)];
1749                         float *v2 = vertexCos[BM_GetIndex(l[1]->v)];
1750                         float *v3 = vertexCos[BM_GetIndex(l[2]->v)];
1751                         float *no = bmdm->faceNos[i];
1752
1753                         normal_tri_v3( no,v1, v2, v3);
1754                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[0]->v)], bmdm->vertexNos[BM_GetIndex(l[0]->v)], no);
1755                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[1]->v)], bmdm->vertexNos[BM_GetIndex(l[1]->v)], no);
1756                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[2]->v)], bmdm->vertexNos[BM_GetIndex(l[2]->v)], no);
1757                 }
1758
1759                 eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1760                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1761                         float *no = bmdm->vertexNos[i];
1762                         /* following Mesh convention; we use vertex coordinate itself
1763                          * for normal in this case */
1764                         if (normalize_v3(no)==0.0) {
1765                                 copy_v3_v3(no, vertexCos[i]);
1766                                 normalize_v3(no);
1767                         }
1768                 }
1769         }
1770
1771         //bmdm_recalc_lookups(bmdm);
1772
1773         return (DerivedMesh*) bmdm;
1774 }