style cleanup
[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 }