svn merge ^/trunk/blender -r42521:42550
[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                                 l->_index = j;
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 (l1->_index > l2->_index) { SWAP(BMLoop*, l1, l2); }
202                                 if (l2->_index > l3->_index) { SWAP(BMLoop*, l2, l3); }
203                                 if (l1->_index > l2->_index) { 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         em->retopo_paint_data= NULL;
275
276         if (em->looptris) MEM_freeN(em->looptris);
277
278         if (em->vert_index) MEM_freeN(em->vert_index);
279         if (em->edge_index) MEM_freeN(em->edge_index);
280         if (em->face_index) MEM_freeN(em->face_index);
281
282         if (em->bm)
283                 BM_Free_Mesh(em->bm);
284 }
285
286 /*
287 ok, basic design:
288
289 the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
290 to three loops per triangle.  the derivedmesh stores a cache of tesselations
291 for each face.  this cache will smartly update as needed (though at first
292 it'll simply be more brute force).  keeping track of face/edge counts may
293 be a small problbm.
294
295 this won't be the most efficient thing, considering that internal edges and
296 faces of tesselations are exposed.  looking up an edge by index in particular
297 is likely to be a little slow.
298 */
299
300 typedef struct EditDerivedBMesh {
301         DerivedMesh dm;
302
303         Object *ob;
304         BMEditMesh *tc;
305
306         float (*vertexCos)[3];
307         float (*vertexNos)[3];
308         float (*faceNos)[3];
309
310         /*lookup caches; these are rebuilt on dm->RecalcTesselation()
311           (or when the derivedmesh is created, of course)*/
312         GHash *vhash, *ehash, *fhash;
313         BMVert **vtable;
314         BMEdge **etable;
315         BMFace **ftable;
316
317         /*private variables, for number of verts/edges/faces
318           within the above hash/table members*/
319         int tv, te, tf;
320 } EditDerivedBMesh;
321
322 static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
323 {
324         BMIter iter;
325         BMHeader *h;
326         int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
327
328         bmdm->tv = bmdm->tc->bm->totvert;
329         bmdm->te = bmdm->tc->bm->totedge;
330         bmdm->tf = bmdm->tc->bm->totface;
331
332         if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
333         if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
334         if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
335
336         bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
337         bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
338         bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh derived");
339
340         if (bmdm->vtable) MEM_freeN(bmdm->vtable);
341         if (bmdm->etable) MEM_freeN(bmdm->etable);
342         if (bmdm->ftable) MEM_freeN(bmdm->ftable);
343
344         if (bmdm->tc->bm->totvert)
345                 bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
346         else bmdm->vtable = NULL;
347
348         if (bmdm->tc->bm->totedge)
349                 bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
350         else bmdm->etable = NULL;
351
352         if (bmdm->tc->bm->totface)
353                 bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
354         else bmdm->ftable = NULL;
355
356         for (a=0; a<3; a++) {
357                 h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
358                 for (i=0; h; h=BMIter_Step(&iter), i++) {
359                         switch (a) {
360                                 case 0:
361                                         bmdm->vtable[i] = (BMVert*) h;
362                                         BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i));
363                                         break;
364                                 case 1:
365                                         bmdm->etable[i] = (BMEdge*) h;
366                                         BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i));
367                                         break;
368                                 case 2:
369                                         bmdm->ftable[i] = (BMFace*) h;
370                                         BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i));
371                                         break;
372
373                         }
374                 }
375         }
376 }
377
378 static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
379 {
380         /* Nothing to do: normals are already calculated and stored on the
381            BMVerts and BMFaces */
382 }
383
384 static void emDM_recalcTesselation(DerivedMesh *UNUSED(dm))
385 {
386         //EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
387
388         //bmdm_recalc_lookups(bmdm);
389 }
390
391 static void emDM_foreachMappedVert(
392                 DerivedMesh *dm,
393                 void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
394                 void *userData)
395 {
396         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
397         BMVert *eve;
398         BMIter iter;
399         int i;
400
401         eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
402         for (i=0; eve; i++, eve=BMIter_Step(&iter)) {
403                 if (bmdm->vertexCos) {
404                         func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
405                 }
406                 else {
407                         func(userData, i, eve->co, eve->no, NULL);
408                 }
409         }
410 }
411 static void emDM_foreachMappedEdge(
412                 DerivedMesh *dm,
413                 void (*func)(void *userData, int index, float *v0co, float *v1co),
414                 void *userData)
415 {
416         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
417         BMEdge *eed;
418         BMIter iter;
419         int i;
420
421         if (bmdm->vertexCos) {
422
423                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
424
425                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
426                 for (i=0; eed; i++,eed=BMIter_Step(&iter))
427                         func(userData, i,
428                                  bmdm->vertexCos[BM_GetIndex(eed->v1)],
429                                  bmdm->vertexCos[BM_GetIndex(eed->v2)]);
430         }
431         else {
432                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
433                 for (i=0; eed; i++,eed=BMIter_Step(&iter))
434                         func(userData, i, eed->v1->co, eed->v2->co);
435         }
436 }
437
438 static void emDM_drawMappedEdges(
439                 DerivedMesh *dm,
440                 int (*setDrawOptions)(void *userData, int index),
441                 void *userData)
442 {
443         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
444         BMEdge *eed;
445         BMIter iter;
446         int i;
447
448         if (bmdm->vertexCos) {
449
450                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
451
452                 glBegin(GL_LINES);
453                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
454                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
455                         if (!setDrawOptions || setDrawOptions(userData, i)) {
456                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v1)]);
457                                 glVertex3fv(bmdm->vertexCos[BM_GetIndex(eed->v2)]);
458                         }
459                 }
460                 glEnd();
461         }
462         else {
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(eed->v1->co);
468                                 glVertex3fv(eed->v2->co);
469                         }
470                 }
471                 glEnd();
472         }
473 }
474 static void emDM_drawEdges(
475                 DerivedMesh *dm,
476                 int UNUSED(drawLooseEdges),
477                 int UNUSED(drawAllEdges))
478 {
479         emDM_drawMappedEdges(dm, NULL, NULL);
480 }
481
482 static void emDM_drawMappedEdgesInterp(
483                 DerivedMesh *dm,
484                 int (*setDrawOptions)(void *userData, int index),
485                 void (*setDrawInterpOptions)(void *userData, int index, float t),
486                 void *userData)
487 {
488         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
489         BMEdge *eed;
490         BMIter iter;
491         int i;
492
493         if (bmdm->vertexCos) {
494
495                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
496
497                 glBegin(GL_LINES);
498                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
499                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
500                         if (!setDrawOptions || setDrawOptions(userData, i)) {
501                                 setDrawInterpOptions(userData, i, 0.0);
502                                 glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v1)]);
503                                 setDrawInterpOptions(userData, i, 1.0);
504                                 glVertex3fv(bmdm->vertexCos[(int) BM_GetIndex(eed->v2)]);
505                         }
506                 }
507                 glEnd();
508         }
509         else {
510                 glBegin(GL_LINES);
511                 eed = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
512                 for (i=0; eed; i++,eed=BMIter_Step(&iter)) {
513                         if (!setDrawOptions || setDrawOptions(userData, i)) {
514                                 setDrawInterpOptions(userData, i, 0.0);
515                                 glVertex3fv(eed->v1->co);
516                                 setDrawInterpOptions(userData, i, 1.0);
517                                 glVertex3fv(eed->v2->co);
518                         }
519                 }
520                 glEnd();
521         }
522 }
523
524 static void emDM_drawUVEdges(DerivedMesh *dm)
525 {
526         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
527         BMEditMesh *em = bmdm->tc;
528         BMFace *efa;
529         BMIter iter;
530
531         glBegin(GL_LINES);
532         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
533                 BMIter liter;
534                 BMLoop *l;
535                 MLoopUV *lastluv = NULL, *firstluv = NULL;
536
537                 if (BM_TestHFlag(efa, BM_HIDDEN))
538                         continue;
539
540                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
541                         MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
542
543                         if (luv) {
544                                 if (lastluv)
545                                         glVertex2fv(luv->uv);
546                                 glVertex2fv(luv->uv);
547
548                                 lastluv = luv;
549                                 if (!firstluv)
550                                         firstluv = luv;
551                         }
552                 }
553
554                 if (lastluv) {
555                         glVertex2fv(lastluv->uv);
556                         glVertex2fv(firstluv->uv);
557                 }
558         }
559         glEnd();
560 }
561
562 static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3])
563 {
564         BMIter iter;
565         BMLoop *l;
566         int tot = 0;
567
568         zero_v3(cent);
569
570         /*simple (and stupid) median (average) based method :/ */
571
572         if (vertexCos) {
573                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
574                 for (; l; l=BMIter_Step(&iter)) {
575                         add_v3_v3(cent, vertexCos[BM_GetIndex(l->v)]);
576                         tot++;
577                 }
578         }
579         else {
580                 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
581                 for (; l; l=BMIter_Step(&iter)) {
582                         add_v3_v3(cent, l->v->co);
583                         tot++;
584                 }
585         }
586
587         if (tot==0) return;
588         mul_v3_fl(cent, 1.0f/(float)tot);
589 }
590
591 static void emDM_foreachMappedFaceCenter(
592                 DerivedMesh *dm,
593                 void (*func)(void *userData, int index, float *co, float *no),
594                 void *userData)
595 {
596         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
597         BMFace *efa;
598         BMIter iter;
599         float cent[3];
600         int i;
601
602         if (bmdm->vertexCos) {
603                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT);
604         }
605
606         efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
607         for (i=0; efa; efa=BMIter_Step(&iter), i++) {
608                 emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
609                 func(userData, i, cent, bmdm->vertexCos?bmdm->faceNos[i]:efa->no);
610         }
611 }
612
613 static void emDM_drawMappedFaces(
614                 DerivedMesh *dm,
615                 int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
616                 int (*setMaterial)(int, void *attribs),
617                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
618                 void *userData, int UNUSED(useColors))
619 {
620         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
621         BMFace *efa;
622         struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
623         const int tottri= bmdm->tc->tottri;
624         const int lasttri= tottri - 1; /* compare agasint this a lot */
625         int i, draw, flush;
626         const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
627
628         /* GL_ZERO is used to detect if drawing has started or not */
629         GLenum poly_prev= GL_ZERO;
630         GLenum shade_prev= GL_ZERO;
631
632         (void)setMaterial; /* UNUSED */
633
634         /* currently unused -- each original face is handled separately */
635         (void)compareDrawOptions;
636
637         if (bmdm->vertexCos) {
638                 /* add direct access */
639                 float (*vertexCos)[3]= bmdm->vertexCos;
640                 float (*vertexNos)[3]= bmdm->vertexNos;
641                 float (*faceNos)[3]=   bmdm->faceNos;
642
643                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
644
645                 for (i=0; i < tottri; i++) {
646                         BMLoop **l = looptris[i];
647                         int drawSmooth;
648
649                         efa = l[0]->f;
650                         drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
651
652                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
653                         if (draw) {
654                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
655                                 if (draw==2) { /* enabled with stipple */
656
657                                         if (poly_prev != GL_ZERO) glEnd();
658                                         poly_prev= GL_ZERO; /* force glBegin */
659
660                                         glEnable(GL_POLYGON_STIPPLE);
661                                         glPolygonStipple(stipple_quarttone);
662                                 }
663
664                                 if (skip_normals) {
665                                         if (poly_type != poly_prev) {
666                                                 if (poly_prev != GL_ZERO) glEnd();
667                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
668                                         }
669                                         glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]);
670                                         glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]);
671                                         glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]);
672                                 }
673                                 else {
674                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
675                                         if (shade_type != shade_prev) {
676                                                 if (poly_prev != GL_ZERO) glEnd();
677                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
678                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
679                                         }
680                                         if (poly_type != poly_prev) {
681                                                 if (poly_prev != GL_ZERO) glEnd();
682                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
683                                         }
684
685                                         if (!drawSmooth) {
686                                                 glNormal3fv(faceNos[i]);
687                                                 glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]);
688                                                 glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]);
689                                                 glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]);
690                                         }
691                                         else {
692                                                 glNormal3fv(vertexNos[(int) BM_GetIndex(l[0]->v)]);
693                                                 glVertex3fv(vertexCos[(int) BM_GetIndex(l[0]->v)]);
694                                                 glNormal3fv(vertexNos[(int) BM_GetIndex(l[1]->v)]);
695                                                 glVertex3fv(vertexCos[(int) BM_GetIndex(l[1]->v)]);
696                                                 glNormal3fv(vertexNos[(int) BM_GetIndex(l[2]->v)]);
697                                                 glVertex3fv(vertexCos[(int) BM_GetIndex(l[2]->v)]);
698                                         }
699                                 }
700
701                                 flush= (draw==2);
702                                 if (!skip_normals && !flush && (i != lasttri))
703                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
704
705                                 if (flush) {
706                                         glEnd();
707                                         poly_prev= GL_ZERO; /* force glBegin */
708
709                                         glDisable(GL_POLYGON_STIPPLE);
710                                 }
711                         }
712                 }
713         }
714         else {
715                 BM_ElemIndex_Ensure(bmdm->tc->bm, BM_FACE);
716
717                 for (i=0; i < tottri; i++) {
718                         BMLoop **l = looptris[i];
719                         int drawSmooth;
720
721                         efa = l[0]->f;
722                         drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
723
724                         draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_GetIndex(efa), &drawSmooth);
725                         if (draw) {
726                                 const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
727                                 if (draw==2) { /* enabled with stipple */
728
729                                         if (poly_prev != GL_ZERO) glEnd();
730                                         poly_prev= GL_ZERO; /* force glBegin */
731
732                                         glEnable(GL_POLYGON_STIPPLE);
733                                         glPolygonStipple(stipple_quarttone);
734                                 }
735
736                                 if (skip_normals) {
737                                         if (poly_type != poly_prev) {
738                                                 if (poly_prev != GL_ZERO) glEnd();
739                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
740                                         }
741                                         glVertex3fv(l[0]->v->co);
742                                         glVertex3fv(l[1]->v->co);
743                                         glVertex3fv(l[2]->v->co);
744                                 }
745                                 else {
746                                         const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
747                                         if (shade_type != shade_prev) {
748                                                 if (poly_prev != GL_ZERO) glEnd();
749                                                 glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
750                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
751                                         }
752                                         if (poly_type != poly_prev) {
753                                                 if (poly_prev != GL_ZERO) glEnd();
754                                                 glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
755                                         }
756
757                                         if (!drawSmooth) {
758                                                 glNormal3fv(efa->no);
759                                                 glVertex3fv(l[0]->v->co);
760                                                 glVertex3fv(l[1]->v->co);
761                                                 glVertex3fv(l[2]->v->co);
762                                         }
763                                         else {
764                                                 glNormal3fv(l[0]->v->no);
765                                                 glVertex3fv(l[0]->v->co);
766                                                 glNormal3fv(l[1]->v->no);
767                                                 glVertex3fv(l[1]->v->co);
768                                                 glNormal3fv(l[2]->v->no);
769                                                 glVertex3fv(l[2]->v->co);
770                                         }
771                                 }
772
773                                 flush= (draw==2);
774                                 if (!skip_normals && !flush && (i != lasttri)) {
775                                         flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
776                                 }
777
778                                 if (flush) {
779                                         glEnd();
780                                         poly_prev= GL_ZERO; /* force glBegin */
781
782                                         glDisable(GL_POLYGON_STIPPLE);
783                                 }
784                         }
785                 }
786         }
787
788         /* if non zero we know a face was rendered */
789         if (poly_prev != GL_ZERO) glEnd();
790 }
791
792 static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
793                                  int has_uv, int has_col)
794 {
795         if (has_uv) {
796                 luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
797                 luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
798                 luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
799         }
800
801         if (has_col) {
802                 lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
803                 lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
804                 lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
805         }
806
807
808 }
809
810 static void emDM_drawFacesTex_common(
811                 DerivedMesh *dm,
812                 int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
813                 int (*drawParamsMapped)(void *userData, int index),
814                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
815                 void *userData)
816 {
817         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
818         BMEditMesh *em = bmdm->tc;
819         BMesh *bm= bmdm->tc->bm;
820         float (*vertexCos)[3]= bmdm->vertexCos;
821         float (*vertexNos)[3]= bmdm->vertexNos;
822         BMFace *efa;
823         MLoopUV *luv[3], dummyluv = {{0}};
824         MLoopCol *lcol[3], dummylcol = {0};
825         int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
826         int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
827
828         (void) compareDrawOptions;
829
830         luv[0] = luv[1] = luv[2] = &dummyluv;
831         lcol[0] = lcol[1] = lcol[2] = &dummylcol;
832
833         dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
834
835         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
836         glShadeModel(GL_SMOOTH);
837
838         BM_ElemIndex_Ensure(bm, BM_FACE);
839
840         if (vertexCos) {
841                 BM_ElemIndex_Ensure(bm, BM_VERT);
842
843                 glBegin(GL_TRIANGLES);
844                 for (i=0; i<em->tottri; i++) {
845                         BMLoop **ls = em->looptris[i];
846                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
847                         MTFace mtf = {{{0}}};
848                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
849                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
850                         int flag;
851
852                         efa = ls[0]->f;
853
854                         if (has_uv) {
855                                 mtf.flag = tp->flag;
856                                 mtf.tpage = tp->tpage;
857                                 mtf.transp = tp->transp;
858                                 mtf.mode = tp->mode;
859                                 mtf.tile = tp->tile;
860                                 mtf.unwrap = tp->unwrap;
861                         }
862
863                         if (drawParams)
864                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
865                         else if (drawParamsMapped)
866                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
867                         else
868                                 flag= 1;
869
870                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
871
872                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
873                                 if (!has_vcol) {
874                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
875                                 }
876
877                                 if (!drawSmooth) {
878                                         glNormal3fv(bmdm->faceNos[i]);
879
880                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
881
882                                         glTexCoord2fv(luv[0]->uv);
883                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
884                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
885
886                                         glTexCoord2fv(luv[1]->uv);
887                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
888                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
889
890                                         glTexCoord2fv(luv[2]->uv);
891                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
892                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
893                                 }
894                                 else {
895                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
896
897                                         glTexCoord2fv(luv[0]->uv);
898                                         glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
899                                         glNormal3fv(vertexNos[BM_GetIndex(ls[0]->v)]);
900                                         glVertex3fv(vertexCos[BM_GetIndex(ls[0]->v)]);
901
902                                         glTexCoord2fv(luv[1]->uv);
903                                         glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
904                                         glNormal3fv(vertexNos[BM_GetIndex(ls[1]->v)]);
905                                         glVertex3fv(vertexCos[BM_GetIndex(ls[1]->v)]);
906
907                                         glTexCoord2fv(luv[2]->uv);
908                                         glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
909                                         glNormal3fv(vertexNos[BM_GetIndex(ls[2]->v)]);
910                                         glVertex3fv(vertexCos[BM_GetIndex(ls[2]->v)]);
911                                 }
912                         }
913                 }
914                 glEnd();
915         }
916         else {
917                 BM_ElemIndex_Ensure(bm, BM_VERT);
918
919                 for (i=0; i<em->tottri; i++) {
920                         BMLoop **ls = em->looptris[i];
921                         MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
922                         MTFace mtf = {{{0}}};
923                         /*unsigned char *cp= NULL;*/ /*UNUSED*/
924                         int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
925                         int flag;
926
927                         efa = ls[0]->f;
928
929                         if (has_uv) {
930                                 mtf.flag = tp->flag;
931                                 mtf.tpage = tp->tpage;
932                                 mtf.transp = tp->transp;
933                                 mtf.mode = tp->mode;
934                                 mtf.tile = tp->tile;
935                                 mtf.unwrap = tp->unwrap;
936                         }
937
938                         if (drawParams)
939                                 flag= drawParams(&mtf, has_vcol, efa->mat_nr);
940                         else if (drawParamsMapped)
941                                 flag= drawParamsMapped(userData, BM_GetIndex(efa));
942                         else
943                                 flag= 1;
944
945                         if (flag != 0) { /* flag 0 == the face is hidden or invisible */
946
947                                 /* we always want smooth here since otherwise vertex colors dont interpolate */
948                                 if (!has_vcol) {
949                                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
950                                 }
951
952                                 glBegin(GL_TRIANGLES);
953                                 if (!drawSmooth) {
954                                         glNormal3fv(efa->no);
955
956                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
957
958                                         if (luv[0])
959                                                 glTexCoord2fv(luv[0]->uv);
960                                         if (lcol[0])
961                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
962                                         else glColor3ub(0, 0, 0);
963                                         glVertex3fv(ls[0]->v->co);
964
965                                         if (luv[1])
966                                                 glTexCoord2fv(luv[1]->uv);
967                                         if (lcol[1])
968                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
969                                         else glColor3ub(0, 0, 0);
970                                         glVertex3fv(ls[1]->v->co);
971
972                                         if (luv[2])
973                                                 glTexCoord2fv(luv[2]->uv);
974                                         if (lcol[2])
975                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
976                                         else glColor3ub(0, 0, 0);
977                                         glVertex3fv(ls[2]->v->co);
978                                 }
979                                 else {
980                                         bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
981
982                                         if (luv[0])
983                                                 glTexCoord2fv(luv[0]->uv);
984                                         if (lcol[0])
985                                                 glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
986                                         else glColor3ub(0, 0, 0);
987                                         glNormal3fv(ls[0]->v->no);
988                                         glVertex3fv(ls[0]->v->co);
989
990                                         if (luv[1])
991                                                 glTexCoord2fv(luv[1]->uv);
992                                         if (lcol[1])
993                                                 glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
994                                         else glColor3ub(0, 0, 0);
995                                         glNormal3fv(ls[1]->v->no);
996                                         glVertex3fv(ls[1]->v->co);
997
998                                         if (luv[2])
999                                                 glTexCoord2fv(luv[2]->uv);
1000                                         if (lcol[2])
1001                                                 glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
1002                                         else glColor3ub(0, 0, 0);
1003                                         glNormal3fv(ls[2]->v->no);
1004                                         glVertex3fv(ls[2]->v->co);
1005                                 }
1006                                 glEnd();
1007                         }
1008                 }
1009         }
1010 }
1011
1012 static void emDM_drawFacesTex(
1013                 DerivedMesh *dm,
1014                 int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr),
1015                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1016                 void *userData)
1017 {
1018         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
1019 }
1020
1021 static void emDM_drawMappedFacesTex(
1022                 DerivedMesh *dm,
1023                 int (*setDrawOptions)(void *userData, int index),
1024                 int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
1025                 void *userData)
1026 {
1027         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
1028 }
1029
1030 static void emDM_drawMappedFacesGLSL(
1031                 DerivedMesh *dm,
1032                 int (*setMaterial)(int, void *attribs),
1033                 int (*setDrawOptions)(void *userData, int index),
1034                 void *userData)
1035 {
1036         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1037         BMesh *bm= bmdm->tc->bm;
1038         BMEditMesh *em = bmdm->tc;
1039         float (*vertexCos)[3]= bmdm->vertexCos;
1040         float (*vertexNos)[3]= bmdm->vertexNos;
1041         BMFace *efa;
1042         BMLoop **ltri;
1043         DMVertexAttribs attribs;
1044         GPUVertexAttribs gattribs;
1045
1046         int i, b, matnr, new_matnr, dodraw;
1047
1048         dodraw = 0;
1049         matnr = -1;
1050
1051         memset(&attribs, 0, sizeof(attribs));
1052
1053         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1054         glShadeModel(GL_SMOOTH);
1055         BM_ElemIndex_Ensure(bm, BM_VERT | BM_FACE);
1056
1057 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1058         if (attribs.totorco) {                                                                                                          \
1059                 float *orco = attribs.orco.array[BM_GetIndex(eve)];                                             \
1060                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
1061         }                                                                                                                                                       \
1062         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1063                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1064                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
1065         }                                                                                                                                                       \
1066         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
1067                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1068                 GLubyte _col[4];                                                                                                                \
1069                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
1070                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
1071         }                                                                                                                                                       \
1072         if (attribs.tottang) {                                                                                                          \
1073                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
1074                 glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
1075         }                                                                                                                                                       \
1076         }
1077
1078
1079         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1080                 int drawSmooth;
1081
1082                 efa = ltri[0]->f;
1083                 drawSmooth= BM_TestHFlag(efa, BM_SMOOTH);
1084
1085                 if (setDrawOptions && !setDrawOptions(userData, BM_GetIndex(efa)))
1086                         continue;
1087
1088                 new_matnr = efa->mat_nr + 1;
1089                 if (new_matnr != matnr) {
1090                         dodraw = setMaterial(matnr = new_matnr, &gattribs);
1091                         if (dodraw)
1092                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1093                 }
1094
1095                 if (dodraw) {
1096                         glBegin(GL_TRIANGLES);
1097                         if (!drawSmooth) {
1098                                 if (vertexCos) glNormal3fv(bmdm->faceNos[i]);
1099                                 else glNormal3fv(efa->no);
1100
1101                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1102                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1103                                 else glVertex3fv(ltri[0]->v->co);
1104
1105                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1106                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1107                                 else glVertex3fv(ltri[1]->v->co);
1108
1109                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1110                                 if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1111                                 else glVertex3fv(ltri[2]->v->co);
1112                         }
1113                         else {
1114                                 PASSATTRIB(ltri[0], ltri[0]->v, 0);
1115                                 if (vertexCos) {
1116                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1117                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1118                                 }
1119                                 else {
1120                                         glNormal3fv(ltri[0]->v->no);
1121                                         glVertex3fv(ltri[0]->v->co);
1122                                 }
1123
1124                                 PASSATTRIB(ltri[1], ltri[1]->v, 1);
1125                                 if (vertexCos) {
1126                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1127                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1128                                 }
1129                                 else {
1130                                         glNormal3fv(ltri[1]->v->no);
1131                                         glVertex3fv(ltri[1]->v->co);
1132                                 }
1133
1134                                 PASSATTRIB(ltri[2], ltri[2]->v, 2);
1135                                 if (vertexCos) {
1136                                         glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1137                                         glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1138                                 }
1139                                 else {
1140                                         glNormal3fv(ltri[2]->v->no);
1141                                         glVertex3fv(ltri[2]->v->co);
1142                                 }
1143                         }
1144                         glEnd();
1145                 }
1146         }
1147 #undef PASSATTRIB
1148 }
1149
1150 static void emDM_drawFacesGLSL(
1151                 DerivedMesh *dm,
1152                 int (*setMaterial)(int, void *attribs))
1153 {
1154         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1155 }
1156
1157 static void emDM_drawMappedFacesMat(
1158                 DerivedMesh *dm,
1159                 void (*setMaterial)(void *userData, int, void *attribs),
1160                 int (*setFace)(void *userData, int index), void *userData)
1161 {
1162         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1163         BMesh *bm= bmdm->tc->bm;
1164         BMEditMesh *em = bmdm->tc;
1165         float (*vertexCos)[3]= bmdm->vertexCos;
1166         float (*vertexNos)[3]= bmdm->vertexNos;
1167         BMFace *efa;
1168         BMLoop **ltri;
1169         DMVertexAttribs attribs= {{{0}}};
1170         GPUVertexAttribs gattribs;
1171         int i, b, matnr, new_matnr;
1172
1173         matnr = -1;
1174
1175         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1176         glShadeModel(GL_SMOOTH);
1177
1178         BM_ElemIndex_Ensure(bm, BM_VERT);
1179
1180 #define PASSATTRIB(loop, eve, vert) {                                                                                   \
1181         if (attribs.totorco) {                                                                                                          \
1182                 float *orco = attribs.orco.array[BM_GetIndex(eve)];                                             \
1183                 glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
1184         }                                                                                                                                                       \
1185         for (b = 0; b < attribs.tottface; b++) {                                                                        \
1186                 MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
1187                 glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
1188         }                                                                                                                                                       \
1189         for (b = 0; b < attribs.totmcol; b++) {                                                                         \
1190                 MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
1191                 GLubyte _col[4];                                                                                                                \
1192                 _col[0]= _cp->b; _col[1]= _cp->g; _col[2]= _cp->r; _col[3]= _cp->a;             \
1193                 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, _col);                                   \
1194         }                                                                                                                                                       \
1195         if (attribs.tottang) {                                                                                                          \
1196                 float *tang = attribs.tang.array[i*4 + vert];                                                   \
1197                 glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
1198         }                                                                                                                                                       \
1199 }
1200
1201         for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
1202                 int drawSmooth;
1203
1204                 efa = ltri[0]->f;
1205                 drawSmooth = BM_TestHFlag(efa, BM_SMOOTH);
1206
1207                 /* face hiding */
1208                 if (setFace && !setFace(userData, BM_GetIndex(efa)))
1209                         continue;
1210
1211                 /* material */
1212                 new_matnr = efa->mat_nr + 1;
1213                 if (new_matnr != matnr) {
1214                         setMaterial(userData, matnr = new_matnr, &gattribs);
1215                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1216                 }
1217
1218                 /* face */
1219                 glBegin(GL_TRIANGLES);
1220                 if (!drawSmooth) {
1221                         if (vertexCos) glNormal3fv(bmdm->faceNos[i]);
1222                         else glNormal3fv(efa->no);
1223
1224                         PASSATTRIB(ltri[0], ltri[0]->v, 0);
1225                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1226                         else glVertex3fv(ltri[0]->v->co);
1227
1228                         PASSATTRIB(ltri[1], ltri[1]->v, 1);
1229                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1230                         else glVertex3fv(ltri[1]->v->co);
1231
1232                         PASSATTRIB(ltri[2], ltri[2]->v, 2);
1233                         if (vertexCos) glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1234                         else glVertex3fv(ltri[2]->v->co);
1235
1236                 }
1237                 else {
1238                         PASSATTRIB(ltri[0], ltri[0]->v, 0);
1239                         if (vertexCos) {
1240                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[0]->v)]);
1241                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[0]->v)]);
1242                         }
1243                         else {
1244                                 glNormal3fv(ltri[0]->v->no);
1245                                 glVertex3fv(ltri[0]->v->co);
1246                         }
1247
1248                         PASSATTRIB(ltri[1], ltri[1]->v, 1);
1249                         if (vertexCos) {
1250                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[1]->v)]);
1251                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[1]->v)]);
1252                         }
1253                         else {
1254                                 glNormal3fv(ltri[1]->v->no);
1255                                 glVertex3fv(ltri[1]->v->co);
1256                         }
1257
1258                         PASSATTRIB(ltri[2], ltri[2]->v, 2);
1259                         if (vertexCos) {
1260                                 glNormal3fv(vertexNos[BM_GetIndex(ltri[2]->v)]);
1261                                 glVertex3fv(vertexCos[BM_GetIndex(ltri[2]->v)]);
1262                         }
1263                         else {
1264                                 glNormal3fv(ltri[2]->v->no);
1265                                 glVertex3fv(ltri[2]->v->co);
1266                         }
1267                 }
1268                 glEnd();
1269         }
1270 #undef PASSATTRIB
1271 }
1272
1273 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1274 {
1275         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1276         BMVert *eve;
1277         BMIter iter;
1278         int i;
1279
1280         if (bmdm->tc->bm->totvert) {
1281                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1282                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1283                         if (bmdm->vertexCos) {
1284                                 DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
1285                         }
1286                         else {
1287                                 DO_MINMAX(eve->co, min_r, max_r);
1288                         }
1289                 }
1290         }
1291         else {
1292                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1293         }
1294 }
1295 static int emDM_getNumVerts(DerivedMesh *dm)
1296 {
1297         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1298
1299         return bmdm->tc->bm->totvert;
1300 }
1301
1302 static int emDM_getNumEdges(DerivedMesh *dm)
1303 {
1304         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1305
1306         return bmdm->tc->bm->totedge;
1307 }
1308
1309 static int emDM_getNumTessFaces(DerivedMesh *dm)
1310 {
1311         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1312
1313         return bmdm->tc->tottri;
1314 }
1315
1316 static int emDM_getNumLoops(DerivedMesh *dm)
1317 {
1318         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1319
1320         return bmdm->tc->bm->totloop;
1321 }
1322
1323 static int emDM_getNumPolys(DerivedMesh *dm)
1324 {
1325         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1326
1327         return bmdm->tc->bm->totface;
1328 }
1329
1330 static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
1331 {
1332         copy_v3_v3(vert_r->co, ev->co);
1333
1334         normal_float_to_short_v3(vert_r->no, ev->no);
1335
1336         vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1337
1338         if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1339                 vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1340         }
1341
1342         return 1;
1343 }
1344
1345 static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
1346 {
1347         BMVert *ev;
1348
1349         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
1350                 printf("error in emDM_getVert.\n");
1351                 return;
1352         }
1353
1354         ev = ((EditDerivedBMesh *)dm)->vtable[index];
1355         bmvert_to_mvert(((EditDerivedBMesh *)dm)->tc->bm, ev, vert_r);
1356 }
1357
1358 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
1359 {
1360         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1361         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1362         BMEdge *e;
1363
1364         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
1365                 printf("error in emDM_getEdge.\n");
1366                 return;
1367         }
1368
1369         e = bmdm->etable[index];
1370
1371         if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
1372                 edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_BWEIGHT)*255.0f);
1373         }
1374
1375         if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
1376                 edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, e, CD_CREASE)*255.0f);
1377         }
1378
1379         edge_r->flag = BM_Edge_Flag_To_MEFlag(e);
1380
1381         edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1));
1382         edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2));
1383 }
1384
1385 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
1386 {
1387         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1388         BMFace *ef;
1389         BMLoop **l;
1390
1391         if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
1392                 printf("error in emDM_getTessFace.\n");
1393                 return;
1394         }
1395
1396         l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
1397
1398         ef = l[0]->f;
1399
1400         face_r->mat_nr = (unsigned char) ef->mat_nr;
1401         face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1402
1403         face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v));
1404         face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v));
1405         face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v));
1406         face_r->v4 = 0;
1407
1408         test_index_face(face_r, NULL, 0, 3);
1409 }
1410
1411 static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
1412 {
1413         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1414         BMVert *ev;
1415         BMIter iter;
1416
1417         ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1418         for ( ; ev; ev = BMIter_Step(&iter), ++vert_r) {
1419                 copy_v3_v3(vert_r->co, ev->co);
1420
1421                 normal_float_to_short_v3(vert_r->no, ev->no);
1422
1423                 vert_r->flag = BM_Vert_Flag_To_MEFlag(ev);
1424
1425                 if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
1426                         vert_r->bweight = (unsigned char) (BM_GetCDf(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
1427                 }
1428         }
1429 }
1430
1431 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
1432 {
1433         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1434         BMEdge *ee;
1435         BMIter iter;
1436         int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
1437         int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
1438
1439         BM_ElemIndex_Ensure(bm, BM_VERT);
1440
1441         ee = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
1442         for ( ; ee; ee=BMIter_Step(&iter), edge_r++) {
1443                 if (has_bweight) {
1444                         edge_r->bweight = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_BWEIGHT)*255.0f);
1445                 }
1446
1447                 if (has_crease) {
1448                         edge_r->crease = (unsigned char) (BM_GetCDf(&bm->edata, ee, CD_CREASE)*255.0f);
1449                 }
1450
1451                 edge_r->flag = BM_Edge_Flag_To_MEFlag(ee);
1452
1453                 edge_r->v1 = (int)BM_GetIndex(ee->v1);
1454                 edge_r->v2 = (int)BM_GetIndex(ee->v2);
1455         }
1456 }
1457
1458 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
1459 {
1460         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1461         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1462         BMFace *ef;
1463         BMLoop **l;
1464         int i;
1465
1466         BM_ElemIndex_Ensure(bm, BM_VERT);
1467
1468         for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
1469                 l = bmdm->tc->looptris[i];
1470                 ef = l[0]->f;
1471
1472                 face_r->mat_nr = (unsigned char) ef->mat_nr;
1473
1474                 face_r->flag = BM_Face_Flag_To_MEFlag(ef);
1475
1476                 face_r->v1 = BM_GetIndex(l[0]->v);
1477                 face_r->v2 = BM_GetIndex(l[1]->v);
1478                 face_r->v3 = BM_GetIndex(l[2]->v);
1479                 face_r->v4 = 0;
1480
1481                 test_index_face(face_r, NULL, 0, 3);
1482         }
1483 }
1484
1485
1486 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
1487 {
1488         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1489         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1490         BMIter iter, liter;
1491         BMFace *f;
1492         BMLoop *l;
1493
1494         BM_ElemIndex_Ensure(bm, BM_VERT | BM_EDGE);
1495
1496         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1497                 BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
1498                         loop_r->v = BM_GetIndex(l->v);
1499                         loop_r->e = BM_GetIndex(l->e);
1500                         loop_r++;
1501                 }
1502         }
1503 }
1504
1505 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
1506 {
1507         /* EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; */ /* UNUSED */
1508         BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
1509         BMIter iter;
1510         BMFace *f;
1511         int i;
1512
1513         i = 0;
1514         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1515                 poly_r->flag = BM_Face_Flag_To_MEFlag(f);
1516                 poly_r->loopstart = i;
1517                 poly_r->totloop = f->len;
1518                 poly_r->mat_nr = f->mat_nr;
1519
1520                 poly_r++;
1521                 i += f->len;
1522         }
1523 }
1524
1525 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1526 {
1527         EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
1528         BMesh *bm= bmdm->tc->bm;
1529         BMFace *efa;
1530         char *data, *bmdata;
1531         void *datalayer;
1532         int index /*, offset*/ /*UNUSED */, size, i;
1533
1534         datalayer = DM_get_tessface_data_layer(dm, type);
1535         if (datalayer)
1536                 return datalayer;
1537
1538         /* layers are store per face for editmesh, we convert to a tbmporary
1539          * data layer array in the derivedmesh when these are requested */
1540         if (type == CD_MTFACE || type == CD_MCOL) {
1541                 index = CustomData_get_layer_index(&bm->pdata, type);
1542
1543                 if (index != -1) {
1544                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1545                         size = CustomData_sizeof(type);
1546
1547                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1548                         index = CustomData_get_layer_index(&dm->faceData, type);
1549                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1550
1551                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1552                         for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
1553                                 efa = bmdm->tc->looptris[i][0]->f;
1554                                 /*BMESH_TODO: need to still add tface data,
1555                                   derived from the loops.*/
1556                                 bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
1557                                 memcpy(data, bmdata, size);
1558                         }
1559                 }
1560         }
1561
1562         return datalayer;
1563 }
1564
1565 static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1566 {
1567         EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
1568         BMVert *eve;
1569         BMIter iter;
1570         int i;
1571
1572         i= 0;
1573         BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
1574                 if (emdm->vertexCos) {
1575                         copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
1576                 }
1577                 else {
1578                         copy_v3_v3(cos_r[i], eve->co);
1579                 }
1580
1581                 i++;
1582         }
1583 }
1584
1585 static void emDM_release(DerivedMesh *dm)
1586 {
1587         EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
1588
1589         if (DM_release(dm)) {
1590                 if (bmdm->vertexCos) {
1591                         MEM_freeN(bmdm->vertexCos);
1592                         MEM_freeN(bmdm->vertexNos);
1593                         MEM_freeN(bmdm->faceNos);
1594                 }
1595
1596                 if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
1597                 if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
1598                 if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
1599
1600                 if (bmdm->vtable) MEM_freeN(bmdm->vtable);
1601                 if (bmdm->etable) MEM_freeN(bmdm->etable);
1602                 if (bmdm->ftable) MEM_freeN(bmdm->ftable);
1603
1604                 MEM_freeN(bmdm);
1605         }
1606 }
1607
1608 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1609 {
1610         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1611
1612         return &bmdm->tc->bm->vdata;
1613 }
1614
1615 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1616 {
1617         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1618
1619         return &bmdm->tc->bm->edata;
1620 }
1621
1622 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1623 {
1624         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1625
1626         return &bmdm->dm.faceData;
1627 }
1628
1629 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1630 {
1631         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1632
1633         return &bmdm->tc->bm->ldata;
1634 }
1635
1636 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1637 {
1638         EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
1639
1640         return &bmdm->tc->bm->pdata;
1641 }
1642
1643
1644 DerivedMesh *getEditDerivedBMesh(
1645                 BMEditMesh *em,
1646                 Object *UNUSED(ob),
1647                 float (*vertexCos)[3])
1648 {
1649         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1650         BMesh *bm = em->bm;
1651
1652         bmdm->tc = em;
1653
1654         DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
1655                  em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
1656
1657         CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
1658
1659         bmdm->dm.getVertCos = emDM_getVertCos;
1660         bmdm->dm.getMinMax = emDM_getMinMax;
1661
1662         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1663         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1664         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1665         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1666         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1667
1668         bmdm->dm.getNumVerts = emDM_getNumVerts;
1669         bmdm->dm.getNumEdges = emDM_getNumEdges;
1670         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1671         bmdm->dm.getNumLoops = emDM_getNumLoops;
1672         bmdm->dm.getNumPolys = emDM_getNumPolys;
1673
1674         bmdm->dm.getVert = emDM_getVert;
1675         bmdm->dm.getEdge = emDM_getEdge;
1676         bmdm->dm.getTessFace = emDM_getTessFace;
1677         bmdm->dm.copyVertArray = emDM_copyVertArray;
1678         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1679         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1680         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1681         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1682
1683         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1684
1685         bmdm->dm.calcNormals = emDM_calcNormals;
1686         bmdm->dm.recalcTesselation = emDM_recalcTesselation;
1687
1688         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1689         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1690         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1691
1692         bmdm->dm.drawEdges = emDM_drawEdges;
1693         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1694         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1695         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1696         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1697         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1698         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1699         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1700         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1701         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1702
1703         bmdm->dm.release = emDM_release;
1704
1705         bmdm->vertexCos = vertexCos;
1706
1707         if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
1708                 BMIter iter;
1709                 BMVert *eve;
1710                 int i;
1711
1712                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1713
1714                 eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
1715                 for (i=0; eve; eve=BMIter_Step(&iter), i++)
1716                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1717                                                          CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
1718         }
1719
1720         if (vertexCos) {
1721                 BMVert *eve;
1722                 BMIter iter;
1723                 int totface = bmdm->tc->tottri;
1724                 int i;
1725
1726                 BM_ElemIndex_Ensure(bm, BM_VERT);
1727
1728                 bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
1729                 bmdm->faceNos = MEM_mallocN(sizeof(*bmdm->faceNos)*totface, "bmdm_vno");
1730
1731                 for (i=0; i<bmdm->tc->tottri; i++) {
1732                         BMLoop **l = bmdm->tc->looptris[i];
1733                         float *v1 = vertexCos[(int) BM_GetIndex(l[0]->v)];
1734                         float *v2 = vertexCos[(int) BM_GetIndex(l[1]->v)];
1735                         float *v3 = vertexCos[(int) BM_GetIndex(l[2]->v)];
1736                         float *no = bmdm->faceNos[i];
1737
1738                         normal_tri_v3( no,v1, v2, v3);
1739                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[0]->v)], bmdm->vertexNos[BM_GetIndex(l[0]->v)], no);
1740                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[1]->v)], bmdm->vertexNos[BM_GetIndex(l[1]->v)], no);
1741                         add_v3_v3v3(bmdm->vertexNos[BM_GetIndex(l[2]->v)], bmdm->vertexNos[BM_GetIndex(l[2]->v)], no);
1742                 }
1743
1744                 eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
1745                 for (i=0; eve; eve=BMIter_Step(&iter), i++) {
1746                         float *no = bmdm->vertexNos[i];
1747                         /* following Mesh convention; we use vertex coordinate itself
1748                          * for normal in this case */
1749                         if (normalize_v3(no)==0.0) {
1750                                 copy_v3_v3(no, vertexCos[i]);
1751                                 normalize_v3(no);
1752                         }
1753                 }
1754         }
1755
1756         //bmdm_recalc_lookups(bmdm);
1757
1758         return (DerivedMesh*) bmdm;
1759 }