Ghost Context Refactor
[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  * basic design:
32  *
33  * the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
34  * to three loops per triangle.  the derivedmesh stores a cache of tessellations
35  * for each face.  this cache will smartly update as needed (though at first
36  * it'll simply be more brute force).  keeping track of face/edge counts may
37  * be a small problem.
38  *
39  * this won't be the most efficient thing, considering that internal edges and
40  * faces of tessellations are exposed.  looking up an edge by index in particular
41  * is likely to be a little slow.
42  */
43
44 #include "BLI_math.h"
45 #include "BLI_jitter.h"
46 #include "BLI_bitmap.h"
47
48 #include "BKE_cdderivedmesh.h"
49 #include "BKE_mesh.h"
50 #include "BKE_editmesh.h"
51 #include "BKE_editmesh_bvh.h"
52
53 #include "DNA_scene_types.h"
54 #include "DNA_object_types.h"
55
56 #include "MEM_guardedalloc.h"
57
58 #include "GPU_extensions.h"
59 #include "GPU_glew.h"
60
61 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
62
63 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]);
64
65 typedef struct EditDerivedBMesh {
66         DerivedMesh dm;
67
68         BMEditMesh *em;
69
70         /** when set, \a vertexNos, polyNos are lazy initialized */
71         const float (*vertexCos)[3];
72
73         /** lazy initialize (when \a vertexCos is set) */
74         float const (*vertexNos)[3];
75         float const (*polyNos)[3];
76         /** also lazy init but dont depend on \a vertexCos */
77         const float (*polyCos)[3];
78 } EditDerivedBMesh;
79
80 /* -------------------------------------------------------------------- */
81 /* Lazy initialize datastructures */
82
83 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm);
84
85 static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm)
86 {
87         if (bmdm->vertexCos && (bmdm->vertexNos == NULL)) {
88
89                 BMesh *bm = bmdm->em->bm;
90                 const float (*vertexCos)[3], (*polyNos)[3];
91                 float (*vertexNos)[3];
92
93                 /* calculate vertex normals from poly normals */
94                 emDM_ensurePolyNormals(bmdm);
95
96                 BM_mesh_elem_index_ensure(bm, BM_FACE);
97
98                 polyNos = bmdm->polyNos;
99                 vertexCos = bmdm->vertexCos;
100                 vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__);
101
102                 BM_verts_calc_normal_vcos(bm, polyNos, vertexCos, vertexNos);
103
104                 bmdm->vertexNos = (const float (*)[3])vertexNos;
105         }
106 }
107
108 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm)
109 {
110         if (bmdm->vertexCos && (bmdm->polyNos == NULL)) {
111                 BMesh *bm = bmdm->em->bm;
112                 const float (*vertexCos)[3];
113                 float (*polyNos)[3];
114
115                 BMFace *efa;
116                 BMIter fiter;
117                 int i;
118
119                 BM_mesh_elem_index_ensure(bm, BM_VERT);
120
121                 polyNos = MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__);
122
123                 vertexCos = bmdm->vertexCos;
124
125                 BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
126                         BM_elem_index_set(efa, i); /* set_inline */
127                         BM_face_calc_normal_vcos(bm, efa, polyNos[i], vertexCos);
128                 }
129                 bm->elem_index_dirty &= ~BM_FACE;
130
131                 bmdm->polyNos = (const float (*)[3])polyNos;
132         }
133 }
134
135 static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm)
136 {
137         if (bmdm->polyCos == NULL) {
138                 BMesh *bm = bmdm->em->bm;
139                 float (*polyCos)[3];
140
141                 BMFace *efa;
142                 BMIter fiter;
143                 int i;
144
145                 polyCos = MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__);
146
147                 if (bmdm->vertexCos) {
148                         const float (*vertexCos)[3];
149                         vertexCos = bmdm->vertexCos;
150
151                         BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
152                                 BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos);
153                         }
154                 }
155                 else {
156                         BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
157                                 BM_face_calc_center_mean(efa, polyCos[i]);
158                         }
159                 }
160
161                 bmdm->polyCos = (const float (*)[3])polyCos;
162         }
163 }
164
165 static void emDM_calcNormals(DerivedMesh *dm)
166 {
167         /* Nothing to do: normals are already calculated and stored on the
168          * BMVerts and BMFaces */
169         dm->dirty &= ~DM_DIRTY_NORMALS;
170 }
171
172 static void emDM_calcLoopNormals(DerivedMesh *dm, const float split_angle)
173 {
174         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
175         BMesh *bm = bmdm->em->bm;
176         const float (*vertexCos)[3], (*vertexNos)[3], (*polyNos)[3];
177         float (*loopNos)[3];
178
179         /* calculate loop normals from poly and vertex normals */
180         emDM_ensureVertNormals(bmdm);
181         emDM_ensurePolyNormals(bmdm);
182         dm->dirty &= ~DM_DIRTY_NORMALS;
183
184         vertexCos = bmdm->vertexCos;
185         vertexNos = bmdm->vertexNos;
186         polyNos = bmdm->polyNos;
187
188         loopNos = dm->getLoopDataArray(dm, CD_NORMAL);
189         if (!loopNos) {
190                 DM_add_loop_layer(dm, CD_NORMAL, CD_CALLOC, NULL);
191                 loopNos = dm->getLoopDataArray(dm, CD_NORMAL);
192         }
193
194         BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, split_angle, loopNos);
195 }
196
197 static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
198 {
199         /* do nothing */
200 }
201
202 static void emDM_foreachMappedVert(
203         DerivedMesh *dm,
204         void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
205         void *userData,
206         DMForeachFlag flag)
207 {
208         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
209         BMesh *bm = bmdm->em->bm;
210         BMVert *eve;
211         BMIter iter;
212         int i;
213
214         if (bmdm->vertexCos) {
215                 const float (*vertexCos)[3] = bmdm->vertexCos;
216                 const float (*vertexNos)[3];
217
218                 if (flag & DM_FOREACH_USE_NORMAL) {
219                         emDM_ensureVertNormals(bmdm);
220                         vertexNos = bmdm->vertexNos;
221                 }
222                 else {
223                         vertexNos = NULL;
224                 }
225
226                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
227                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
228                         func(userData, i, vertexCos[i], no, NULL);
229                 }
230         }
231         else {
232                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
233                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? eve->no : NULL;
234                         func(userData, i, eve->co, no, NULL);
235                 }
236         }
237 }
238 static void emDM_foreachMappedEdge(DerivedMesh *dm,
239                                    void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
240                                    void *userData)
241 {
242         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
243         BMesh *bm = bmdm->em->bm;
244         BMEdge *eed;
245         BMIter iter;
246         int i;
247
248         if (bmdm->vertexCos) {
249
250                 BM_mesh_elem_index_ensure(bm, BM_VERT);
251
252                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
253                         func(userData, i,
254                              bmdm->vertexCos[BM_elem_index_get(eed->v1)],
255                              bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
256                 }
257         }
258         else {
259                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
260                         func(userData, i, eed->v1->co, eed->v2->co);
261                 }
262         }
263 }
264
265 static void emDM_drawMappedEdges(DerivedMesh *dm,
266                                  DMSetDrawOptions setDrawOptions,
267                                  void *userData)
268 {
269         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
270         BMesh *bm = bmdm->em->bm;
271         BMEdge *eed;
272         BMIter iter;
273         int i;
274
275         if (bmdm->vertexCos) {
276
277                 BM_mesh_elem_index_ensure(bm, BM_VERT);
278
279                 glBegin(GL_LINES);
280                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
281                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
282                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
283                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
284                         }
285                 }
286                 glEnd();
287         }
288         else {
289                 glBegin(GL_LINES);
290                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
291                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
292                                 glVertex3fv(eed->v1->co);
293                                 glVertex3fv(eed->v2->co);
294                         }
295                 }
296                 glEnd();
297         }
298 }
299 static void emDM_drawEdges(DerivedMesh *dm,
300                            bool UNUSED(drawLooseEdges),
301                            bool UNUSED(drawAllEdges))
302 {
303         emDM_drawMappedEdges(dm, NULL, NULL);
304 }
305
306 static void emDM_drawMappedEdgesInterp(DerivedMesh *dm,
307                                        DMSetDrawOptions setDrawOptions,
308                                        DMSetDrawInterpOptions setDrawInterpOptions,
309                                        void *userData)
310 {
311         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
312         BMesh *bm = bmdm->em->bm;
313         BMEdge *eed;
314         BMIter iter;
315         int i;
316
317         if (bmdm->vertexCos) {
318
319                 BM_mesh_elem_index_ensure(bm, BM_VERT);
320
321                 glBegin(GL_LINES);
322                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
323                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
324                                 setDrawInterpOptions(userData, i, 0.0);
325                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
326                                 setDrawInterpOptions(userData, i, 1.0);
327                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
328                         }
329                 }
330                 glEnd();
331         }
332         else {
333                 glBegin(GL_LINES);
334                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
335                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
336                                 setDrawInterpOptions(userData, i, 0.0);
337                                 glVertex3fv(eed->v1->co);
338                                 setDrawInterpOptions(userData, i, 1.0);
339                                 glVertex3fv(eed->v2->co);
340                         }
341                 }
342                 glEnd();
343         }
344 }
345
346 static void emDM_drawUVEdges(DerivedMesh *dm)
347 {
348         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
349         BMesh *bm = bmdm->em->bm;
350         BMFace *efa;
351         BMIter iter;
352
353         const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
354
355         if (UNLIKELY(cd_loop_uv_offset == -1)) {
356                 return;
357         }
358
359         glBegin(GL_LINES);
360         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
361                 BMLoop *l_iter, *l_first;
362                 const float *uv, *uv_prev;
363
364                 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
365                         continue;
366
367                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
368                 uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv;
369                 do {
370                         uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
371                         glVertex2fv(uv);
372                         glVertex2fv(uv_prev);
373                         uv_prev = uv;
374                 } while ((l_iter = l_iter->next) != l_first);
375         }
376         glEnd();
377 }
378
379 static void emDM_foreachMappedLoop(
380         DerivedMesh *dm,
381         void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
382         void *userData,
383         DMForeachFlag flag)
384 {
385         /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
386          * return loop data from bmesh itself. */
387         const float (*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) : NULL;
388
389         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
390         BMesh *bm = bmdm->em->bm;
391         BMFace *efa;
392         BMIter iter;
393
394         const float (*vertexCos)[3] = bmdm->vertexCos;
395         int f_idx;
396
397         BM_mesh_elem_index_ensure(bm, BM_VERT);
398
399         BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) {
400                 BMLoop *l_iter, *l_first;
401
402                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
403                 do {
404                         const BMVert *eve = l_iter->v;
405                         const int v_idx = BM_elem_index_get(eve);
406                         const float *no = lnors ? *lnors++ : NULL;
407                         func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
408                 } while ((l_iter = l_iter->next) != l_first);
409         }
410 }
411
412 static void emDM_foreachMappedFaceCenter(
413         DerivedMesh *dm,
414         void (*func)(void *userData, int index, const float co[3], const float no[3]),
415         void *userData,
416         DMForeachFlag flag)
417 {
418         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
419         BMesh *bm = bmdm->em->bm;
420         const float (*polyNos)[3];
421         const float (*polyCos)[3];
422         BMFace *efa;
423         BMIter iter;
424         int i;
425
426         emDM_ensurePolyCenters(bmdm);
427         polyCos = bmdm->polyCos;  /* always set */
428
429         if (flag & DM_FOREACH_USE_NORMAL) {
430                 emDM_ensurePolyNormals(bmdm);
431                 polyNos = bmdm->polyNos;  /* maybe NULL */
432         }
433         else {
434                 polyNos = NULL;
435         }
436
437         if (polyNos) {
438                 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
439                         const float *no = polyNos[i];
440                         func(userData, i, polyCos[i], no);
441                 }
442         }
443         else {
444                 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
445                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? efa->no : NULL;
446                         func(userData, i, polyCos[i], no);
447                 }
448         }
449 }
450
451 static void emDM_drawMappedFaces(DerivedMesh *dm,
452                                  DMSetDrawOptions setDrawOptions,
453                                  DMSetMaterial setMaterial,
454                                  DMCompareDrawOptions compareDrawOptions,
455                                  void *userData,
456                                  DMDrawFlag flag)
457 {
458         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
459         BMEditMesh *em = bmdm->em;
460         BMesh *bm = em->bm;
461         BMFace *efa;
462         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
463         const int tottri = bmdm->em->tottri;
464         const int lasttri = tottri - 1; /* compare agasint this a lot */
465         DMDrawOption draw_option;
466         int i, flush;
467         const int skip_normals = !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
468
469         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
470         MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
471         unsigned char(*color_vert_array)[4] = em->derivedVertColor;
472         unsigned char(*color_face_array)[4] = em->derivedFaceColor;
473         bool has_vcol_preview = (color_vert_array != NULL) && !skip_normals;
474         bool has_fcol_preview = (color_face_array != NULL) && !skip_normals;
475         bool has_vcol_any = has_vcol_preview;
476
477         /* GL_ZERO is used to detect if drawing has started or not */
478         GLenum poly_prev = GL_ZERO;
479         GLenum shade_prev = GL_ZERO;
480
481         (void)setMaterial; /* UNUSED */
482
483         /* currently unused -- each original face is handled separately */
484         (void)compareDrawOptions;
485
486         /* call again below is ok */
487         if (has_vcol_preview) {
488                 BM_mesh_elem_index_ensure(bm, BM_VERT);
489         }
490         if (has_fcol_preview) {
491                 BM_mesh_elem_index_ensure(bm, BM_FACE);
492         }
493         if (has_vcol_preview || has_fcol_preview) {
494                 flag |= DM_DRAW_ALWAYS_SMOOTH;
495                 glDisable(GL_LIGHTING);  /* grr */
496         }
497
498         if (bmdm->vertexCos) {
499                 /* add direct access */
500                 const float (*vertexCos)[3] = bmdm->vertexCos;
501                 const float (*vertexNos)[3];
502                 const float (*polyNos)[3];
503
504                 if (skip_normals) {
505                         vertexNos = NULL;
506                         polyNos = NULL;
507                 }
508                 else {
509                         emDM_ensureVertNormals(bmdm);
510                         emDM_ensurePolyNormals(bmdm);
511                         vertexNos = bmdm->vertexNos;
512                         polyNos = bmdm->polyNos;
513                 }
514
515                 BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE);
516
517                 for (i = 0; i < tottri; i++) {
518                         BMLoop **ltri = looptris[i];
519                         int drawSmooth;
520
521                         efa = ltri[0]->f;
522                         drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
523
524                         draw_option = (!setDrawOptions ?
525                                        DM_DRAW_OPTION_NORMAL :
526                                        setDrawOptions(userData, BM_elem_index_get(efa)));
527                         if (draw_option != DM_DRAW_OPTION_SKIP) {
528                                 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
529                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
530
531                                         if (poly_prev != GL_ZERO) glEnd();
532                                         poly_prev = GL_ZERO; /* force glBegin */
533
534                                         glEnable(GL_POLYGON_STIPPLE);
535                                         glPolygonStipple(stipple_quarttone);
536                                 }
537
538                                 if      (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
539                                 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
540                                 if (skip_normals) {
541                                         if (poly_type != poly_prev) {
542                                                 if (poly_prev != GL_ZERO) glEnd();
543                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
544                                         }
545                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
546                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
547                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
548                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
549                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
550                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
551                                 }
552                                 else {
553                                         const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
554                                         if (shade_type != shade_prev) {
555                                                 if (poly_prev != GL_ZERO) glEnd();
556                                                 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
557                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
558                                         }
559                                         if (poly_type != poly_prev) {
560                                                 if (poly_prev != GL_ZERO) glEnd();
561                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
562                                         }
563
564                                         if (!drawSmooth) {
565                                                 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
566                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
567                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
568                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
569                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
570                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
571                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
572                                         }
573                                         else {
574                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
575                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
576                                                 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
577                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
578                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
579                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
580                                                 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
581                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
582                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
583                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
584                                                 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
585                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
586                                         }
587                                 }
588
589                                 flush = (draw_option == DM_DRAW_OPTION_STIPPLE);
590                                 if (!skip_normals && !flush && (i != lasttri))
591                                         flush |= efa->mat_nr != looptris[i + 1][0]->f->mat_nr;  /* TODO, make this neater */
592
593                                 if (flush) {
594                                         glEnd();
595                                         poly_prev = GL_ZERO; /* force glBegin */
596
597                                         glDisable(GL_POLYGON_STIPPLE);
598                                 }
599                         }
600                 }
601         }
602         else {
603                 BM_mesh_elem_index_ensure(bm, lnors ? BM_FACE | BM_LOOP : BM_FACE);
604
605                 for (i = 0; i < tottri; i++) {
606                         BMLoop **ltri = looptris[i];
607                         int drawSmooth;
608
609                         efa = ltri[0]->f;
610                         drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
611
612                         draw_option = (!setDrawOptions ?
613                                        DM_DRAW_OPTION_NORMAL :
614                                        setDrawOptions(userData, BM_elem_index_get(efa)));
615                         if (draw_option != DM_DRAW_OPTION_SKIP) {
616                                 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
617                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
618
619                                         if (poly_prev != GL_ZERO) glEnd();
620                                         poly_prev = GL_ZERO; /* force glBegin */
621
622                                         glEnable(GL_POLYGON_STIPPLE);
623                                         glPolygonStipple(stipple_quarttone);
624                                 }
625
626                                 if      (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
627                                 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
628
629                                 if (skip_normals) {
630                                         if (poly_type != poly_prev) {
631                                                 if (poly_prev != GL_ZERO) glEnd();
632                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
633                                         }
634                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
635                                         glVertex3fv(ltri[0]->v->co);
636                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
637                                         glVertex3fv(ltri[1]->v->co);
638                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
639                                         glVertex3fv(ltri[2]->v->co);
640                                 }
641                                 else {
642                                         const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
643                                         if (shade_type != shade_prev) {
644                                                 if (poly_prev != GL_ZERO) glEnd();
645                                                 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
646                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
647                                         }
648                                         if (poly_type != poly_prev) {
649                                                 if (poly_prev != GL_ZERO) glEnd();
650                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
651                                         }
652
653                                         if (!drawSmooth) {
654                                                 glNormal3fv(efa->no);
655                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
656                                                 glVertex3fv(ltri[0]->v->co);
657                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
658                                                 glVertex3fv(ltri[1]->v->co);
659                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
660                                                 glVertex3fv(ltri[2]->v->co);
661                                         }
662                                         else {
663                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
664                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
665                                                 else glNormal3fv(ltri[0]->v->no);
666                                                 glVertex3fv(ltri[0]->v->co);
667                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
668                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
669                                                 else glNormal3fv(ltri[1]->v->no);
670                                                 glVertex3fv(ltri[1]->v->co);
671                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
672                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
673                                                 else glNormal3fv(ltri[2]->v->no);
674                                                 glVertex3fv(ltri[2]->v->co);
675                                         }
676                                 }
677
678                                 flush = (draw_option == DM_DRAW_OPTION_STIPPLE);
679                                 if (!skip_normals && !flush && (i != lasttri)) {
680                                         flush |= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
681                                 }
682
683                                 if (flush) {
684                                         glEnd();
685                                         poly_prev = GL_ZERO; /* force glBegin */
686
687                                         glDisable(GL_POLYGON_STIPPLE);
688                                 }
689                         }
690                 }
691         }
692
693         /* if non zero we know a face was rendered */
694         if (poly_prev != GL_ZERO) glEnd();
695 }
696
697 static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
698 {
699         luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset);
700         luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset);
701         luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset);
702 }
703
704 static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset)
705 {
706         lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset);
707         lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset);
708         lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset);
709 }
710
711 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4])
712 {
713         lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)];
714         lcol[1] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[1]->v)];
715         lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)];
716 }
717
718 static void emDM_drawFacesTex_common(DerivedMesh *dm,
719                                      DMSetDrawOptionsTex drawParams,
720                                      DMSetDrawOptions drawParamsMapped,
721                                      DMCompareDrawOptions compareDrawOptions,
722                                      void *userData)
723 {
724         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
725         BMEditMesh *em = bmdm->em;
726         BMesh *bm = em->bm;
727         struct BMLoop *(*looptris)[3] = em->looptris;
728         BMFace *efa;
729         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
730         MLoopUV *luv[3], dummyluv = {{0}};
731         MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
732         const int cd_loop_uv_offset    = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
733         const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
734         const int cd_poly_tex_offset   = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
735         unsigned char(*color_vert_array)[4] = em->derivedVertColor;
736         bool has_uv   = (cd_loop_uv_offset    != -1);
737         bool has_vcol_preview = (color_vert_array != NULL);
738         bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false);
739         bool has_vcol_any = (has_vcol_preview || has_vcol);
740         int i;
741
742         (void) compareDrawOptions;
743
744         luv[0] = luv[1] = luv[2] = &dummyluv;
745
746         // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255;  /* UNUSED */
747
748         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
749         glShadeModel(GL_SMOOTH);
750
751         BM_mesh_elem_index_ensure(bm, BM_FACE);
752
753         /* call again below is ok */
754         if (has_vcol_preview) {
755                 BM_mesh_elem_index_ensure(bm, BM_VERT);
756         }
757
758         if (bmdm->vertexCos) {
759                 /* add direct access */
760                 const float (*vertexCos)[3] = bmdm->vertexCos;
761                 const float (*vertexNos)[3];
762                 const float (*polyNos)[3];
763
764                 emDM_ensureVertNormals(bmdm);
765                 emDM_ensurePolyNormals(bmdm);
766                 vertexNos = bmdm->vertexNos;
767                 polyNos = bmdm->polyNos;
768
769                 BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
770
771                 for (i = 0; i < em->tottri; i++) {
772                         BMLoop **ltri = looptris[i];
773                         MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
774                         MTFace mtf = {{{0}}};
775                         /*unsigned char *cp = NULL;*/ /*UNUSED*/
776                         int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
777                         DMDrawOption draw_option;
778
779                         efa = ltri[0]->f;
780
781                         if (cd_poly_tex_offset != -1) {
782                                 ME_MTEXFACE_CPY(&mtf, tp);
783                         }
784
785                         if (drawParams)
786                                 draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
787                         else if (drawParamsMapped)
788                                 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
789                         else
790                                 draw_option = DM_DRAW_OPTION_NORMAL;
791
792                         if (draw_option != DM_DRAW_OPTION_SKIP) {
793
794                                 if      (has_uv)            bmdm_get_tri_uv(ltri,  luv,  cd_loop_uv_offset);
795                                 if      (has_vcol)          bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
796                                 else if (has_vcol_preview)  bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
797
798                                 glBegin(GL_TRIANGLES);
799                                 if (!drawSmooth) {
800                                         glNormal3fv(polyNos[BM_elem_index_get(efa)]);
801
802                                         glTexCoord2fv(luv[0]->uv);
803                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
804                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
805
806                                         glTexCoord2fv(luv[1]->uv);
807                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
808                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
809
810                                         glTexCoord2fv(luv[2]->uv);
811                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
812                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
813                                 }
814                                 else {
815                                         glTexCoord2fv(luv[0]->uv);
816                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
817                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
818                                         else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
819                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
820
821                                         glTexCoord2fv(luv[1]->uv);
822                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
823                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
824                                         else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
825                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
826
827                                         glTexCoord2fv(luv[2]->uv);
828                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
829                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
830                                         else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
831                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
832                                 }
833                                 glEnd();
834                         }
835                 }
836         }
837         else {
838                 BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
839
840                 for (i = 0; i < em->tottri; i++) {
841                         BMLoop **ltri = looptris[i];
842                         MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
843                         MTFace mtf = {{{0}}};
844                         /*unsigned char *cp = NULL;*/ /*UNUSED*/
845                         int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
846                         DMDrawOption draw_option;
847
848                         efa = ltri[0]->f;
849
850                         if (cd_poly_tex_offset != -1) {
851                                 ME_MTEXFACE_CPY(&mtf, tp);
852                         }
853
854                         if (drawParams)
855                                 draw_option = drawParams(&mtf, has_vcol, efa->mat_nr);
856                         else if (drawParamsMapped)
857                                 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
858                         else
859                                 draw_option = DM_DRAW_OPTION_NORMAL;
860
861                         if (draw_option != DM_DRAW_OPTION_SKIP) {
862
863                                 if      (has_uv)            bmdm_get_tri_uv(ltri,  luv,  cd_loop_uv_offset);
864                                 if      (has_vcol)          bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
865                                 else if (has_vcol_preview)  bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
866
867                                 glBegin(GL_TRIANGLES);
868                                 if (!drawSmooth) {
869                                         glNormal3fv(efa->no);
870
871                                         glTexCoord2fv(luv[0]->uv);
872                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
873                                         glVertex3fv(ltri[0]->v->co);
874
875                                         glTexCoord2fv(luv[1]->uv);
876                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
877                                         glVertex3fv(ltri[1]->v->co);
878
879                                         glTexCoord2fv(luv[2]->uv);
880                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
881                                         glVertex3fv(ltri[2]->v->co);
882                                 }
883                                 else {
884                                         glTexCoord2fv(luv[0]->uv);
885                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
886                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
887                                         else glNormal3fv(ltri[0]->v->no);
888                                         glVertex3fv(ltri[0]->v->co);
889
890                                         glTexCoord2fv(luv[1]->uv);
891                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
892                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
893                                         else glNormal3fv(ltri[1]->v->no);
894                                         glVertex3fv(ltri[1]->v->co);
895
896                                         glTexCoord2fv(luv[2]->uv);
897                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
898                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
899                                         else glNormal3fv(ltri[2]->v->no);
900                                         glVertex3fv(ltri[2]->v->co);
901                                 }
902                                 glEnd();
903                         }
904                 }
905         }
906
907         glShadeModel(GL_FLAT);
908 }
909
910 static void emDM_drawFacesTex(DerivedMesh *dm,
911                               DMSetDrawOptionsTex setDrawOptions,
912                               DMCompareDrawOptions compareDrawOptions,
913                               void *userData, DMDrawFlag UNUSED(flag))
914 {
915         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
916 }
917
918 static void emDM_drawMappedFacesTex(DerivedMesh *dm,
919                                     DMSetDrawOptions setDrawOptions,
920                                     DMCompareDrawOptions compareDrawOptions,
921                                     void *userData, DMDrawFlag UNUSED(flag))
922 {
923         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
924 }
925
926 /**
927  * \note
928  *
929  * For UV's:
930  *   const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
931  *
932  * This is intentionally different to calling:
933  *   CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i);
934  *
935  * ... because the material may use layer names to select different UV's
936  * see: [#34378]
937  */
938 static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const BMLoop *loop, const int index_in_face)
939 {
940         BMVert *eve = loop->v;
941         int i;
942         const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
943
944         if (attribs->totorco) {
945                 int index = BM_elem_index_get(eve);
946                 const float *orco = (attribs->orco.array) ? attribs->orco.array[index] : zero;
947
948                 if (attribs->orco.gl_texco)
949                         glTexCoord3fv(orco);
950                 else
951                         glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
952         }
953         for (i = 0; i < attribs->tottface; i++) {
954                 const float *uv;
955
956                 if (attribs->tface[i].em_offset != -1) {
957                         const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
958                         uv = luv->uv;
959                 }
960                 else {
961                         uv = zero;
962                 }
963
964                 if (attribs->tface[i].gl_texco)
965                         glTexCoord2fv(uv);
966                 else
967                         glVertexAttrib2fvARB(attribs->tface[i].gl_index, uv);
968         }
969         for (i = 0; i < attribs->totmcol; i++) {
970                 GLubyte col[4];
971                 if (attribs->mcol[i].em_offset != -1) {
972                         const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
973                         col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
974                 }
975                 else {
976                         col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
977                 }
978                 glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col);
979         }
980         if (attribs->tottang) {
981                 int index = i * 4 + index_in_face;
982                 const float *tang = (attribs->tang.array) ? attribs->tang.array[index] : zero;
983                 glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
984         }
985 }
986
987 static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
988                                      DMSetMaterial setMaterial,
989                                      DMSetDrawOptions setDrawOptions,
990                                      void *userData)
991 {
992         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
993         BMEditMesh *em = bmdm->em;
994         BMesh *bm = em->bm;
995         struct BMLoop *(*looptris)[3] = em->looptris;
996         /* add direct access */
997         const float (*vertexCos)[3] = bmdm->vertexCos;
998         const float (*vertexNos)[3];
999         const float (*polyNos)[3];
1000         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1001
1002         BMFace *efa;
1003         DMVertexAttribs attribs;
1004         GPUVertexAttribs gattribs;
1005
1006         int i, matnr, new_matnr, fi;
1007         bool do_draw;
1008
1009         do_draw = false;
1010         matnr = -1;
1011
1012         memset(&attribs, 0, sizeof(attribs));
1013
1014         emDM_ensureVertNormals(bmdm);
1015         emDM_ensurePolyNormals(bmdm);
1016         vertexNos = bmdm->vertexNos;
1017         polyNos = bmdm->polyNos;
1018
1019         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1020         glShadeModel(GL_SMOOTH);
1021         BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE);
1022
1023         for (i = 0; i < em->tottri; i++) {
1024                 BMLoop **ltri = looptris[i];
1025                 int drawSmooth;
1026
1027                 efa = ltri[0]->f;
1028
1029                 if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
1030                         continue;
1031
1032                 new_matnr = efa->mat_nr + 1;
1033                 if (new_matnr != matnr) {
1034                         if (matnr != -1)
1035                                 glEnd();
1036
1037                         do_draw = setMaterial(matnr = new_matnr, &gattribs);
1038                         if (do_draw)
1039                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1040
1041                         glBegin(GL_TRIANGLES);
1042                 }
1043
1044                 if (do_draw) {
1045
1046                         /* draw face */
1047                         drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1048
1049                         if (!drawSmooth) {
1050                                 if (vertexCos) {
1051                                         glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1052                                         for (fi = 0; fi < 3; fi++) {
1053                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1054                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
1055                                         }
1056                                 }
1057                                 else {
1058                                         glNormal3fv(efa->no);
1059                                         for (fi = 0; fi < 3; fi++) {
1060                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1061                                                 glVertex3fv(ltri[fi]->v->co);
1062                                         }
1063                                 }
1064                         }
1065                         else {
1066                                 if (vertexCos) {
1067                                         for (fi = 0; fi < 3; fi++) {
1068                                                 const int j = BM_elem_index_get(ltri[fi]->v);
1069                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1070                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1071                                                 else glNormal3fv(vertexNos[j]);
1072                                                 glVertex3fv(vertexCos[j]);
1073                                         }
1074                                 }
1075                                 else {
1076                                         for (fi = 0; fi < 3; fi++) {
1077                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1078                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1079                                                 else glNormal3fv(ltri[fi]->v->no);
1080                                                 glVertex3fv(ltri[fi]->v->co);
1081                                         }
1082                                 }
1083                         }
1084                 }
1085         }
1086
1087         if (matnr != -1) {
1088                 glEnd();
1089         }
1090 }
1091
1092 static void emDM_drawFacesGLSL(DerivedMesh *dm,
1093                                int (*setMaterial)(int matnr, void *attribs))
1094 {
1095         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1096 }
1097
1098 static void emDM_drawMappedFacesMat(DerivedMesh *dm,
1099                                     void (*setMaterial)(void *userData, int matnr, void *attribs),
1100                                     bool (*setFace)(void *userData, int index), void *userData)
1101 {
1102         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1103         BMEditMesh *em = bmdm->em;
1104         BMesh *bm = em->bm;
1105         struct BMLoop *(*looptris)[3] = em->looptris;
1106         const float (*vertexCos)[3] = bmdm->vertexCos;
1107         const float (*vertexNos)[3];
1108         const float (*polyNos)[3];
1109         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1110         BMFace *efa;
1111         DMVertexAttribs attribs = {{{NULL}}};
1112         GPUVertexAttribs gattribs;
1113         int i, matnr, new_matnr, fi;
1114
1115         matnr = -1;
1116
1117         emDM_ensureVertNormals(bmdm);
1118         emDM_ensurePolyNormals(bmdm);
1119
1120         vertexNos = bmdm->vertexNos;
1121         polyNos = bmdm->polyNos;
1122
1123         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1124         glShadeModel(GL_SMOOTH);
1125
1126         BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE);
1127
1128         for (i = 0; i < em->tottri; i++) {
1129                 BMLoop **ltri = looptris[i];
1130                 int drawSmooth;
1131
1132                 efa = ltri[0]->f;
1133
1134                 /* face hiding */
1135                 if (setFace && !setFace(userData, BM_elem_index_get(efa)))
1136                         continue;
1137
1138                 /* material */
1139                 new_matnr = efa->mat_nr + 1;
1140                 if (new_matnr != matnr) {
1141                         if (matnr != -1)
1142                                 glEnd();
1143
1144                         setMaterial(userData, matnr = new_matnr, &gattribs);
1145                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1146
1147                         glBegin(GL_TRIANGLES);
1148                 }
1149
1150                 /* draw face */
1151                 drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1152
1153                 if (!drawSmooth) {
1154                         if (vertexCos) {
1155                                 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1156                                 for (fi = 0; fi < 3; fi++) {
1157                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1158                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
1159                                 }
1160                         }
1161                         else {
1162                                 glNormal3fv(efa->no);
1163                                 for (fi = 0; fi < 3; fi++) {
1164                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1165                                         glVertex3fv(ltri[fi]->v->co);
1166                                 }
1167                         }
1168                 }
1169                 else {
1170                         if (vertexCos) {
1171                                 for (fi = 0; fi < 3; fi++) {
1172                                         const int j = BM_elem_index_get(ltri[fi]->v);
1173                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1174                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1175                                         else glNormal3fv(vertexNos[j]);
1176                                         glVertex3fv(vertexCos[j]);
1177                                 }
1178                         }
1179                         else {
1180                                 for (fi = 0; fi < 3; fi++) {
1181                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi], fi);
1182                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1183                                         else glNormal3fv(ltri[fi]->v->no);
1184                                         glVertex3fv(ltri[fi]->v->co);
1185                                 }
1186                         }
1187                 }
1188         }
1189
1190         if (matnr != -1) {
1191                 glEnd();
1192         }
1193 }
1194
1195 static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
1196 {
1197         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1198         BMesh *bm = bmdm->em->bm;
1199         BMVert *eve;
1200         BMIter iter;
1201         int i;
1202
1203         if (bm->totvert) {
1204                 if (bmdm->vertexCos) {
1205                         BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1206                                 minmax_v3v3_v3(r_min, r_max, bmdm->vertexCos[i]);
1207                         }
1208                 }
1209                 else {
1210                         BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1211                                 minmax_v3v3_v3(r_min, r_max, eve->co);
1212                         }
1213                 }
1214         }
1215         else {
1216                 zero_v3(r_min);
1217                 zero_v3(r_max);
1218         }
1219 }
1220 static int emDM_getNumVerts(DerivedMesh *dm)
1221 {
1222         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1223
1224         return bmdm->em->bm->totvert;
1225 }
1226
1227 static int emDM_getNumEdges(DerivedMesh *dm)
1228 {
1229         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1230
1231         return bmdm->em->bm->totedge;
1232 }
1233
1234 static int emDM_getNumTessFaces(DerivedMesh *dm)
1235 {
1236         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1237
1238         return bmdm->em->tottri;
1239 }
1240
1241 static int emDM_getNumLoops(DerivedMesh *dm)
1242 {
1243         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1244
1245         return bmdm->em->bm->totloop;
1246 }
1247
1248 static int emDM_getNumPolys(DerivedMesh *dm)
1249 {
1250         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1251
1252         return bmdm->em->bm->totface;
1253 }
1254
1255 static void bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *r_vert)
1256 {
1257         const float *f;
1258
1259         copy_v3_v3(r_vert->co, ev->co);
1260
1261         normal_float_to_short_v3(r_vert->no, ev->no);
1262
1263         r_vert->flag = BM_vert_flag_to_mflag(ev);
1264
1265         if ((f = CustomData_bmesh_get(&bm->vdata, ev->head.data, CD_BWEIGHT))) {
1266                 r_vert->bweight = (unsigned char)((*f) * 255.0f);
1267         }
1268 }
1269
1270 static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
1271 {
1272         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1273         BMesh *bm = bmdm->em->bm;
1274         BMVert *ev;
1275
1276         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1277                 BLI_assert(!"error in emDM_getVert");
1278                 return;
1279         }
1280
1281         BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1282         ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1283         // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1284
1285         bmvert_to_mvert(bm, ev, r_vert);
1286         if (bmdm->vertexCos)
1287                 copy_v3_v3(r_vert->co, bmdm->vertexCos[index]);
1288 }
1289
1290 static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
1291 {
1292         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1293         BMesh *bm = bmdm->em->bm;
1294
1295         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1296                 BLI_assert(!"error in emDM_getVertCo");
1297                 return;
1298         }
1299
1300         if (bmdm->vertexCos) {
1301                 copy_v3_v3(r_co, bmdm->vertexCos[index]);
1302         }
1303         else {
1304                 BMVert *ev;
1305
1306                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1307                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1308                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1309                 copy_v3_v3(r_co, ev->co);
1310         }
1311 }
1312
1313 static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
1314 {
1315         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1316         BMesh *bm = bmdm->em->bm;
1317
1318         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1319                 BLI_assert(!"error in emDM_getVertNo");
1320                 return;
1321         }
1322
1323
1324         if (bmdm->vertexCos) {
1325                 emDM_ensureVertNormals(bmdm);
1326                 copy_v3_v3(r_no, bmdm->vertexNos[index]);
1327         }
1328         else {
1329                 BMVert *ev;
1330
1331                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1332                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1333                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1334                 copy_v3_v3(r_no, ev->no);
1335         }
1336 }
1337
1338 static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3])
1339 {
1340         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1341         BMesh *bm = bmdm->em->bm;
1342
1343         if (UNLIKELY(index < 0 || index >= bm->totface)) {
1344                 BLI_assert(!"error in emDM_getPolyNo");
1345                 return;
1346         }
1347
1348         if (bmdm->vertexCos) {
1349                 emDM_ensurePolyNormals(bmdm);
1350                 copy_v3_v3(r_no, bmdm->polyNos[index]);
1351         }
1352         else {
1353                 BMFace *efa;
1354
1355                 BLI_assert((bm->elem_table_dirty & BM_FACE) == 0);
1356                 efa = bm->ftable[index];  /* should be BM_vert_at_index() */
1357                 // efa = BM_face_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1358                 copy_v3_v3(r_no, efa->no);
1359         }
1360 }
1361
1362 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
1363 {
1364         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1365         BMesh *bm = bmdm->em->bm;
1366         BMEdge *e;
1367         const float *f;
1368
1369         if (UNLIKELY(index < 0 || index >= bm->totedge)) {
1370                 BLI_assert(!"error in emDM_getEdge");
1371                 return;
1372         }
1373
1374         BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
1375         e = bm->etable[index];  /* should be BM_edge_at_index() */
1376         // e = BM_edge_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1377
1378         r_edge->flag = BM_edge_flag_to_mflag(e);
1379
1380         r_edge->v1 = BM_elem_index_get(e->v1);
1381         r_edge->v2 = BM_elem_index_get(e->v2);
1382
1383         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT))) {
1384                 r_edge->bweight = (unsigned char)((*f) * 255.0f);
1385         }
1386         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE))) {
1387                 r_edge->crease = (unsigned char)((*f) * 255.0f);
1388         }
1389 }
1390
1391 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
1392 {
1393         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1394         BMFace *ef;
1395         BMLoop **ltri;
1396
1397         if (UNLIKELY(index < 0 || index >= bmdm->em->tottri)) {
1398                 BLI_assert(!"error in emDM_getTessFace");
1399                 return;
1400         }
1401
1402         ltri = bmdm->em->looptris[index];
1403
1404         ef = ltri[0]->f;
1405
1406         r_face->mat_nr = (unsigned char) ef->mat_nr;
1407         r_face->flag = BM_face_flag_to_mflag(ef);
1408
1409         r_face->v1 = BM_elem_index_get(ltri[0]->v);
1410         r_face->v2 = BM_elem_index_get(ltri[1]->v);
1411         r_face->v3 = BM_elem_index_get(ltri[2]->v);
1412         r_face->v4 = 0;
1413
1414         test_index_face(r_face, NULL, 0, 3);
1415 }
1416
1417 static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
1418 {
1419         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1420         BMesh *bm = bmdm->em->bm;
1421         BMVert *eve;
1422         BMIter iter;
1423         const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
1424
1425         if (bmdm->vertexCos) {
1426                 int i;
1427
1428                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1429                         copy_v3_v3(r_vert->co, bmdm->vertexCos[i]);
1430                         normal_float_to_short_v3(r_vert->no, eve->no);
1431                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1432
1433                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1434
1435                         r_vert++;
1436                 }
1437         }
1438         else {
1439                 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1440                         copy_v3_v3(r_vert->co, eve->co);
1441                         normal_float_to_short_v3(r_vert->no, eve->no);
1442                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1443
1444                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1445
1446                         r_vert++;
1447                 }
1448         }
1449 }
1450
1451 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
1452 {
1453         BMesh *bm = ((EditDerivedBMesh *)dm)->em->bm;
1454         BMEdge *eed;
1455         BMIter iter;
1456
1457         const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
1458         const int cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
1459
1460         BM_mesh_elem_index_ensure(bm, BM_VERT);
1461
1462         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1463                 r_edge->v1 = BM_elem_index_get(eed->v1);
1464                 r_edge->v2 = BM_elem_index_get(eed->v2);
1465
1466                 r_edge->flag = BM_edge_flag_to_mflag(eed);
1467
1468                 r_edge->crease  = (cd_edge_crease_offset  != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset)  : 0;
1469                 r_edge->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0;
1470
1471                 r_edge++;
1472         }
1473 }
1474
1475 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
1476 {
1477         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1478         BMesh *bm = bmdm->em->bm;
1479         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
1480         BMFace *ef;
1481         int i;
1482
1483         BM_mesh_elem_index_ensure(bm, BM_VERT);
1484
1485         for (i = 0; i < bmdm->em->tottri; i++, r_face++) {
1486                 BMLoop **ltri = looptris[i];
1487                 ef = ltri[0]->f;
1488
1489                 r_face->mat_nr = (unsigned char) ef->mat_nr;
1490
1491                 r_face->flag = BM_face_flag_to_mflag(ef);
1492                 r_face->edcode = 0;
1493
1494                 r_face->v1 = BM_elem_index_get(ltri[0]->v);
1495                 r_face->v2 = BM_elem_index_get(ltri[1]->v);
1496                 r_face->v3 = BM_elem_index_get(ltri[2]->v);
1497                 r_face->v4 = 0;
1498
1499                 test_index_face(r_face, NULL, 0, 3);
1500         }
1501 }
1502
1503 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
1504 {
1505         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1506         BMesh *bm = bmdm->em->bm;
1507         BMIter iter;
1508         BMFace *efa;
1509
1510         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
1511
1512         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1513                 BMLoop *l_iter, *l_first;
1514                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
1515                 do {
1516                         r_loop->v = BM_elem_index_get(l_iter->v);
1517                         r_loop->e = BM_elem_index_get(l_iter->e);
1518                         r_loop++;
1519                 } while ((l_iter = l_iter->next) != l_first);
1520         }
1521 }
1522
1523 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
1524 {
1525         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1526         BMesh *bm = bmdm->em->bm;
1527         BMIter iter;
1528         BMFace *efa;
1529         int i;
1530
1531         i = 0;
1532         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1533                 r_poly->flag = BM_face_flag_to_mflag(efa);
1534                 r_poly->loopstart = i;
1535                 r_poly->totloop = efa->len;
1536                 r_poly->mat_nr = efa->mat_nr;
1537
1538                 r_poly++;
1539                 i += efa->len;
1540         }
1541 }
1542
1543 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
1544 {
1545         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1546         BMesh *bm = bmdm->em->bm;
1547         void *datalayer;
1548
1549         datalayer = DM_get_tessface_data_layer(dm, type);
1550         if (datalayer)
1551                 return datalayer;
1552
1553         /* layers are store per face for editmesh, we convert to a temporary
1554          * data layer array in the derivedmesh when these are requested */
1555         if (type == CD_MTFACE || type == CD_MCOL) {
1556                 const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
1557                 int index;
1558                 const char *data, *bmdata;
1559                 index = CustomData_get_layer_index(&bm->pdata, type_from);
1560
1561                 if (index != -1) {
1562                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
1563                         BMLoop *(*looptris)[3] = bmdm->em->looptris;
1564                         const int size = CustomData_sizeof(type);
1565                         int i, j;
1566
1567                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1568                         index = CustomData_get_layer_index(&dm->faceData, type);
1569                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1570
1571                         data = datalayer = DM_get_tessface_data_layer(dm, type);
1572
1573                         if (type == CD_MTFACE) {
1574                                 const int cd_loop_uv_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
1575                                 const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
1576
1577                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1578                                         BMFace *efa = looptris[i][0]->f;
1579
1580                                         // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
1581                                         bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
1582
1583                                         ME_MTEXFACE_CPY(((MTFace *)data), ((MTexPoly *)bmdata));
1584                                         for (j = 0; j < 3; j++) {
1585                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
1586                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
1587                                                 copy_v2_v2(((MTFace *)data)->uv[j], ((MLoopUV *)bmdata)->uv);
1588                                         }
1589                                 }
1590                         }
1591                         else {
1592                                 const int cd_loop_color_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
1593                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
1594                                         for (j = 0; j < 3; j++) {
1595                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
1596                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
1597                                                 MESH_MLOOPCOL_TO_MCOL(((MLoopCol *)bmdata), (((MCol *)data) + j));
1598                                         }
1599                                 }
1600                         }
1601                 }
1602         }
1603
1604         /* Special handling for CD_TESSLOOPNORMAL, we generate it on demand as well. */
1605         if (type == CD_TESSLOOPNORMAL) {
1606                 const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1607
1608                 if (lnors) {
1609                         BMLoop *(*looptris)[3] = bmdm->em->looptris;
1610                         short (*tlnors)[4][3], (*tlnor)[4][3];
1611                         int index, i, j;
1612
1613                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
1614                         index = CustomData_get_layer_index(&dm->faceData, type);
1615                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
1616
1617                         tlnor = tlnors = DM_get_tessface_data_layer(dm, type);
1618
1619                         BM_mesh_elem_index_ensure(bm, BM_LOOP);
1620
1621                         for (i = 0; i < bmdm->em->tottri; i++, tlnor++, looptris++) {
1622                                 for (j = 0; j < 3; j++) {
1623                                         normal_float_to_short_v3((*tlnor)[j], lnors[BM_elem_index_get((*looptris)[j])]);
1624                                 }
1625                         }
1626                 }
1627         }
1628
1629         return datalayer;
1630 }
1631
1632 static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3])
1633 {
1634         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1635         BMesh *bm = bmdm->em->bm;
1636         BMVert *eve;
1637         BMIter iter;
1638         int i;
1639
1640         if (bmdm->vertexCos) {
1641                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1642                         copy_v3_v3(r_cos[i], bmdm->vertexCos[i]);
1643                 }
1644         }
1645         else {
1646                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1647                         copy_v3_v3(r_cos[i], eve->co);
1648                 }
1649         }
1650 }
1651
1652 static void emDM_release(DerivedMesh *dm)
1653 {
1654         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1655
1656         if (DM_release(dm)) {
1657                 if (bmdm->vertexCos) {
1658                         MEM_freeN((void *)bmdm->vertexCos);
1659                         if (bmdm->vertexNos) {
1660                                 MEM_freeN((void *)bmdm->vertexNos);
1661                         }
1662                         if (bmdm->polyNos) {
1663                                 MEM_freeN((void *)bmdm->polyNos);
1664                         }
1665                 }
1666
1667                 if (bmdm->polyCos) {
1668                         MEM_freeN((void *)bmdm->polyCos);
1669                 }
1670
1671                 MEM_freeN(bmdm);
1672         }
1673 }
1674
1675 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
1676 {
1677         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1678
1679         return &bmdm->em->bm->vdata;
1680 }
1681
1682 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
1683 {
1684         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1685
1686         return &bmdm->em->bm->edata;
1687 }
1688
1689 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
1690 {
1691         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1692
1693         return &bmdm->dm.faceData;
1694 }
1695
1696 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
1697 {
1698         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1699
1700         return &bmdm->em->bm->ldata;
1701 }
1702
1703 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
1704 {
1705         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1706
1707         return &bmdm->em->bm->pdata;
1708 }
1709
1710
1711 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
1712                                  Object *UNUSED(ob),
1713                                  float (*vertexCos)[3])
1714 {
1715         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
1716         BMesh *bm = em->bm;
1717         const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
1718         const int cd_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
1719
1720         bmdm->em = em;
1721
1722         DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, bm->totvert,
1723                 bm->totedge, em->tottri, bm->totloop, bm->totface);
1724
1725         /* could also get from the objects mesh directly */
1726         bmdm->dm.cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
1727
1728         bmdm->dm.getVertCos = emDM_getVertCos;
1729         bmdm->dm.getMinMax = emDM_getMinMax;
1730
1731         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
1732         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
1733         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
1734         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
1735         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
1736
1737         bmdm->dm.getNumVerts = emDM_getNumVerts;
1738         bmdm->dm.getNumEdges = emDM_getNumEdges;
1739         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
1740         bmdm->dm.getNumLoops = emDM_getNumLoops;
1741         bmdm->dm.getNumPolys = emDM_getNumPolys;
1742
1743         bmdm->dm.getVert = emDM_getVert;
1744         bmdm->dm.getVertCo = emDM_getVertCo;
1745         bmdm->dm.getVertNo = emDM_getVertNo;
1746         bmdm->dm.getPolyNo = emDM_getPolyNo;
1747         bmdm->dm.getEdge = emDM_getEdge;
1748         bmdm->dm.getTessFace = emDM_getTessFace;
1749         bmdm->dm.copyVertArray = emDM_copyVertArray;
1750         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
1751         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
1752         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
1753         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
1754
1755         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
1756
1757         bmdm->dm.calcNormals = emDM_calcNormals;
1758         bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
1759         bmdm->dm.recalcTessellation = emDM_recalcTessellation;
1760
1761         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
1762         bmdm->dm.foreachMappedLoop = emDM_foreachMappedLoop;
1763         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
1764         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
1765
1766         bmdm->dm.drawEdges = emDM_drawEdges;
1767         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
1768         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
1769         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
1770         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
1771         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
1772         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
1773         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
1774         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
1775         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
1776
1777         bmdm->dm.release = emDM_release;
1778
1779         bmdm->vertexCos = (const float (*)[3])vertexCos;
1780         bmdm->dm.deformedOnly = (vertexCos != NULL);
1781
1782         if (cd_dvert_offset != -1) {
1783                 BMIter iter;
1784                 BMVert *eve;
1785                 int i;
1786
1787                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
1788
1789                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1790                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
1791                                          BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
1792                 }
1793         }
1794
1795         if (cd_skin_offset != -1) {
1796                 BMIter iter;
1797                 BMVert *eve;
1798                 int i;
1799
1800                 DM_add_vert_layer(&bmdm->dm, CD_MVERT_SKIN, CD_CALLOC, NULL);
1801
1802                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1803                         DM_set_vert_data(&bmdm->dm, i, CD_MVERT_SKIN,
1804                                          BM_ELEM_CD_GET_VOID_P(eve, cd_skin_offset));
1805                 }
1806         }
1807
1808         return (DerivedMesh *)bmdm;
1809 }
1810
1811
1812
1813 /* -------------------------------------------------------------------- */
1814 /* StatVis Functions */
1815
1816 static void axis_from_enum_v3(float v[3], const char axis)
1817 {
1818         zero_v3(v);
1819         if (axis < 3) v[axis]     =  1.0f;
1820         else          v[axis - 3] = -1.0f;
1821 }
1822
1823 static void statvis_calc_overhang(
1824         BMEditMesh *em,
1825         const float (*polyNos)[3],
1826         /* values for calculating */
1827         const float min, const float max, const char axis,
1828         /* result */
1829         unsigned char (*r_face_colors)[4])
1830 {
1831         BMIter iter;
1832         BMesh *bm = em->bm;
1833         BMFace *f;
1834         float dir[3];
1835         int index;
1836         const float minmax_irange = 1.0f / (max - min);
1837         bool is_max;
1838
1839         /* fallback */
1840         unsigned char col_fallback[4] = {64, 64, 64, 255}; /* gray */
1841         unsigned char col_fallback_max[4] = {0,  0,  0,  255}; /* max color */
1842
1843         BLI_assert(min <= max);
1844
1845         axis_from_enum_v3(dir, axis);
1846
1847         if (LIKELY(em->ob)) {
1848                 mul_transposed_mat3_m4_v3(em->ob->obmat, dir);
1849                 normalize_v3(dir);
1850         }
1851
1852         /* fallback max */
1853         {
1854                 float fcol[3];
1855                 weight_to_rgb(fcol, 1.0f);
1856                 rgb_float_to_uchar(col_fallback_max, fcol);
1857         }
1858
1859         /* now convert into global space */
1860         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
1861                 float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI;
1862
1863                 /* remap */
1864                 if ((is_max = (fac <= max)) && (fac >= min)) {
1865                         float fcol[3];
1866                         fac = (fac - min) * minmax_irange;
1867                         fac = 1.0f - fac;
1868                         CLAMP(fac, 0.0f, 1.0f);
1869                         weight_to_rgb(fcol, fac);
1870                         rgb_float_to_uchar(r_face_colors[index], fcol);
1871                 }
1872                 else {
1873                         unsigned char *fallback = is_max ? col_fallback_max : col_fallback;
1874                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)fallback);
1875                 }
1876         }
1877 }
1878
1879 /* so we can use jitter values for face interpolation */
1880 static void uv_from_jitter_v2(float uv[2])
1881 {
1882         uv[0] += 0.5f;
1883         uv[1] += 0.5f;
1884         if (uv[0] + uv[1] > 1.0f) {
1885                 uv[0] = 1.0f - uv[0];
1886                 uv[1] = 1.0f - uv[1];
1887         }
1888
1889         CLAMP(uv[0], 0.0f, 1.0f);
1890         CLAMP(uv[1], 0.0f, 1.0f);
1891 }
1892
1893 static void statvis_calc_thickness(
1894         BMEditMesh *em,
1895         const float (*vertexCos)[3],
1896         /* values for calculating */
1897         const float min, const float max, const int samples,
1898         /* result */
1899         unsigned char (*r_face_colors)[4])
1900 {
1901         const float eps_offset = 0.00002f;  /* values <= 0.00001 give errors */
1902         float *face_dists = (float *)r_face_colors;  /* cheating */
1903         const bool use_jit = samples < 32;
1904         float jit_ofs[32][2];
1905         BMesh *bm = em->bm;
1906         const int tottri = em->tottri;
1907         const float minmax_irange = 1.0f / (max - min);
1908         int i;
1909
1910         struct BMLoop *(*looptris)[3] = em->looptris;
1911
1912         /* fallback */
1913         const char col_fallback[4] = {64, 64, 64, 255};
1914
1915         struct BMBVHTree *bmtree;
1916
1917         BLI_assert(min <= max);
1918
1919         fill_vn_fl(face_dists, em->bm->totface, max);
1920
1921         if (use_jit) {
1922                 int j;
1923                 BLI_assert(samples < 32);
1924                 BLI_jitter_init(jit_ofs, samples);
1925
1926                 for (j = 0; j < samples; j++) {
1927                         uv_from_jitter_v2(jit_ofs[j]);
1928                 }
1929         }
1930
1931         BM_mesh_elem_index_ensure(bm, BM_FACE);
1932         if (vertexCos) {
1933                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1934         }
1935
1936         bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
1937
1938         for (i = 0; i < tottri; i++) {
1939                 BMFace *f_hit;
1940                 BMLoop **ltri = looptris[i];
1941                 const int index = BM_elem_index_get(ltri[0]->f);
1942                 const float *cos[3];
1943                 float ray_co[3];
1944                 float ray_no[3];
1945
1946                 if (vertexCos) {
1947                         cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)];
1948                         cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)];
1949                         cos[2] = vertexCos[BM_elem_index_get(ltri[2]->v)];
1950                 }
1951                 else {
1952                         cos[0] = ltri[0]->v->co;
1953                         cos[1] = ltri[1]->v->co;
1954                         cos[2] = ltri[2]->v->co;
1955                 }
1956
1957                 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
1958
1959 #define FACE_RAY_TEST_ANGLE \
1960                 f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, \
1961                                            &dist, NULL, NULL); \
1962                 if (f_hit && dist < face_dists[index]) { \
1963                         float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
1964                         angle_fac = 1.0f - angle_fac; \
1965                         angle_fac = angle_fac * angle_fac * angle_fac; \
1966                         angle_fac = 1.0f - angle_fac; \
1967                         dist /= angle_fac; \
1968                         if (dist < face_dists[index]) { \
1969                                 face_dists[index] = dist; \
1970                         } \
1971                 } (void)0
1972
1973                 if (use_jit) {
1974                         int j;
1975                         for (j = 0; j < samples; j++) {
1976                                 float dist = face_dists[index];
1977                                 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
1978                                 madd_v3_v3fl(ray_co, ray_no, eps_offset);
1979
1980                                 FACE_RAY_TEST_ANGLE;
1981                         }
1982                 }
1983                 else {
1984                         float dist = face_dists[index];
1985                         mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]);
1986                         madd_v3_v3fl(ray_co, ray_no, eps_offset);
1987
1988                         FACE_RAY_TEST_ANGLE;
1989                 }
1990         }
1991
1992         BKE_bmbvh_free(bmtree);
1993
1994         /* convert floats into color! */
1995         for (i = 0; i < bm->totface; i++) {
1996                 float fac = face_dists[i];
1997
1998                 /* important not '<=' */
1999                 if (fac < max) {
2000                         float fcol[3];
2001                         fac = (fac - min) * minmax_irange;
2002                         fac = 1.0f - fac;
2003                         CLAMP(fac, 0.0f, 1.0f);
2004                         weight_to_rgb(fcol, fac);
2005                         rgb_float_to_uchar(r_face_colors[i], fcol);
2006                 }
2007                 else {
2008                         copy_v4_v4_char((char *)r_face_colors[i], (const char *)col_fallback);
2009                 }
2010         }
2011 }
2012
2013 static void statvis_calc_intersect(
2014         BMEditMesh *em,
2015         const float (*vertexCos)[3],
2016         /* result */
2017         unsigned char (*r_face_colors)[4])
2018 {
2019         BMIter iter;
2020         BMesh *bm = em->bm;
2021         BMEdge *e;
2022         int index;
2023
2024         /* fallback */
2025         // const char col_fallback[4] = {64, 64, 64, 255};
2026
2027         struct BMBVHTree *bmtree;
2028
2029         memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
2030
2031         BM_mesh_elem_index_ensure(bm, BM_FACE);
2032         if (vertexCos) {
2033                 BM_mesh_elem_index_ensure(bm, BM_VERT);
2034         }
2035
2036         bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
2037
2038         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2039                 BMFace *f_hit;
2040                 float cos[2][3];
2041                 float cos_mid[3];
2042                 float ray_no[3];
2043
2044                 if (e->l == NULL)
2045                         continue;
2046
2047                 if (vertexCos) {
2048                         copy_v3_v3(cos[0], vertexCos[BM_elem_index_get(e->v1)]);
2049                         copy_v3_v3(cos[1], vertexCos[BM_elem_index_get(e->v2)]);
2050                 }
2051                 else {
2052                         copy_v3_v3(cos[0], e->v1->co);
2053                         copy_v3_v3(cos[1], e->v2->co);
2054                 }
2055
2056                 mid_v3_v3v3(cos_mid, cos[0], cos[1]);
2057                 sub_v3_v3v3(ray_no, cos[1], cos[0]);
2058
2059                 f_hit = BKE_bmbvh_find_face_segment(bmtree, cos[0], cos[1],
2060                                                     NULL, NULL, NULL);
2061
2062                 if (f_hit) {
2063                         BMLoop *l_iter, *l_first;
2064                         float fcol[3];
2065
2066                         index = BM_elem_index_get(f_hit);
2067                         weight_to_rgb(fcol, 1.0f);
2068                         rgb_float_to_uchar(r_face_colors[index], fcol);
2069
2070                         l_iter = l_first = e->l;
2071                         do {
2072                                 index = BM_elem_index_get(l_iter->f);
2073                                 weight_to_rgb(fcol, 1.0f);
2074                                 rgb_float_to_uchar(r_face_colors[index], fcol);
2075                         } while ((l_iter = l_iter->radial_next) != l_first);
2076                 }
2077
2078         }
2079
2080         BKE_bmbvh_free(bmtree);
2081 }
2082
2083 static void statvis_calc_distort(
2084         BMEditMesh *em,
2085         const float (*vertexCos)[3], const float (*polyNos)[3],
2086         /* values for calculating */
2087         const float min, const float max,
2088         /* result */
2089         unsigned char (*r_face_colors)[4])
2090 {
2091         BMIter iter;
2092         BMesh *bm = em->bm;
2093         BMFace *f;
2094         const float *f_no;
2095         int index;
2096         const float minmax_irange = 1.0f / (max - min);
2097
2098         /* fallback */
2099         const char col_fallback[4] = {64, 64, 64, 255};
2100
2101         /* now convert into global space */
2102         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2103                 float fac;
2104
2105                 if (f->len == 3) {
2106                         fac = -1.0f;
2107                 }
2108                 else {
2109                         BMLoop *l_iter, *l_first;
2110                         if (vertexCos) {
2111                                 f_no = polyNos[index];
2112                         }
2113                         else {
2114                                 f_no = f->no;
2115                         }
2116
2117                         fac = 0.0f;
2118                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2119                         do {
2120                                 float no_corner[3];
2121                                 if (vertexCos) {
2122                                         normal_tri_v3(no_corner,
2123                                                       vertexCos[BM_elem_index_get(l_iter->prev->v)],
2124                                                       vertexCos[BM_elem_index_get(l_iter->v)],
2125                                                       vertexCos[BM_elem_index_get(l_iter->next->v)]);
2126                                 }
2127                                 else {
2128                                         BM_loop_calc_face_normal(l_iter, no_corner);
2129                                 }
2130                                 /* simple way to detect (what is most likely) concave */
2131                                 if (dot_v3v3(f_no, no_corner) < 0.0f) {
2132                                         negate_v3(no_corner);
2133                                 }
2134                                 fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
2135                         } while ((l_iter = l_iter->next) != l_first);
2136                         fac *= 2.0f;
2137                 }
2138
2139                 /* remap */
2140                 if (fac >= min) {
2141                         float fcol[3];
2142                         fac = (fac - min) * minmax_irange;
2143                         CLAMP(fac, 0.0f, 1.0f);
2144                         weight_to_rgb(fcol, fac);
2145                         rgb_float_to_uchar(r_face_colors[index], fcol);
2146                 }
2147                 else {
2148                         copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
2149                 }
2150         }
2151 }
2152
2153 static void statvis_calc_sharp(
2154         BMEditMesh *em,
2155         const float (*vertexCos)[3],
2156         /* values for calculating */
2157         const float min, const float max,
2158         /* result */
2159         unsigned char (*r_vert_colors)[4])
2160 {
2161         float *vert_angles = (float *)r_vert_colors;  /* cheating */
2162         BMIter iter;
2163         BMesh *bm = em->bm;
2164         BMEdge *e;
2165         //float f_no[3];
2166         const float minmax_irange = 1.0f / (max - min);
2167         int i;
2168
2169         /* fallback */
2170         const char col_fallback[4] = {64, 64, 64, 255};
2171
2172         (void)vertexCos;  /* TODO */
2173
2174         fill_vn_fl(vert_angles, em->bm->totvert, -M_PI);
2175
2176         /* first assign float values to verts */
2177         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2178                 float angle = BM_edge_calc_face_angle_signed(e);
2179                 float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
2180                 float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
2181                 *col1 = max_ff(*col1, angle);
2182                 *col2 = max_ff(*col2, angle);
2183         }
2184
2185         /* convert floats into color! */
2186         for (i = 0; i < bm->totvert; i++) {
2187                 float fac = vert_angles[i];
2188
2189                 /* important not '<=' */
2190                 if (fac > min) {
2191                         float fcol[3];
2192                         fac = (fac - min) * minmax_irange;
2193                         CLAMP(fac, 0.0f, 1.0f);
2194                         weight_to_rgb(fcol, fac);
2195                         rgb_float_to_uchar(r_vert_colors[i], fcol);
2196                 }
2197                 else {
2198                         copy_v4_v4_char((char *)r_vert_colors[i], (const char *)col_fallback);
2199                 }
2200         }
2201 }
2202
2203 void BKE_editmesh_statvis_calc(BMEditMesh *em, DerivedMesh *dm,
2204                                MeshStatVis *statvis)
2205 {
2206         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2207         BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH);
2208
2209         switch (statvis->type) {
2210                 case SCE_STATVIS_OVERHANG:
2211                 {
2212                         BKE_editmesh_color_ensure(em, BM_FACE);
2213                         statvis_calc_overhang(
2214                                     em, bmdm ? bmdm->polyNos : NULL,
2215                                     statvis->overhang_min / (float)M_PI,
2216                                     statvis->overhang_max / (float)M_PI,
2217                                     statvis->overhang_axis,
2218                                     em->derivedFaceColor);
2219                         break;
2220                 }
2221                 case SCE_STATVIS_THICKNESS:
2222                 {
2223                         const float scale = 1.0f / mat4_to_scale(em->ob->obmat);
2224                         BKE_editmesh_color_ensure(em, BM_FACE);
2225                         statvis_calc_thickness(
2226                                     em, bmdm ? bmdm->vertexCos : NULL,
2227                                     statvis->thickness_min * scale,
2228                                     statvis->thickness_max * scale,
2229                                     statvis->thickness_samples,
2230                                     em->derivedFaceColor);
2231                         break;
2232                 }
2233                 case SCE_STATVIS_INTERSECT:
2234                 {
2235                         BKE_editmesh_color_ensure(em, BM_FACE);
2236                         statvis_calc_intersect(
2237                                     em, bmdm ? bmdm->vertexCos : NULL,
2238                                     em->derivedFaceColor);
2239                         break;
2240                 }
2241                 case SCE_STATVIS_DISTORT:
2242                 {
2243                         BKE_editmesh_color_ensure(em, BM_FACE);
2244
2245                         if (bmdm)
2246                                 emDM_ensurePolyNormals(bmdm);
2247
2248                         statvis_calc_distort(
2249                                 em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL,
2250                                 statvis->distort_min,
2251                                 statvis->distort_max,
2252                                 em->derivedFaceColor);
2253                         break;
2254                 }
2255                 case SCE_STATVIS_SHARP:
2256                 {
2257                         BKE_editmesh_color_ensure(em, BM_VERT);
2258                         statvis_calc_sharp(
2259                                 em, bmdm ? bmdm->vertexCos : NULL,
2260                                 statvis->sharp_min,
2261                                 statvis->sharp_max,
2262                                 /* in this case they are vertex colors */
2263                                 em->derivedVertColor);
2264                         break;
2265                 }
2266         }
2267 }
2268
2269
2270
2271 /* -------------------------------------------------------------------- */
2272 /* Editmesh Vert Coords */
2273
2274 struct CageUserData {
2275         int totvert;
2276         float (*cos_cage)[3];
2277         BLI_bitmap *visit_bitmap;
2278 };
2279
2280 static void cage_mapped_verts_callback(void *userData, int index, const float co[3],
2281                                        const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2282 {
2283         struct CageUserData *data = userData;
2284
2285         if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
2286                 BLI_BITMAP_ENABLE(data->visit_bitmap, index);
2287                 copy_v3_v3(data->cos_cage[index], co);
2288         }
2289 }
2290
2291 float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
2292 {
2293         DerivedMesh *cage, *final;
2294         BLI_bitmap *visit_bitmap;
2295         struct CageUserData data;
2296         float (*cos_cage)[3];
2297
2298         cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, &final, CD_MASK_BAREMESH);
2299         cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
2300
2301         /* when initializing cage verts, we only want the first cage coordinate for each vertex,
2302          * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
2303         visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2304
2305         data.totvert = em->bm->totvert;
2306         data.cos_cage = cos_cage;
2307         data.visit_bitmap = visit_bitmap;
2308
2309         cage->foreachMappedVert(cage, cage_mapped_verts_callback, &data, DM_FOREACH_NOP);
2310
2311         MEM_freeN(visit_bitmap);
2312
2313         if (r_numVerts) {
2314                 *r_numVerts = em->bm->totvert;
2315         }
2316
2317         return cos_cage;
2318 }