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