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