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