bmesh py api:
[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 in case 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; */ /* UNUSED */
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                 DMSetDrawOptions setDrawOptions,
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) != DM_DRAW_OPTION_SKIP)) {
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) != DM_DRAW_OPTION_SKIP)) {
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                 DMSetDrawOptions setDrawOptions,
447                 DMSetDrawInterpOptions setDrawInterpOptions,
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) != DM_DRAW_OPTION_SKIP)) {
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) != DM_DRAW_OPTION_SKIP)) {
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                 DMSetDrawOptions setDrawOptions,
583                 DMSetMaterial setMaterial,
584                 DMCompareDrawOptions compareDrawOptions,
585                 void *userData,
586                 DMDrawFlag flag)
587 {
588         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
589         BMFace *efa;
590         struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
591         const int tottri= bmdm->tc->tottri;
592         const int lasttri= tottri - 1; /* compare agasint this a lot */
593         DMDrawOption draw_option;
594         int i, flush;
595         const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
596
597         /* GL_ZERO is used to detect if drawing has started or not */
598         GLenum poly_prev= GL_ZERO;
599         GLenum shade_prev= GL_ZERO;
600
601         (void)setMaterial; /* UNUSED */
602
603         /* currently unused -- each original face is handled separately */
604         (void)compareDrawOptions;
605
606         if (bmdm->vertexCos) {
607                 /* add direct access */
608                 float (*vertexCos)[3]= bmdm->vertexCos;
609                 float (*vertexNos)[3]= bmdm->vertexNos;
610                 float (*polyNos)[3]=   bmdm->polyNos;
611                 // int *triPolyMap= bmdm->triPolyMap;
612
613                 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
614
615                 for (i=0; i < tottri; i++) {
616                         BMLoop **l = looptris[i];
617                         int drawSmooth;
618
619                         efa = l[0]->f;
620                         drawSmooth= (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
621
622                         draw_option = (!setDrawOptions ?
623                                                    DM_DRAW_OPTION_NORMAL :
624                                                    setDrawOptions(userData, BM_elem_index_get(efa)));
625                         if (draw_option != DM_DRAW_OPTION_SKIP) {
626                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
627                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
628
629                                         if (poly_prev != GL_ZERO) glEnd();
630                                         poly_prev= GL_ZERO; /* force glBegin */
631
632                                         glEnable(GL_POLYGON_STIPPLE);
633                                         glPolygonStipple(stipple_quarttone);
634                                 }
635
636                                 if (skip_normals) {
637                                         if (poly_type != poly_prev) {
638                                                 if (poly_prev != GL_ZERO) glEnd();
639                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
640                                         }
641                                         glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
642                                         glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
643                                         glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
644                                 }
645                                 else {
646                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
647                                         if (shade_type != shade_prev) {
648                                                 if (poly_prev != GL_ZERO) glEnd();
649                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
650                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
651                                         }
652                                         if (poly_type != poly_prev) {
653                                                 if (poly_prev != GL_ZERO) glEnd();
654                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
655                                         }
656
657                                         if (!drawSmooth) {
658                                                 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
659                                                 glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
660                                                 glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
661                                                 glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
662                                         }
663                                         else {
664                                                 glNormal3fv(vertexNos[BM_elem_index_get(l[0]->v)]);
665                                                 glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
666                                                 glNormal3fv(vertexNos[BM_elem_index_get(l[1]->v)]);
667                                                 glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
668                                                 glNormal3fv(vertexNos[BM_elem_index_get(l[2]->v)]);
669                                                 glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
670                                         }
671                                 }
672
673                                 flush= (draw_option == DM_DRAW_OPTION_STIPPLE);
674                                 if (!skip_normals && !flush && (i != lasttri))
675                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
676
677                                 if (flush) {
678                                         glEnd();
679                                         poly_prev= GL_ZERO; /* force glBegin */
680
681                                         glDisable(GL_POLYGON_STIPPLE);
682                                 }
683                         }
684                 }
685         }
686         else {
687                 BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_FACE);
688
689                 for (i=0; i < tottri; i++) {
690                         BMLoop **l = looptris[i];
691                         int drawSmooth;
692
693                         efa = l[0]->f;
694                         drawSmooth= (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
695
696                         draw_option = (!setDrawOptions ?
697                                                    DM_DRAW_OPTION_NORMAL :
698                                                    setDrawOptions(userData, BM_elem_index_get(efa)));
699                         if (draw_option != DM_DRAW_OPTION_SKIP) {
700                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
701                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
702
703                                         if (poly_prev != GL_ZERO) glEnd();
704                                         poly_prev= GL_ZERO; /* force glBegin */
705
706                                         glEnable(GL_POLYGON_STIPPLE);
707                                         glPolygonStipple(stipple_quarttone);
708                                 }
709
710                                 if (skip_normals) {
711                                         if (poly_type != poly_prev) {
712                                                 if (poly_prev != GL_ZERO) glEnd();
713                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
714                                         }
715                                         glVertex3fv(l[0]->v->co);
716                                         glVertex3fv(l[1]->v->co);
717                                         glVertex3fv(l[2]->v->co);
718                                 }
719                                 else {
720                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
721                                         if (shade_type != shade_prev) {
722                                                 if (poly_prev != GL_ZERO) glEnd();
723                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
724                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
725                                         }
726                                         if (poly_type != poly_prev) {
727                                                 if (poly_prev != GL_ZERO) glEnd();
728                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
729                                         }
730
731                                         if (!drawSmooth) {
732                                                 glNormal3fv(efa->no);
733                                                 glVertex3fv(l[0]->v->co);
734                                                 glVertex3fv(l[1]->v->co);
735                                                 glVertex3fv(l[2]->v->co);
736                                         }
737                                         else {
738                                                 glNormal3fv(l[0]->v->no);
739                                                 glVertex3fv(l[0]->v->co);
740                                                 glNormal3fv(l[1]->v->no);
741                                                 glVertex3fv(l[1]->v->co);
742                                                 glNormal3fv(l[2]->v->no);
743                                                 glVertex3fv(l[2]->v->co);
744                                         }
745                                 }
746
747                                 flush= (draw_option == DM_DRAW_OPTION_STIPPLE);
748                                 if (!skip_normals && !flush && (i != lasttri)) {
749                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
750                                 }
751
752                                 if (flush) {
753                                         glEnd();
754                                         poly_prev= GL_ZERO; /* force glBegin */
755
756                                         glDisable(GL_POLYGON_STIPPLE);
757                                 }
758                         }
759                 }
760         }
761
762         /* if non zero we know a face was rendered */
763         if (poly_prev != GL_ZERO) glEnd();
764 }
765
766 static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
767                                  int has_uv, int has_col)
768 {
769         if (has_uv) {
770                 luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
771                 luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
772                 luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
773         }
774
775         if (has_col) {
776                 lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
777                 lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
778                 lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
779         }
780
781
782 }
783
784 static void emDM_drawFacesTex_common(
785                 DerivedMesh *dm,
786                 DMSetDrawOptionsTex drawParams,
787                 DMSetDrawOptions drawParamsMapped,
788                 DMCompareDrawOptions compareDrawOptions,
789                 void *userData)
790 {
791         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
792         BMEditMesh *em = bmdm->tc;
793         BMesh *bm= bmdm->tc->bm;
794         float (*vertexCos)[3]= bmdm->vertexCos;
795         float (*vertexNos)[3]= bmdm->vertexNos;
796         BMFace *efa;
797         MLoopUV *luv[3], dummyluv = {{0}};
798         MLoopCol *lcol[3] = {NULL}, dummylcol = {0};
799         int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
800         int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
801
802         (void) compareDrawOptions;
803
804         luv[0] = luv[1] = luv[2] = &dummyluv;
805
806         dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
807
808         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
809         glShadeModel(GL_SMOOTH);
810
811         BM_mesh_elem_index_ensure(bm, BM_FACE);
812
813         if (vertexCos) {
814                 BM_mesh_elem_index_ensure(bm, BM_VERT);
815
816                 glBegin(GL_TRIANGLES);
817                 for (i=0; i<em->tottri; i++) {
818                         BMLoop **ls = em->looptris[i];
819                         MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
820                         MTFace mtf = {{{0}}};
821                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
822                         int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
823                         DMDrawOption draw_option;
824
825                         efa = ls[0]->f;
826
827                         if (has_uv) {
828                                 ME_MTEXFACE_CPY(&mtf, tp);
829                         }
830
831                         if (drawParams)
832                                 draw_option= drawParams(&mtf, has_vcol, efa->mat_nr);
833                         else if (drawParamsMapped)
834                                 draw_option= drawParamsMapped(userData, BM_elem_index_get(efa));
835                         else
836                                 draw_option= DM_DRAW_OPTION_NORMAL;
837
838                         if (draw_option != DM_DRAW_OPTION_SKIP) {
839
840                                 if (!drawSmooth) {
841                                         glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
842
843                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
844
845                                         glTexCoord2fv(luv[0]->uv);
846                                         if (lcol[0])
847                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
848                                         glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
849
850                                         glTexCoord2fv(luv[1]->uv);
851                                         if (lcol[1])
852                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
853                                         glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
854
855                                         glTexCoord2fv(luv[2]->uv);
856                                         if (lcol[2])
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                                         if (lcol[0])
865                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
866                                         glNormal3fv(vertexNos[BM_elem_index_get(ls[0]->v)]);
867                                         glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
868
869                                         glTexCoord2fv(luv[1]->uv);
870                                         if (lcol[1])
871                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
872                                         glNormal3fv(vertexNos[BM_elem_index_get(ls[1]->v)]);
873                                         glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
874
875                                         glTexCoord2fv(luv[2]->uv);
876                                         if (lcol[2])
877                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
878                                         glNormal3fv(vertexNos[BM_elem_index_get(ls[2]->v)]);
879                                         glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
880                                 }
881                         }
882                 }
883                 glEnd();
884         }
885         else {
886                 BM_mesh_elem_index_ensure(bm, BM_VERT);
887
888                 for (i=0; i<em->tottri; i++) {
889                         BMLoop **ls = em->looptris[i];
890                         MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
891                         MTFace mtf = {{{0}}};
892                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
893                         int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
894                         DMDrawOption draw_option;
895
896                         efa = ls[0]->f;
897
898                         if (has_uv) {
899                                 ME_MTEXFACE_CPY(&mtf, tp);
900                         }
901
902                         if (drawParams)
903                                 draw_option= drawParams(&mtf, has_vcol, efa->mat_nr);
904                         else if (drawParamsMapped)
905                                 draw_option= drawParamsMapped(userData, BM_elem_index_get(efa));
906                         else
907                                 draw_option= DM_DRAW_OPTION_NORMAL;
908
909                         if (draw_option != DM_DRAW_OPTION_SKIP) {
910
911                                 glBegin(GL_TRIANGLES);
912                                 if (!drawSmooth) {
913                                         glNormal3fv(efa->no);
914
915                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
916
917                                         if (luv[0])
918                                                 glTexCoord2fv(luv[0]->uv);
919                                         if (lcol[0])
920                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
921                                         glVertex3fv(ls[0]->v->co);
922
923                                         if (luv[1])
924                                                 glTexCoord2fv(luv[1]->uv);
925                                         if (lcol[1])
926                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
927                                         glVertex3fv(ls[1]->v->co);
928
929                                         if (luv[2])
930                                                 glTexCoord2fv(luv[2]->uv);
931                                         if (lcol[2])
932                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
933                                         glVertex3fv(ls[2]->v->co);
934                                 }
935                                 else {
936                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
937
938                                         if (luv[0])
939                                                 glTexCoord2fv(luv[0]->uv);
940                                         if (lcol[0])
941                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
942                                         glNormal3fv(ls[0]->v->no);
943                                         glVertex3fv(ls[0]->v->co);
944
945                                         if (luv[1])
946                                                 glTexCoord2fv(luv[1]->uv);
947                                         if (lcol[1])
948                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
949                                         glNormal3fv(ls[1]->v->no);
950                                         glVertex3fv(ls[1]->v->co);
951
952                                         if (luv[2])
953                                                 glTexCoord2fv(luv[2]->uv);
954                                         if (lcol[2])
955                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
956                                         glNormal3fv(ls[2]->v->no);
957                                         glVertex3fv(ls[2]->v->co);
958                                 }
959                                 glEnd();
960                         }
961                 }
962         }
963
964         glShadeModel(GL_FLAT);
965 }
966
967 static void emDM_drawFacesTex(
968                 DerivedMesh *dm,
969                 DMSetDrawOptionsTex setDrawOptions,
970                 DMCompareDrawOptions compareDrawOptions,
971                 void *userData)
972 {
973         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
974 }
975
976 static void emDM_drawMappedFacesTex(
977                 DerivedMesh *dm,
978                 DMSetDrawOptions setDrawOptions,
979                 DMCompareDrawOptions compareDrawOptions,
980                 void *userData)
981 {
982         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
983 }
984
985 static void emDM_drawMappedFacesGLSL(
986                 DerivedMesh *dm,
987                 DMSetMaterial setMaterial,
988                 DMSetDrawOptions setDrawOptions,
989                 void *userData)
990 {
991         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
992         BMesh *bm= bmdm->tc->bm;
993         BMEditMesh *em = bmdm->tc;
994         float (*vertexCos)[3]= bmdm->vertexCos;
995         float (*vertexNos)[3]= bmdm->vertexNos;
996         BMFace *efa;
997         BMLoop **ltri;
998         DMVertexAttribs attribs;
999         GPUVertexAttribs gattribs;
1000
1001         int i, b, matnr, new_matnr, dodraw;
1002
1003         dodraw = 0;
1004         matnr = -1;
1005
1006         memset(&attribs, 0, sizeof(attribs));
1007
1008         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1009         glShadeModel(GL_SMOOTH);
1010         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
1011
1012 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1013         if (attribs.totorco) {                                                                                                          \
1014                 float *orco = attribs.orco.array[BM_elem_index_get(eve)];                                               \
1015                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
1016         }                                                                                                                                                       \
1017         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1018                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1019                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
1020         }                                                                                                                                                       \
1021         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
1022                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1023                 GLubyte _col[4];                                                                                                                \
1024                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
1025                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
1026         }                                                                                                                                                       \
1027         if (attribs.tottang) {                                                                                                          \
1028                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
1029                 glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
1030         }                                                                                                                                                       \
1031         }
1032
1033
1034         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1035                 int drawSmooth;
1036
1037                 efa = ltri[0]->f;
1038                 drawSmooth= BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1039
1040                 if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
1041                         continue;
1042
1043                 new_matnr = efa->mat_nr + 1;
1044                 if (new_matnr != matnr) {
1045                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1046                         if (dodraw)
1047                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1048                 }
1049
1050                 if (dodraw) {
1051                         glBegin(GL_TRIANGLES);
1052                         if (!drawSmooth) {
1053                                 if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
1054                                 else glNormal3fv(efa->no);
1055
1056                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1057                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1058                                 else glVertex3fv(ltri[0]->v->co);
1059
1060                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1061                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1062                                 else glVertex3fv(ltri[1]->v->co);
1063
1064                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1065                                 if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1066                                 else glVertex3fv(ltri[2]->v->co);
1067                         }
1068                         else {
1069                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1070                                 if (vertexCos) {
1071                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1072                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1073                                 }
1074                                 else {
1075                                         glNormal3fv(ltri[0]->v->no);
1076                                         glVertex3fv(ltri[0]->v->co);
1077                                 }
1078
1079                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1080                                 if (vertexCos) {
1081                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1082                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1083                                 }
1084                                 else {
1085                                         glNormal3fv(ltri[1]->v->no);
1086                                         glVertex3fv(ltri[1]->v->co);
1087                                 }
1088
1089                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1090                                 if (vertexCos) {
1091                                         glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1092                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1093                                 }
1094                                 else {
1095                                         glNormal3fv(ltri[2]->v->no);
1096                                         glVertex3fv(ltri[2]->v->co);
1097                                 }
1098                         }
1099                         glEnd();
1100                 }
1101         }
1102 #undef PASSATTRIB
1103 }
1104
1105 static void emDM_drawFacesGLSL(
1106                 DerivedMesh *dm,
1107                 int (*setMaterial)(int, void *attribs))
1108 {
1109         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1110 }
1111
1112 static void emDM_drawMappedFacesMat(
1113                 DerivedMesh *dm,
1114                 void (*setMaterial)(void *userData, int, void *attribs),
1115                 int (*setFace)(void *userData, int index), void *userData)
1116 {
1117         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1118         BMesh *bm= bmdm->tc->bm;
1119         BMEditMesh *em = bmdm->tc;
1120         float (*vertexCos)[3]= bmdm->vertexCos;
1121         float (*vertexNos)[3]= bmdm->vertexNos;
1122         BMFace *efa;
1123         BMLoop **ltri;
1124         DMVertexAttribs attribs= {{{0}}};
1125         GPUVertexAttribs gattribs;
1126         int i, b, matnr, new_matnr;
1127
1128         matnr = -1;
1129
1130         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1131         glShadeModel(GL_SMOOTH);
1132
1133         BM_mesh_elem_index_ensure(bm, BM_VERT|BM_FACE);
1134
1135 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1136         if (attribs.totorco) {                                                                                                          \
1137                 float *orco = attribs.orco.array[BM_elem_index_get(eve)];                               \
1138                 if (attribs.orco.glTexco)                                                                                               \
1139                         glTexCoord3fv(orco);                                                                                            \
1140                 else                                                                                                                                    \
1141                         glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                       \
1142         }                                                                                                                                                       \
1143         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1144                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1145                 if (attribs.tface[b].glTexco)                                                                                   \
1146                         glTexCoord2fv(_luv->uv);                                                                                        \
1147                 else                                                                                                                                    \
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.recalcTessellation = emDM_recalcTessellation;
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], (float const (*)[3])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 }
1715
1716 /**
1717  * \brief Return the BMEditMesh for a given object
1718  *
1719  * \note this function assumes this is a mesh object,
1720  * don't add NULL data check here. caller must do that
1721  */
1722 BMEditMesh *BMEdit_FromObject(Object *ob)
1723 {
1724         BLI_assert(ob->type == OB_MESH);
1725         return ((Mesh *)ob->data)->edit_btmesh;
1726 }