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