55dd20061d8fbf2cce761e20334ff5aef80e6ca9
[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_getNumPolys(DerivedMesh *dm)
1280 {
1281         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1282         
1283         return bmdm->tc->bm->totface;
1284 }
1285
1286 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1287 {
1288         copy_v3_v3(vert_r->co, ev->co);
1289
1290         vert_r->no[0] = (short)(ev->no[0] * 32767.0f);
1291         vert_r->no[1] = (short)(ev->no[1] * 32767.0f);
1292         vert_r->no[2] = (short)(ev->no[2] * 32767.0f);
1293
1294         vert_r->flag = BMFlags_To_MEFlags(ev);
1295
1296         if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1297                 vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1298         }
1299
1300         return 1;
1301 }
1302
1303 static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1304 {
1305         BMVert *ev;
1306
1307         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
1308                 printf("error in bmDM_getVert.\n");
1309                 return;
1310         }
1311
1312         ev = ((EditDerivedBMesh *)dm)->vtable[index];
1313         bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r);
1314 }
1315
1316 static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1317 {
1318         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1319         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1320         BMEdge *e;
1321
1322         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
1323                 printf("error in bmDM_getEdge.\n");
1324                 return;
1325         }
1326
1327         e = bmdm->etable[index];
1328
1329         if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1330                 edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f);
1331         }
1332
1333         if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1334                 edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f);
1335         }
1336
1337         edge_r->flag = BMFlags_To_MEFlags(e);
1338         
1339         edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1));
1340         edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2));
1341 }
1342
1343 static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1344 {
1345         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1346         BMFace *ef;
1347         BMLoop **l;
1348         
1349         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
1350                 printf("error in bmDM_getTessFace.\n");
1351                 return;
1352         }
1353
1354         l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
1355
1356         ef = l[0]->f;
1357
1358         face_r->mat_nr = (unsigned char) ef->mat_nr;
1359         face_r->flag = BMFlags_To_MEFlags(ef);
1360
1361         face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v));
1362         face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v));
1363         face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v));
1364         face_r->v4 = 0;
1365
1366         test_index_face(face_r, NULL, 0, 3);
1367 }
1368
1369 static void bmDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1370 {
1371         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1372         BMVert *ev;
1373         BMIter iter;
1374
1375         ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1376         for( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
1377                 copy_v3_v3(vert_r->co, ev->co);
1378
1379                 vert_r->no[0] = (short) (ev->no[0] * 32767.0);
1380                 vert_r->no[1] = (short) (ev->no[1] * 32767.0);
1381                 vert_r->no[2] = (short) (ev->no[2] * 32767.0);
1382
1383                 vert_r->flag = BMFlags_To_MEFlags(ev);
1384
1385                 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1386                         vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1387                 }
1388         }
1389 }
1390
1391 static void bmDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1392 {
1393         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1394         BMEdge *ee;
1395         BMIter iter;
1396         int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1397         int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1398
1399         BM_ElemIndex_Ensure(bm, BM_VERT);
1400
1401         ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1402         for( ; ee; ee=BMIter_Step(&iter), edge_r++) {
1403                 if (has_bweight) {
1404                         edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f);
1405                 }
1406
1407                 if (has_crease) {
1408                         edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f);
1409                 }
1410
1411                 edge_r->flag = BMFlags_To_MEFlags(ee);
1412
1413                 edge_r->v1 = (int)BM_GetIndex(ee->v1);
1414                 edge_r->v2 = (int)BM_GetIndex(ee->v2);
1415         }
1416 }
1417
1418 static void bmDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
1419 {
1420         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1421         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1422         BMFace *ef;
1423         BMLoop **l;
1424         int i;
1425
1426         BM_ElemIndex_Ensure(bm, BM_VERT);
1427
1428         for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
1429                 l = bmdm->tc->looptris[i];
1430                 ef = l[0]->f;
1431
1432                 face_r->mat_nr = (unsigned char) ef->mat_nr;
1433
1434                 face_r->flag = BMFlags_To_MEFlags(ef);
1435
1436                 face_r->v1 = BM_GetIndex(l[0]->v);
1437                 face_r->v2 = BM_GetIndex(l[1]->v);
1438                 face_r->v3 = BM_GetIndex(l[2]->v);
1439                 face_r->v4 = 0;
1440
1441                 test_index_face(face_r, NULL, 0, 3);
1442         }
1443 }
1444
1445
1446 static void bmDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1447 {
1448         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1449         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1450         BMIter iter, liter;
1451         BMFace *f;
1452         BMLoop *l;
1453
1454         BM_ElemIndex_Ensure(bm, BM_VERT | BM_EDGE);
1455
1456         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1457                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
1458                         loop_r->v = BM_GetIndex(l->v);
1459                         loop_r->e = BM_GetIndex(l->e);
1460                         loop_r++;
1461                 }
1462         }
1463 }
1464
1465 static void bmDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1466 {
1467         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1468         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1469         BMIter iter;
1470         BMFace *f;
1471         int i;
1472
1473         i = 0;
1474         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1475                 poly_r->flag = BMFlags_To_MEFlags(f);
1476                 poly_r->loopstart = i;
1477                 poly_r->totloop = f->len;
1478                 poly_r->mat_nr = f->mat_nr;
1479
1480                 poly_r++;
1481                 i += f->len;
1482         }
1483 }
1484
1485 static void *bmDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1486 {
1487         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1488         BMesh *bm= bmdm->tc->bm;
1489         BMFace *efa;
1490         char *data, *bmdata;
1491         void *datalayer;
1492         int index /*, offset*/ /*UNUSED */, size, i;
1493
1494         datalayer = DM_get_tessface_data_layer(dm, type);
1495         if(datalayer)
1496                 return datalayer;
1497
1498         /* layers are store per face for editmesh, we convert to a tbmporary
1499          * data layer array in the derivedmesh when these are requested */
1500         if(type == CD_MTFACE || type == CD_MCOL) {
1501                 index = CustomData_get_layer_index(&bm->pdata, type);
1502
1503                 if(index != -1) {
1504                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1505                         size = CustomData_sizeof(type);
1506
1507                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1508                         index = CustomData_get_layer_index(&dm->faceData, type);
1509                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1510
1511                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1512                         for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
1513                                 efa = bmdm->tc->looptris[i][0]->f;
1514                                 /*BMESH_TODO: need to still add tface data,
1515                                   derived from the loops.*/
1516                                 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
1517                                 memcpy(data, bmdata, size);
1518                         }
1519                 }
1520         }
1521
1522         return datalayer;
1523 }
1524
1525 static void bmDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1526 {
1527         EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1528         BMVert *eve;
1529         BMIter iter;
1530         int i;
1531
1532         i= 0;
1533         BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
1534                 if (emdm->vertexCos) {
1535                         copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1536                 } else {
1537                         copy_v3_v3(cos_r[i], eve->co);
1538                 }
1539                 
1540                 i++;
1541         }
1542 }
1543
1544 static void bmDM_release(DerivedMesh *dm)
1545 {
1546         EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1547
1548         if (DM_release(dm)) {
1549                 if (bmdm->vertexCos) {
1550                         MEM_freeN(bmdm->vertexCos);
1551                         MEM_freeN(bmdm->vertexNos);
1552                         MEM_freeN(bmdm->faceNos);
1553                 }
1554                 
1555                 if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
1556                 if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
1557                 if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
1558
1559                 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
1560                 if (bmdm->etable) MEM_freeN(bmdm->etable);
1561                 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
1562                 
1563                 MEM_freeN(bmdm);
1564         }
1565 }
1566
1567 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1568 {
1569         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1570
1571         return &bmdm->tc->bm->vdata;
1572 }
1573
1574 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1575 {
1576         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1577
1578         return &bmdm->tc->bm->edata;
1579 }
1580
1581 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1582 {
1583         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1584
1585         return &bmdm->dm.faceData;
1586 }
1587
1588 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1589 {
1590         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1591
1592         return &bmdm->tc->bm->ldata;
1593 }
1594
1595 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1596 {
1597         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1598
1599         return &bmdm->tc->bm->pdata;
1600 }
1601
1602
1603 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, 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 = bmDM_getVertCos;
1617         bmdm->dm.getMinMax = bmDM_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 = bmDM_getNumVerts;
1626         bmdm->dm.getNumEdges = bmDM_getNumEdges;
1627         bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces;
1628         bmdm->dm.getNumPolys = bmDM_getNumPolys;
1629
1630         bmdm->dm.getVert = bmDM_getVert;
1631         bmdm->dm.getEdge = bmDM_getEdge;
1632         bmdm->dm.getTessFace = bmDM_getTessFace;
1633         bmdm->dm.copyVertArray = bmDM_copyVertArray;
1634         bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray;
1635         bmdm->dm.copyTessFaceArray = bmDM_copyTessFaceArray;
1636         bmdm->dm.copyLoopArray = bmDM_copyLoopArray;
1637         bmdm->dm.copyPolyArray = bmDM_copyPolyArray;
1638
1639         bmdm->dm.getTessFaceDataArray = bmDM_getTessFaceDataArray;
1640
1641         bmdm->dm.calcNormals = bmDM_calcNormals;
1642         bmdm->dm.recalcTesselation = bmDM_recalcTesselation;
1643
1644         bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert;
1645         bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge;
1646         bmdm->dm.foreachMappedFaceCenter = bmDM_foreachMappedFaceCenter;
1647
1648         bmdm->dm.drawEdges = bmDM_drawEdges;
1649         bmdm->dm.drawMappedEdges = bmDM_drawMappedEdges;
1650         bmdm->dm.drawMappedEdgesInterp = bmDM_drawMappedEdgesInterp;
1651         bmdm->dm.drawMappedFaces = bmDM_drawMappedFaces;
1652         bmdm->dm.drawMappedFacesTex = bmDM_drawMappedFacesTex;
1653         bmdm->dm.drawMappedFacesGLSL = bmDM_drawMappedFacesGLSL;
1654         bmdm->dm.drawMappedFacesMat = bmDM_drawMappedFacesMat;
1655         bmdm->dm.drawFacesTex = bmDM_drawFacesTex;
1656         bmdm->dm.drawFacesGLSL = bmDM_drawFacesGLSL;
1657         bmdm->dm.drawUVEdges = bmDM_drawUVEdges;
1658
1659         bmdm->dm.release = bmDM_release;
1660         
1661         bmdm->vertexCos = vertexCos;
1662
1663         if(CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1664                 BMIter iter;
1665                 BMVert *eve;
1666                 int i;
1667
1668                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1669                 
1670                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1671                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1672                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1673                                          CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1674         }
1675
1676         if(vertexCos) {
1677                 BMVert *eve;
1678                 BMIter iter;
1679                 int totface = bmdm->tc->tottri;
1680                 int i;
1681
1682                 BM_ElemIndex_Ensure(bm, BM_VERT);
1683
1684                 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
1685                 bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
1686
1687                 for (i=0; i<bmdm->tc->tottri; i++) {
1688                         BMLoop **l = bmdm->tc->looptris[i];
1689                         float *v1 = vertexCos[(int) BM_GetIndex(l[0]->v)];
1690                         float *v2 = vertexCos[(int) BM_GetIndex(l[1]->v)];
1691                         float *v3 = vertexCos[(int) BM_GetIndex(l[2]->v)];
1692                         float *no = bmdm->faceNos[i];
1693                         
1694                         normal_tri_v3( no,v1, v2, v3);
1695                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[0]->v)], bmdm->vertexNos[BM_GetIndex(l[0]->v)], no);
1696                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[1]->v)], bmdm->vertexNos[BM_GetIndex(l[1]->v)], no);
1697                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[2]->v)], bmdm->vertexNos[BM_GetIndex(l[2]->v)], no);
1698                 }
1699
1700                 eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1701                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1702                         float *no = bmdm->vertexNos[i];
1703                         /* following Mesh convention; we use vertex coordinate itself
1704                          * for normal in this case */
1705                         if (normalize_v3(no)==0.0) {
1706                                 copy_v3_v3(no, vertexCos[i]);
1707                                 normalize_v3(no);
1708                         }
1709                 }
1710         }
1711
1712         //bmdm_recalc_lookups(bmdm);
1713
1714         return (DerivedMesh*) bmdm;
1715 }