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