svn merge ^/trunk/blender -r43830:43864
[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 (*polyNos)[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 /* BMESH_TODO, since this is not called get functions fail! */
350 static void UNUSED_FUNCTION(bmdm_recalc_lookups)(EditDerivedBMesh *bmdm)
351 {
352         BMIter iter;
353         int a, i;
354
355         int iters[3] = {BM_VERTS_OF_MESH,
356                         BM_EDGES_OF_MESH,
357                         BM_FACES_OF_MESH};
358
359         BMHeader **iters_table[3] = {
360                 (BMHeader **)bmdm->vtable,
361                 (BMHeader **)bmdm->etable,
362                 (BMHeader **)bmdm->ftable};
363
364         bmdm->tv = bmdm->tc->bm->totvert;
365         bmdm->te = bmdm->tc->bm->totedge;
366         bmdm->tf = bmdm->tc->bm->totface;
367
368         if (bmdm->vtable) MEM_freeN(bmdm->vtable);
369         if (bmdm->etable) MEM_freeN(bmdm->etable);
370         if (bmdm->ftable) MEM_freeN(bmdm->ftable);
371
372         if (bmdm->tc->bm->totvert)
373                 bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
374         else bmdm->vtable = NULL;
375
376         if (bmdm->tc->bm->totedge)
377                 bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
378         else bmdm->etable = NULL;
379
380         if (bmdm->tc->bm->totface)
381                 bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
382         else bmdm->ftable = NULL;
383
384         for (a=0; a<3; a++) {
385                 BMHeader **table = iters_table[a];
386                 BMHeader *ele;
387
388                 ele = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
389                 for (i=0; ele; ele=BMIter_Step(&iter), i++) {
390                         table[i] = ele;
391                         BM_SetIndex(ele, i);  /* set_ok */
392                 }
393         }
394         bmdm->tc->bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
395
396 }
397
398 static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
399 {
400         /* Nothing to do: normals are already calculated and stored on the
401            BMVerts and BMFaces */
402 }
403
404 static void emDM_recalcTesselation(DerivedMesh *UNUSED(dm))
405 {
406         //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
407
408         //bmdm_recalc_lookups(bmdm);
409 }
410
411 static void emDM_foreachMappedVert(
412                 DerivedMesh *dm,
413                 void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
414                 void *userData)
415 {
416         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
417         BMVert *eve;
418         BMIter iter;
419         int i;
420
421         eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
422         for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
423                 if (bmdm->vertexCos) {
424                         func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
425                 }
426                 else {
427                         func(userData, i, eve->co, eve->no, NULL);
428                 }
429         }
430 }
431 static void emDM_foreachMappedEdge(
432                 DerivedMesh *dm,
433                 void (*func)(void *userData, int index, float *v0co, float *v1co),
434                 void *userData)
435 {
436         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
437         BMEdge *eed;
438         BMIter iter;
439         int i;
440
441         if (bmdm->vertexCos) {
442
443                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
444
445                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
446                 for (i=0; eed; i++,eed=BMIter_Step(&iter))
447                         func(userData, i,
448                                  bmdm->vertexCos[BM_GetIndex(eed->v1)],
449                                  bmdm->vertexCos[BM_GetIndex(eed->v2)]);
450         }
451         else {
452                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
453                 for (i=0; eed; i++,eed=BMIter_Step(&iter))
454                         func(userData, i, eed->v1->co, eed->v2->co);
455         }
456 }
457
458 static void emDM_drawMappedEdges(
459                 DerivedMesh *dm,
460                 int (*setDrawOptions)(void *userData, int index),
461                 void *userData)
462 {
463         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
464         BMEdge *eed;
465         BMIter iter;
466         int i;
467
468         if (bmdm->vertexCos) {
469
470                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
471
472                 glBegin(GL_LINES);
473                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
474                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
475                         if (!setDrawOptions || setDrawOptions(userData, i)) {
476                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
477                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
478                         }
479                 }
480                 glEnd();
481         }
482         else {
483                 glBegin(GL_LINES);
484                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
485                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
486                         if (!setDrawOptions || setDrawOptions(userData, i)) {
487                                 glVertex3fv(eed->v1->co);
488                                 glVertex3fv(eed->v2->co);
489                         }
490                 }
491                 glEnd();
492         }
493 }
494 static void emDM_drawEdges(
495                 DerivedMesh *dm,
496                 int UNUSED(drawLooseEdges),
497                 int UNUSED(drawAllEdges))
498 {
499         emDM_drawMappedEdges(dm, NULL, NULL);
500 }
501
502 static void emDM_drawMappedEdgesInterp(
503                 DerivedMesh *dm,
504                 int (*setDrawOptions)(void *userData, int index),
505                 void (*setDrawInterpOptions)(void *userData, int index, float t),
506                 void *userData)
507 {
508         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
509         BMEdge *eed;
510         BMIter iter;
511         int i;
512
513         if (bmdm->vertexCos) {
514
515                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
516
517                 glBegin(GL_LINES);
518                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
519                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
520                         if (!setDrawOptions || setDrawOptions(userData, i)) {
521                                 setDrawInterpOptions(userData, i, 0.0);
522                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
523                                 setDrawInterpOptions(userData, i, 1.0);
524                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
525                         }
526                 }
527                 glEnd();
528         }
529         else {
530                 glBegin(GL_LINES);
531                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
532                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
533                         if (!setDrawOptions || setDrawOptions(userData, i)) {
534                                 setDrawInterpOptions(userData, i, 0.0);
535                                 glVertex3fv(eed->v1->co);
536                                 setDrawInterpOptions(userData, i, 1.0);
537                                 glVertex3fv(eed->v2->co);
538                         }
539                 }
540                 glEnd();
541         }
542 }
543
544 static void emDM_drawUVEdges(DerivedMesh *dm)
545 {
546         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
547         BMEditMesh *em = bmdm->tc;
548         BMFace *efa;
549         BMIter iter;
550
551         glBegin(GL_LINES);
552         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
553                 BMIter liter;
554                 BMLoop *l;
555                 MLoopUV *lastluv = NULL, *firstluv = NULL;
556
557                 if (BM_TestHFlag(efa, BM_HIDDEN))
558                         continue;
559
560                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
561                         MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
562
563                         if (luv) {
564                                 if (lastluv)
565                                         glVertex2fv(luv->uv);
566                                 glVertex2fv(luv->uv);
567
568                                 lastluv = luv;
569                                 if (!firstluv)
570                                         firstluv = luv;
571                         }
572                 }
573
574                 if (lastluv) {
575                         glVertex2fv(lastluv->uv);
576                         glVertex2fv(firstluv->uv);
577                 }
578         }
579         glEnd();
580 }
581
582 static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3])
583 {
584         BMIter iter;
585         BMLoop *l;
586         int tot = 0;
587
588         zero_v3(cent);
589
590         /*simple (and stupid) median (average) based method :/ */
591
592         if (vertexCos) {
593                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
594                 for (; l; l=BMIter_Step(&iter)) {
595                         add_v3_v3(cent, vertexCos[BM_GetIndex(l->v)]);
596                         tot++;
597                 }
598         }
599         else {
600                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
601                 for (; l; l=BMIter_Step(&iter)) {
602                         add_v3_v3(cent, l->v->co);
603                         tot++;
604                 }
605         }
606
607         if (tot==0) return;
608         mul_v3_fl(cent, 1.0f/(float)tot);
609 }
610
611 static void emDM_foreachMappedFaceCenter(
612                 DerivedMesh *dm,
613                 void (*func)(void *userData, int index, float *co, float *no),
614                 void *userData)
615 {
616         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
617         float (*polyNos)[3] = NULL;
618         BMFace *efa;
619         BMIter iter;
620         float cent[3];
621         int i;
622
623         /* ensure for face center calculation */
624         if (bmdm->vertexCos) {
625                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
626                 polyNos = bmdm->polyNos;
627
628                 BLI_assert(polyNos != NULL);
629         }
630
631         efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
632         for (i=0; efa; efa=BMIter_Step(&iter), i++) {
633                 emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
634                 func(userData, i, cent, polyNos ? polyNos[i] : efa->no);
635         }
636 }
637
638 static void emDM_drawMappedFaces(
639                 DerivedMesh *dm,
640                 int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
641                 int (*setMaterial)(int, void *attribs),
642                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
643                 void *userData, int UNUSED(useColors))
644 {
645         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
646         BMFace *efa;
647         struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
648         const int tottri= bmdm->tc->tottri;
649         const int lasttri= tottri - 1; /* compare agasint this a lot */
650         int i, draw, flush;
651         const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
652
653         /* GL_ZERO is used to detect if drawing has started or not */
654         GLenum poly_prev= GL_ZERO;
655         GLenum shade_prev= GL_ZERO;
656
657         (void)setMaterial; /* UNUSED */
658
659         /* currently unused -- each original face is handled separately */
660         (void)compareDrawOptions;
661
662         if (bmdm->vertexCos) {
663                 /* add direct access */
664                 float (*vertexCos)[3]= bmdm->vertexCos;
665                 float (*vertexNos)[3]= bmdm->vertexNos;
666                 float (*polyNos)[3]=   bmdm->polyNos;
667                 // int *triPolyMap= bmdm->triPolyMap;
668
669                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
670
671                 for (i=0; i < tottri; i++) {
672                         BMLoop **l = looptris[i];
673                         int drawSmooth;
674
675                         efa = l[0]->f;
676                         drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
677
678                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
679                         if (draw) {
680                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
681                                 if (draw==2) { /* enabled with stipple */
682
683                                         if (poly_prev != GL_ZERO) glEnd();
684                                         poly_prev= GL_ZERO; /* force glBegin */
685
686                                         glEnable(GL_POLYGON_STIPPLE);
687                                         glPolygonStipple(stipple_quarttone);
688                                 }
689
690                                 if (skip_normals) {
691                                         if (poly_type != poly_prev) {
692                                                 if (poly_prev != GL_ZERO) glEnd();
693                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
694                                         }
695                                         glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
696                                         glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
697                                         glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
698                                 }
699                                 else {
700                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
701                                         if (shade_type != shade_prev) {
702                                                 if (poly_prev != GL_ZERO) glEnd();
703                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
704                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
705                                         }
706                                         if (poly_type != poly_prev) {
707                                                 if (poly_prev != GL_ZERO) glEnd();
708                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
709                                         }
710
711                                         if (!drawSmooth) {
712                                                 glNormal3fv(polyNos[BM_GetIndex(efa)]);
713                                                 glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
714                                                 glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
715                                                 glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
716                                         }
717                                         else {
718                                                 glNormal3fv(vertexNos[BM_GetIndex(l[0]->v)]);
719                                                 glVertex3fv(vertexCos[BM_GetIndex(l[0]->v)]);
720                                                 glNormal3fv(vertexNos[BM_GetIndex(l[1]->v)]);
721                                                 glVertex3fv(vertexCos[BM_GetIndex(l[1]->v)]);
722                                                 glNormal3fv(vertexNos[BM_GetIndex(l[2]->v)]);
723                                                 glVertex3fv(vertexCos[BM_GetIndex(l[2]->v)]);
724                                         }
725                                 }
726
727                                 flush= (draw==2);
728                                 if (!skip_normals && !flush && (i != lasttri))
729                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
730
731                                 if (flush) {
732                                         glEnd();
733                                         poly_prev= GL_ZERO; /* force glBegin */
734
735                                         glDisable(GL_POLYGON_STIPPLE);
736                                 }
737                         }
738                 }
739         }
740         else {
741                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_FACE);
742
743                 for (i=0; i < tottri; i++) {
744                         BMLoop **l = looptris[i];
745                         int drawSmooth;
746
747                         efa = l[0]->f;
748                         drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
749
750                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
751                         if (draw) {
752                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
753                                 if (draw==2) { /* enabled with stipple */
754
755                                         if (poly_prev != GL_ZERO) glEnd();
756                                         poly_prev= GL_ZERO; /* force glBegin */
757
758                                         glEnable(GL_POLYGON_STIPPLE);
759                                         glPolygonStipple(stipple_quarttone);
760                                 }
761
762                                 if (skip_normals) {
763                                         if (poly_type != poly_prev) {
764                                                 if (poly_prev != GL_ZERO) glEnd();
765                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
766                                         }
767                                         glVertex3fv(l[0]->v->co);
768                                         glVertex3fv(l[1]->v->co);
769                                         glVertex3fv(l[2]->v->co);
770                                 }
771                                 else {
772                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
773                                         if (shade_type != shade_prev) {
774                                                 if (poly_prev != GL_ZERO) glEnd();
775                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
776                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
777                                         }
778                                         if (poly_type != poly_prev) {
779                                                 if (poly_prev != GL_ZERO) glEnd();
780                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
781                                         }
782
783                                         if (!drawSmooth) {
784                                                 glNormal3fv(efa->no);
785                                                 glVertex3fv(l[0]->v->co);
786                                                 glVertex3fv(l[1]->v->co);
787                                                 glVertex3fv(l[2]->v->co);
788                                         }
789                                         else {
790                                                 glNormal3fv(l[0]->v->no);
791                                                 glVertex3fv(l[0]->v->co);
792                                                 glNormal3fv(l[1]->v->no);
793                                                 glVertex3fv(l[1]->v->co);
794                                                 glNormal3fv(l[2]->v->no);
795                                                 glVertex3fv(l[2]->v->co);
796                                         }
797                                 }
798
799                                 flush= (draw==2);
800                                 if (!skip_normals && !flush && (i != lasttri)) {
801                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
802                                 }
803
804                                 if (flush) {
805                                         glEnd();
806                                         poly_prev= GL_ZERO; /* force glBegin */
807
808                                         glDisable(GL_POLYGON_STIPPLE);
809                                 }
810                         }
811                 }
812         }
813
814         /* if non zero we know a face was rendered */
815         if (poly_prev != GL_ZERO) glEnd();
816 }
817
818 static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
819                                  int has_uv, int has_col)
820 {
821         if (has_uv) {
822                 luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
823                 luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
824                 luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
825         }
826
827         if (has_col) {
828                 lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
829                 lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
830                 lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
831         }
832
833
834 }
835
836 static void emDM_drawFacesTex_common(
837                 DerivedMesh *dm,
838                 int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
839                 int (*drawParamsMapped)(void *userData, int index),
840                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
841                 void *userData)
842 {
843         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
844         BMEditMesh *em = bmdm->tc;
845         BMesh *bm= bmdm->tc->bm;
846         float (*vertexCos)[3]= bmdm->vertexCos;
847         float (*vertexNos)[3]= bmdm->vertexNos;
848         BMFace *efa;
849         MLoopUV *luv[3], dummyluv = {{0}};
850         MLoopCol *lcol[3], dummylcol = {0};
851         int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
852         int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
853
854         (void) compareDrawOptions;
855
856         luv[0] = luv[1] = luv[2] = &dummyluv;
857         lcol[0] = lcol[1] = lcol[2] = &dummylcol;
858
859         dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
860
861         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
862         glShadeModel(GL_SMOOTH);
863
864         BM_ElemIndex_Ensure(bm, BM_FACE);
865
866         if (vertexCos) {
867                 BM_ElemIndex_Ensure(bm, BM_VERT);
868
869                 glBegin(GL_TRIANGLES);
870                 for (i=0; i<em->tottri; i++) {
871                         BMLoop **ls = em->looptris[i];
872                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
873                         MTFace mtf = {{{0}}};
874                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
875                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
876                         int flag;
877
878                         efa = ls[0]->f;
879
880                         if (has_uv) {
881                                 mtf.flag = tp->flag;
882                                 mtf.tpage = tp->tpage;
883                                 mtf.transp = tp->transp;
884                                 mtf.mode = tp->mode;
885                                 mtf.tile = tp->tile;
886                                 mtf.unwrap = tp->unwrap;
887                         }
888
889                         if (drawParams)
890                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
891                         else if (drawParamsMapped)
892                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
893                         else
894                                 flag= 1;
895
896                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
897
898                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
899                                 if (!has_vcol) {
900                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
901                                 }
902
903                                 if (!drawSmooth) {
904                                         glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]);
905
906                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
907
908                                         glTexCoord2fv(luv[0]->uv);
909                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
910                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
911
912                                         glTexCoord2fv(luv[1]->uv);
913                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
914                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
915
916                                         glTexCoord2fv(luv[2]->uv);
917                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
918                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
919                                 }
920                                 else {
921                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
922
923                                         glTexCoord2fv(luv[0]->uv);
924                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
925                                         glNormal3fv(vertexNos[BM_GetIndex(ls[0]->v)]);
926                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
927
928                                         glTexCoord2fv(luv[1]->uv);
929                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
930                                         glNormal3fv(vertexNos[BM_GetIndex(ls[1]->v)]);
931                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
932
933                                         glTexCoord2fv(luv[2]->uv);
934                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
935                                         glNormal3fv(vertexNos[BM_GetIndex(ls[2]->v)]);
936                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
937                                 }
938                         }
939                 }
940                 glEnd();
941         }
942         else {
943                 BM_ElemIndex_Ensure(bm, BM_VERT);
944
945                 for (i=0; i<em->tottri; i++) {
946                         BMLoop **ls = em->looptris[i];
947                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
948                         MTFace mtf = {{{0}}};
949                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
950                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
951                         int flag;
952
953                         efa = ls[0]->f;
954
955                         if (has_uv) {
956                                 mtf.flag = tp->flag;
957                                 mtf.tpage = tp->tpage;
958                                 mtf.transp = tp->transp;
959                                 mtf.mode = tp->mode;
960                                 mtf.tile = tp->tile;
961                                 mtf.unwrap = tp->unwrap;
962                         }
963
964                         if (drawParams)
965                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
966                         else if (drawParamsMapped)
967                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
968                         else
969                                 flag= 1;
970
971                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
972
973                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
974                                 if (!has_vcol) {
975                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
976                                 }
977
978                                 glBegin(GL_TRIANGLES);
979                                 if (!drawSmooth) {
980                                         glNormal3fv(efa->no);
981
982                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
983
984                                         if (luv[0])
985                                                 glTexCoord2fv(luv[0]->uv);
986                                         if (lcol[0])
987                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
988                                         else glColor3ub(0, 0, 0);
989                                         glVertex3fv(ls[0]->v->co);
990
991                                         if (luv[1])
992                                                 glTexCoord2fv(luv[1]->uv);
993                                         if (lcol[1])
994                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
995                                         else glColor3ub(0, 0, 0);
996                                         glVertex3fv(ls[1]->v->co);
997
998                                         if (luv[2])
999                                                 glTexCoord2fv(luv[2]->uv);
1000                                         if (lcol[2])
1001                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
1002                                         else glColor3ub(0, 0, 0);
1003                                         glVertex3fv(ls[2]->v->co);
1004                                 }
1005                                 else {
1006                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
1007
1008                                         if (luv[0])
1009                                                 glTexCoord2fv(luv[0]->uv);
1010                                         if (lcol[0])
1011                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
1012                                         else glColor3ub(0, 0, 0);
1013                                         glNormal3fv(ls[0]->v->no);
1014                                         glVertex3fv(ls[0]->v->co);
1015
1016                                         if (luv[1])
1017                                                 glTexCoord2fv(luv[1]->uv);
1018                                         if (lcol[1])
1019                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
1020                                         else glColor3ub(0, 0, 0);
1021                                         glNormal3fv(ls[1]->v->no);
1022                                         glVertex3fv(ls[1]->v->co);
1023
1024                                         if (luv[2])
1025                                                 glTexCoord2fv(luv[2]->uv);
1026                                         if (lcol[2])
1027                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
1028                                         else glColor3ub(0, 0, 0);
1029                                         glNormal3fv(ls[2]->v->no);
1030                                         glVertex3fv(ls[2]->v->co);
1031                                 }
1032                                 glEnd();
1033                         }
1034                 }
1035         }
1036 }
1037
1038 static void emDM_drawFacesTex(
1039                 DerivedMesh *dm,
1040                 int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr),
1041                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1042                 void *userData)
1043 {
1044         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
1045 }
1046
1047 static void emDM_drawMappedFacesTex(
1048                 DerivedMesh *dm,
1049                 int (*setDrawOptions)(void *userData, int index),
1050                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1051                 void *userData)
1052 {
1053         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
1054 }
1055
1056 static void emDM_drawMappedFacesGLSL(
1057                 DerivedMesh *dm,
1058                 int (*setMaterial)(int, void *attribs),
1059                 int (*setDrawOptions)(void *userData, int index),
1060                 void *userData)
1061 {
1062         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1063         BMesh *bm= bmdm->tc->bm;
1064         BMEditMesh *em = bmdm->tc;
1065         float (*vertexCos)[3]= bmdm->vertexCos;
1066         float (*vertexNos)[3]= bmdm->vertexNos;
1067         BMFace *efa;
1068         BMLoop **ltri;
1069         DMVertexAttribs attribs;
1070         GPUVertexAttribs gattribs;
1071
1072         int i, b, matnr, new_matnr, dodraw;
1073
1074         dodraw = 0;
1075         matnr = -1;
1076
1077         memset(&attribs, 0, sizeof(attribs));
1078
1079         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1080         glShadeModel(GL_SMOOTH);
1081         BM_ElemIndex_Ensure(bm, BM_VERT | BM_FACE);
1082
1083 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1084         if (attribs.totorco) {                                                                                                          \
1085                 float *orco = attribs.orco.array[BM_GetIndex(eve)];                                             \
1086                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
1087         }                                                                                                                                                       \
1088         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1089                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1090                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
1091         }                                                                                                                                                       \
1092         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
1093                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1094                 GLubyte _col[4];                                                                                                                \
1095                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
1096                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
1097         }                                                                                                                                                       \
1098         if (attribs.tottang) {                                                                                                          \
1099                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
1100                 glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
1101         }                                                                                                                                                       \
1102         }
1103
1104
1105         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1106                 int drawSmooth;
1107
1108                 efa = ltri[0]->f;
1109                 drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
1110
1111                 if (setDrawOptions && !setDrawOptions(userData, BM_GetIndex(efa)))
1112                         continue;
1113
1114                 new_matnr = efa->mat_nr + 1;
1115                 if (new_matnr != matnr) {
1116                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1117                         if (dodraw)
1118                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1119                 }
1120
1121                 if (dodraw) {
1122                         glBegin(GL_TRIANGLES);
1123                         if (!drawSmooth) {
1124                                 if (vertexCos) glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]);
1125                                 else glNormal3fv(efa->no);
1126
1127                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1128                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1129                                 else glVertex3fv(ltri[0]->v->co);
1130
1131                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1132                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1133                                 else glVertex3fv(ltri[1]->v->co);
1134
1135                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1136                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1137                                 else glVertex3fv(ltri[2]->v->co);
1138                         }
1139                         else {
1140                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1141                                 if (vertexCos) {
1142                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1143                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1144                                 }
1145                                 else {
1146                                         glNormal3fv(ltri[0]->v->no);
1147                                         glVertex3fv(ltri[0]->v->co);
1148                                 }
1149
1150                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1151                                 if (vertexCos) {
1152                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1153                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1154                                 }
1155                                 else {
1156                                         glNormal3fv(ltri[1]->v->no);
1157                                         glVertex3fv(ltri[1]->v->co);
1158                                 }
1159
1160                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1161                                 if (vertexCos) {
1162                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1163                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1164                                 }
1165                                 else {
1166                                         glNormal3fv(ltri[2]->v->no);
1167                                         glVertex3fv(ltri[2]->v->co);
1168                                 }
1169                         }
1170                         glEnd();
1171                 }
1172         }
1173 #undef PASSATTRIB
1174 }
1175
1176 static void emDM_drawFacesGLSL(
1177                 DerivedMesh *dm,
1178                 int (*setMaterial)(int, void *attribs))
1179 {
1180         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1181 }
1182
1183 static void emDM_drawMappedFacesMat(
1184                 DerivedMesh *dm,
1185                 void (*setMaterial)(void *userData, int, void *attribs),
1186                 int (*setFace)(void *userData, int index), void *userData)
1187 {
1188         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1189         BMesh *bm= bmdm->tc->bm;
1190         BMEditMesh *em = bmdm->tc;
1191         float (*vertexCos)[3]= bmdm->vertexCos;
1192         float (*vertexNos)[3]= bmdm->vertexNos;
1193         BMFace *efa;
1194         BMLoop **ltri;
1195         DMVertexAttribs attribs= {{{0}}};
1196         GPUVertexAttribs gattribs;
1197         int i, b, matnr, new_matnr;
1198
1199         matnr = -1;
1200
1201         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1202         glShadeModel(GL_SMOOTH);
1203
1204         BM_ElemIndex_Ensure(bm, BM_VERT);
1205
1206 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1207         if (attribs.totorco) {                                                                                                          \
1208                 float *orco = attribs.orco.array[BM_GetIndex(eve)];                                             \
1209                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
1210         }                                                                                                                                                       \
1211         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1212                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1213                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
1214         }                                                                                                                                                       \
1215         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
1216                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1217                 GLubyte _col[4];                                                                                                                \
1218                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
1219                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
1220         }                                                                                                                                                       \
1221         if (attribs.tottang) {                                                                                                          \
1222                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
1223                 glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
1224         }                                                                                                                                                       \
1225 }
1226
1227         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1228                 int drawSmooth;
1229
1230                 efa = ltri[0]->f;
1231                 drawSmooth = BM_TestHFlag(efa, BM_SMOOTH);
1232
1233                 /* face hiding */
1234                 if (setFace && !setFace(userData, BM_GetIndex(efa)))
1235                         continue;
1236
1237                 /* material */
1238                 new_matnr = efa->mat_nr + 1;
1239                 if (new_matnr != matnr) {
1240                         setMaterial(userData, matnr = new_matnr, &gattribs);
1241                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1242                 }
1243
1244                 /* face */
1245                 glBegin(GL_TRIANGLES);
1246                 if (!drawSmooth) {
1247                         if (vertexCos) glNormal3fv(bmdm->polyNos[BM_GetIndex(efa)]);
1248                         else glNormal3fv(efa->no);
1249
1250                         PASSATTRIB(ltri[0], ltri[0]->v, 0);
1251                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1252                         else glVertex3fv(ltri[0]->v->co);
1253
1254                         PASSATTRIB(ltri[1], ltri[1]->v, 1);
1255                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1256                         else glVertex3fv(ltri[1]->v->co);
1257
1258                         PASSATTRIB(ltri[2], ltri[2]->v, 2);
1259                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1260                         else glVertex3fv(ltri[2]->v->co);
1261
1262                 }
1263                 else {
1264                         PASSATTRIB(ltri[0], ltri[0]->v, 0);
1265                         if (vertexCos) {
1266                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1267                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1268                         }
1269                         else {
1270                                 glNormal3fv(ltri[0]->v->no);
1271                                 glVertex3fv(ltri[0]->v->co);
1272                         }
1273
1274                         PASSATTRIB(ltri[1], ltri[1]->v, 1);
1275                         if (vertexCos) {
1276                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1277                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1278                         }
1279                         else {
1280                                 glNormal3fv(ltri[1]->v->no);
1281                                 glVertex3fv(ltri[1]->v->co);
1282                         }
1283
1284                         PASSATTRIB(ltri[2], ltri[2]->v, 2);
1285                         if (vertexCos) {
1286                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1287                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1288                         }
1289                         else {
1290                                 glNormal3fv(ltri[2]->v->no);
1291                                 glVertex3fv(ltri[2]->v->co);
1292                         }
1293                 }
1294                 glEnd();
1295         }
1296 #undef PASSATTRIB
1297 }
1298
1299 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1300 {
1301         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1302         BMVert *eve;
1303         BMIter iter;
1304         int i;
1305
1306         if (bmdm->tc->bm->totvert) {
1307                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1308                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1309                         if (bmdm->vertexCos) {
1310                                 DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
1311                         }
1312                         else {
1313                                 DO_MINMAX(eve->co, min_r, max_r);
1314                         }
1315                 }
1316         }
1317         else {
1318                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1319         }
1320 }
1321 static int emDM_getNumVerts(DerivedMesh *dm)
1322 {
1323         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1324
1325         return bmdm->tc->bm->totvert;
1326 }
1327
1328 static int emDM_getNumEdges(DerivedMesh *dm)
1329 {
1330         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1331
1332         return bmdm->tc->bm->totedge;
1333 }
1334
1335 static int emDM_getNumTessFaces(DerivedMesh *dm)
1336 {
1337         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1338
1339         return bmdm->tc->tottri;
1340 }
1341
1342 static int emDM_getNumLoops(DerivedMesh *dm)
1343 {
1344         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1345
1346         return bmdm->tc->bm->totloop;
1347 }
1348
1349 static int emDM_getNumPolys(DerivedMesh *dm)
1350 {
1351         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1352
1353         return bmdm->tc->bm->totface;
1354 }
1355
1356 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1357 {
1358         copy_v3_v3(vert_r->co, ev->co);
1359
1360         normal_float_to_short_v3(vert_r->no, ev->no);
1361
1362         vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1363
1364         if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1365                 vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1366         }
1367
1368         return 1;
1369 }
1370
1371 static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1372 {
1373         BMVert *ev;
1374
1375         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
1376                 printf("error in emDM_getVert.\n");
1377                 return;
1378         }
1379
1380         ev = ((EditDerivedBMesh *)dm)->vtable[index];
1381         bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r);
1382 }
1383
1384 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1385 {
1386         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1387         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1388         BMEdge *e;
1389
1390         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
1391                 printf("error in emDM_getEdge.\n");
1392                 return;
1393         }
1394
1395         e = bmdm->etable[index];
1396
1397         if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1398                 edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f);
1399         }
1400
1401         if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1402                 edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f);
1403         }
1404
1405         edge_r->flag = BM_Edge_Flag_To_MEFlag(e);
1406
1407         edge_r->v1 = BM_GetIndex(e->v1);
1408         edge_r->v2 = BM_GetIndex(e->v2);
1409 }
1410
1411 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1412 {
1413         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */
1414         BMFace *ef;
1415         BMLoop **l;
1416
1417         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
1418                 printf("error in emDM_getTessFace.\n");
1419                 return;
1420         }
1421
1422         l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
1423
1424         ef = l[0]->f;
1425
1426         face_r->mat_nr = (unsigned char) ef->mat_nr;
1427         face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1428
1429         face_r->v1 = BM_GetIndex(l[0]->v);
1430         face_r->v2 = BM_GetIndex(l[1]->v);
1431         face_r->v3 = BM_GetIndex(l[2]->v);
1432         face_r->v4 = 0;
1433
1434         test_index_face(face_r, NULL, 0, 3);
1435 }
1436
1437 static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1438 {
1439         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1440         BMVert *ev;
1441         BMIter iter;
1442
1443         ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1444         for ( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
1445                 copy_v3_v3(vert_r->co, ev->co);
1446
1447                 normal_float_to_short_v3(vert_r->no, ev->no);
1448
1449                 vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1450
1451                 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1452                         vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1453                 }
1454         }
1455 }
1456
1457 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1458 {
1459         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1460         BMEdge *ee;
1461         BMIter iter;
1462         int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1463         int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1464
1465         BM_ElemIndex_Ensure(bm, BM_VERT);
1466
1467         ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1468         for ( ; ee; ee=BMIter_Step(&iter), edge_r++) {
1469                 if (has_bweight) {
1470                         edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f);
1471                 }
1472
1473                 if (has_crease) {
1474                         edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f);
1475                 }
1476
1477                 edge_r->flag = BM_Edge_Flag_To_MEFlag(ee);
1478
1479                 edge_r->v1 = BM_GetIndex(ee->v1);
1480                 edge_r->v2 = BM_GetIndex(ee->v2);
1481         }
1482 }
1483
1484 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
1485 {
1486         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1487         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1488         BMFace *ef;
1489         BMLoop **l;
1490         int i;
1491
1492         BM_ElemIndex_Ensure(bm, BM_VERT);
1493
1494         for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
1495                 l = bmdm->tc->looptris[i];
1496                 ef = l[0]->f;
1497
1498                 face_r->mat_nr = (unsigned char) ef->mat_nr;
1499
1500                 face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1501
1502                 face_r->v1 = BM_GetIndex(l[0]->v);
1503                 face_r->v2 = BM_GetIndex(l[1]->v);
1504                 face_r->v3 = BM_GetIndex(l[2]->v);
1505                 face_r->v4 = 0;
1506
1507                 test_index_face(face_r, NULL, 0, 3);
1508         }
1509 }
1510
1511
1512 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1513 {
1514         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1515         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1516         BMIter iter, liter;
1517         BMFace *f;
1518         BMLoop *l;
1519
1520         BM_ElemIndex_Ensure(bm, BM_VERT | BM_EDGE);
1521
1522         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1523                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
1524                         loop_r->v = BM_GetIndex(l->v);
1525                         loop_r->e = BM_GetIndex(l->e);
1526                         loop_r++;
1527                 }
1528         }
1529 }
1530
1531 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1532 {
1533         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1534         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1535         BMIter iter;
1536         BMFace *f;
1537         int i;
1538
1539         i = 0;
1540         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1541                 poly_r->flag = BM_Face_Flag_To_MEFlag(f);
1542                 poly_r->loopstart = i;
1543                 poly_r->totloop = f->len;
1544                 poly_r->mat_nr = f->mat_nr;
1545
1546                 poly_r++;
1547                 i += f->len;
1548         }
1549 }
1550
1551 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1552 {
1553         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1554         BMesh *bm= bmdm->tc->bm;
1555         BMFace *efa;
1556         char *data, *bmdata;
1557         void *datalayer;
1558         int index /*, offset*/ /*UNUSED */, size, i;
1559
1560         datalayer = DM_get_tessface_data_layer(dm, type);
1561         if (datalayer)
1562                 return datalayer;
1563
1564         /* layers are store per face for editmesh, we convert to a tbmporary
1565          * data layer array in the derivedmesh when these are requested */
1566         if (type == CD_MTFACE || type == CD_MCOL) {
1567                 index = CustomData_get_layer_index(&bm->pdata, type);
1568
1569                 if (index != -1) {
1570                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1571                         size = CustomData_sizeof(type);
1572
1573                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1574                         index = CustomData_get_layer_index(&dm->faceData, type);
1575                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1576
1577                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1578                         for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
1579                                 efa = bmdm->tc->looptris[i][0]->f;
1580                                 /*BMESH_TODO: need to still add tface data,
1581                                   derived from the loops.*/
1582                                 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
1583                                 memcpy(data, bmdata, size);
1584                         }
1585                 }
1586         }
1587
1588         return datalayer;
1589 }
1590
1591 static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1592 {
1593         EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1594         BMVert *eve;
1595         BMIter iter;
1596         int i;
1597
1598         i= 0;
1599         BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
1600                 if (emdm->vertexCos) {
1601                         copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1602                 }
1603                 else {
1604                         copy_v3_v3(cos_r[i], eve->co);
1605                 }
1606
1607                 i++;
1608         }
1609 }
1610
1611 static void emDM_release(DerivedMesh *dm)
1612 {
1613         EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1614
1615         if (DM_release(dm)) {
1616                 if (bmdm->vertexCos) {
1617                         MEM_freeN(bmdm->vertexCos);
1618                         MEM_freeN(bmdm->vertexNos);
1619                         MEM_freeN(bmdm->polyNos);
1620                 }
1621
1622                 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
1623                 if (bmdm->etable) MEM_freeN(bmdm->etable);
1624                 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
1625
1626                 MEM_freeN(bmdm);
1627         }
1628 }
1629
1630 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1631 {
1632         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1633
1634         return &bmdm->tc->bm->vdata;
1635 }
1636
1637 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1638 {
1639         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1640
1641         return &bmdm->tc->bm->edata;
1642 }
1643
1644 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1645 {
1646         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1647
1648         return &bmdm->dm.faceData;
1649 }
1650
1651 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1652 {
1653         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1654
1655         return &bmdm->tc->bm->ldata;
1656 }
1657
1658 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1659 {
1660         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1661
1662         return &bmdm->tc->bm->pdata;
1663 }
1664
1665
1666 DerivedMesh *getEditDerivedBMesh(
1667                 BMEditMesh *em,
1668                 Object *UNUSED(ob),
1669                 float (*vertexCos)[3])
1670 {
1671         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1672         BMesh *bm = em->bm;
1673
1674         bmdm->tc = em;
1675
1676         DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
1677                  em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1678
1679         CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
1680
1681         bmdm->dm.getVertCos = emDM_getVertCos;
1682         bmdm->dm.getMinMax = emDM_getMinMax;
1683
1684         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1685         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1686         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1687         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1688         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1689
1690         bmdm->dm.getNumVerts = emDM_getNumVerts;
1691         bmdm->dm.getNumEdges = emDM_getNumEdges;
1692         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1693         bmdm->dm.getNumLoops = emDM_getNumLoops;
1694         bmdm->dm.getNumPolys = emDM_getNumPolys;
1695
1696         bmdm->dm.getVert = emDM_getVert;
1697         bmdm->dm.getEdge = emDM_getEdge;
1698         bmdm->dm.getTessFace = emDM_getTessFace;
1699         bmdm->dm.copyVertArray = emDM_copyVertArray;
1700         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1701         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1702         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1703         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1704
1705         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1706
1707         bmdm->dm.calcNormals = emDM_calcNormals;
1708         bmdm->dm.recalcTesselation = emDM_recalcTesselation;
1709
1710         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1711         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1712         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1713
1714         bmdm->dm.drawEdges = emDM_drawEdges;
1715         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1716         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1717         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1718         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1719         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1720         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1721         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1722         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1723         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1724
1725         bmdm->dm.release = emDM_release;
1726
1727         bmdm->vertexCos = vertexCos;
1728
1729         if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1730                 BMIter iter;
1731                 BMVert *eve;
1732                 int i;
1733
1734                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1735
1736                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1737                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1738                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1739                                                          CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1740         }
1741
1742         if (vertexCos) {
1743                 BMFace *efa;
1744                 BMVert *eve;
1745                 BMIter fiter;
1746                 BMIter viter;
1747                 int i;
1748
1749                 BM_ElemIndex_Ensure(bm, BM_VERT);
1750
1751                 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
1752                 bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos)*bm->totface, "bmdm_pno");
1753
1754                 i = 0;
1755                 BM_ITER(efa, &fiter, bm, BM_FACES_OF_MESH, NULL) {
1756                         BM_SetIndex(efa, i); /* set_inline */
1757                         BM_Face_UpdateNormal_VertexCos(bm, efa, bmdm->polyNos[i], vertexCos);
1758                         i++;
1759                 }
1760                 bm->elem_index_dirty &= ~BM_FACE;
1761
1762                 eve=BMIter_New(&viter, bm, BM_VERTS_OF_MESH, NULL);
1763                 for (i=0; eve; eve=BMIter_Step(&viter), i++) {
1764                         float *no = bmdm->vertexNos[i];
1765                         BM_ITER(efa, &fiter, bm, BM_FACES_OF_VERT, eve) {
1766                                 add_v3_v3(no, bmdm->polyNos[BM_GetIndex(efa)]);
1767                         }
1768
1769                         /* following Mesh convention; we use vertex coordinate itself
1770                          * for normal in this case */
1771                         if (normalize_v3(no)==0.0) {
1772                                 copy_v3_v3(no, vertexCos[i]);
1773                                 normalize_v3(no);
1774                         }
1775                 }
1776         }
1777
1778         //bmdm_recalc_lookups(bmdm);
1779
1780         return (DerivedMesh*) bmdm;
1781 }