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