BMesh: move safe loop-normal-calc to own function
[blender.git] / source / blender / blenkernel / intern / editderivedmesh.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/editderivedmesh.c
29  *  \ingroup bke
30  *
31  * 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 #include "BLI_task.h"
48
49 #include "BKE_cdderivedmesh.h"
50 #include "BKE_mesh.h"
51 #include "BKE_editmesh.h"
52 #include "BKE_editmesh_bvh.h"
53
54 #include "DNA_scene_types.h"
55 #include "DNA_object_types.h"
56
57 #include "MEM_guardedalloc.h"
58
59 #include "GPU_glew.h"
60 #include "GPU_buffers.h"
61 #include "GPU_shader.h"
62 #include "GPU_basic_shader.h"
63
64 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]);
65
66 typedef struct EditDerivedBMesh {
67         DerivedMesh dm;
68
69         BMEditMesh *em;
70
71         /** when set, \a vertexNos, polyNos are lazy initialized */
72         const float (*vertexCos)[3];
73
74         /** lazy initialize (when \a vertexCos is set) */
75         float const (*vertexNos)[3];
76         float const (*polyNos)[3];
77         /** also lazy init but dont depend on \a vertexCos */
78         const float (*polyCos)[3];
79 } EditDerivedBMesh;
80
81 /* -------------------------------------------------------------------- */
82 /* Lazy initialize datastructures */
83
84 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm);
85
86 static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm)
87 {
88         if (bmdm->vertexCos && (bmdm->vertexNos == NULL)) {
89
90                 BMesh *bm = bmdm->em->bm;
91                 const float (*vertexCos)[3], (*polyNos)[3];
92                 float (*vertexNos)[3];
93
94                 /* calculate vertex normals from poly normals */
95                 emDM_ensurePolyNormals(bmdm);
96
97                 BM_mesh_elem_index_ensure(bm, BM_FACE);
98
99                 polyNos = bmdm->polyNos;
100                 vertexCos = bmdm->vertexCos;
101                 vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__);
102
103                 BM_verts_calc_normal_vcos(bm, polyNos, vertexCos, vertexNos);
104
105                 bmdm->vertexNos = (const float (*)[3])vertexNos;
106         }
107 }
108
109 static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm)
110 {
111         if (bmdm->vertexCos && (bmdm->polyNos == NULL)) {
112                 BMesh *bm = bmdm->em->bm;
113                 const float (*vertexCos)[3];
114                 float (*polyNos)[3];
115
116                 BMFace *efa;
117                 BMIter fiter;
118                 int i;
119
120                 BM_mesh_elem_index_ensure(bm, BM_VERT);
121
122                 polyNos = MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__);
123
124                 vertexCos = bmdm->vertexCos;
125
126                 BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
127                         BM_elem_index_set(efa, i); /* set_inline */
128                         BM_face_calc_normal_vcos(bm, efa, polyNos[i], vertexCos);
129                 }
130                 bm->elem_index_dirty &= ~BM_FACE;
131
132                 bmdm->polyNos = (const float (*)[3])polyNos;
133         }
134 }
135
136 static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm)
137 {
138         if (bmdm->polyCos == NULL) {
139                 BMesh *bm = bmdm->em->bm;
140                 float (*polyCos)[3];
141
142                 BMFace *efa;
143                 BMIter fiter;
144                 int i;
145
146                 polyCos = MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__);
147
148                 if (bmdm->vertexCos) {
149                         const float (*vertexCos)[3];
150                         vertexCos = bmdm->vertexCos;
151
152                         BM_mesh_elem_index_ensure(bm, BM_VERT);
153
154                         BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
155                                 BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos);
156                         }
157                 }
158                 else {
159                         BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
160                                 BM_face_calc_center_mean(efa, polyCos[i]);
161                         }
162                 }
163
164                 bmdm->polyCos = (const float (*)[3])polyCos;
165         }
166 }
167
168 static void emDM_calcNormals(DerivedMesh *dm)
169 {
170         /* Nothing to do: normals are already calculated and stored on the
171          * BMVerts and BMFaces */
172         dm->dirty &= ~DM_DIRTY_NORMALS;
173 }
174
175 static void emDM_calcLoopNormalsSpaceArray(
176         DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr);
177
178 static void emDM_calcLoopNormals(DerivedMesh *dm, const bool use_split_normals, const float split_angle)
179 {
180         emDM_calcLoopNormalsSpaceArray(dm, use_split_normals, split_angle, NULL);
181 }
182
183 /* #define DEBUG_CLNORS */
184
185 static void emDM_calcLoopNormalsSpaceArray(
186         DerivedMesh *dm, const bool use_split_normals, const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr)
187 {
188         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
189         BMesh *bm = bmdm->em->bm;
190         const float (*vertexCos)[3], (*vertexNos)[3], (*polyNos)[3];
191         float (*loopNos)[3];
192         short (*clnors_data)[2];
193         int cd_loop_clnors_offset;
194
195         /* calculate loop normals from poly and vertex normals */
196         emDM_ensureVertNormals(bmdm);
197         emDM_ensurePolyNormals(bmdm);
198         dm->dirty &= ~DM_DIRTY_NORMALS;
199
200         vertexCos = bmdm->vertexCos;
201         vertexNos = bmdm->vertexNos;
202         polyNos = bmdm->polyNos;
203
204         loopNos = dm->getLoopDataArray(dm, CD_NORMAL);
205         if (!loopNos) {
206                 DM_add_loop_layer(dm, CD_NORMAL, CD_CALLOC, NULL);
207                 loopNos = dm->getLoopDataArray(dm, CD_NORMAL);
208         }
209
210         /* We can have both, give priority to dm's data, and fallback to bm's ones. */
211         clnors_data = dm->getLoopDataArray(dm, CD_CUSTOMLOOPNORMAL);
212         cd_loop_clnors_offset = clnors_data ? -1 : CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
213
214         BM_loops_calc_normal_vcos(bm, vertexCos, vertexNos, polyNos, use_split_normals, split_angle, loopNos,
215                                   r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
216 #ifdef DEBUG_CLNORS
217         if (r_lnors_spacearr) {
218                 int i;
219                 for (i = 0; i < numLoops; i++) {
220                         if (r_lnors_spacearr->lspacearr[i]->ref_alpha != 0.0f) {
221                                 LinkNode *loops = r_lnors_spacearr->lspacearr[i]->loops;
222                                 printf("Loop %d uses lnor space %p:\n", i, r_lnors_spacearr->lspacearr[i]);
223                                 print_v3("\tfinal lnor:", loopNos[i]);
224                                 print_v3("\tauto lnor:", r_lnors_spacearr->lspacearr[i]->vec_lnor);
225                                 print_v3("\tref_vec:", r_lnors_spacearr->lspacearr[i]->vec_ref);
226                                 printf("\talpha: %f\n\tbeta: %f\n\tloops: %p\n", r_lnors_spacearr->lspacearr[i]->ref_alpha,
227                                        r_lnors_spacearr->lspacearr[i]->ref_beta, r_lnors_spacearr->lspacearr[i]->loops);
228                                 printf("\t\t(shared with loops");
229                                 while (loops) {
230                                         printf(" %d", GET_INT_FROM_POINTER(loops->link));
231                                         loops = loops->next;
232                                 }
233                                 printf(")\n");
234                         }
235                         else {
236                                 printf("Loop %d has no lnor space\n", i);
237                         }
238                 }
239         }
240 #endif
241 }
242
243
244 /** \name Tangent Space Calculation
245  * \{ */
246
247 /* Necessary complexity to handle looptri's as quads for correct tangents */
248 #define USE_LOOPTRI_DETECT_QUADS
249
250 typedef struct {
251         const float (*precomputedFaceNormals)[3];
252         const float (*precomputedLoopNormals)[3];
253         const BMLoop *(*looptris)[3];
254         int cd_loop_uv_offset;   /* texture coordinates */
255         const float (*orco)[3];
256         float (*tangent)[4];    /* destination */
257         int numTessFaces;
258
259 #ifdef USE_LOOPTRI_DETECT_QUADS
260         /* map from 'fake' face index to looptri,
261          * quads will point to the first looptri of the quad */
262         const int    *face_as_quad_map;
263         int       num_face_as_quad_map;
264 #endif
265
266 } SGLSLEditMeshToTangent;
267
268 #ifdef USE_LOOPTRI_DETECT_QUADS
269 /* seems weak but only used on quads */
270 static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
271 {
272         const BMLoop *l = BM_FACE_FIRST_LOOP(f);
273         while (vert_index--) {
274                 l = l->next;
275         }
276         return l;
277 }
278 #endif
279
280 /* interface */
281 #include "mikktspace.h"
282
283 static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
284 {
285         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
286
287 #ifdef USE_LOOPTRI_DETECT_QUADS
288         return pMesh->num_face_as_quad_map;
289 #else
290         return pMesh->numTessFaces;
291 #endif
292 }
293
294 static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
295 {
296 #ifdef USE_LOOPTRI_DETECT_QUADS
297         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
298         if (pMesh->face_as_quad_map) {
299                 const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
300                 if (lt[0]->f->len == 4) {
301                         return 4;
302                 }
303         }
304         return 3;
305 #else
306         UNUSED_VARS(pContext, face_num);
307         return 3;
308 #endif
309 }
310
311 static void emdm_ts_GetPosition(
312         const SMikkTSpaceContext *pContext, float r_co[3],
313         const int face_num, const int vert_index)
314 {
315         //assert(vert_index >= 0 && vert_index < 4);
316         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
317         const BMLoop **lt;
318         const BMLoop *l;
319
320 #ifdef USE_LOOPTRI_DETECT_QUADS
321         if (pMesh->face_as_quad_map) {
322                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
323                 if (lt[0]->f->len == 4) {
324                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
325                         goto finally;
326                 }
327                 /* fall through to regular triangle */
328         }
329         else {
330                 lt = pMesh->looptris[face_num];
331         }
332 #else
333         lt = pMesh->looptris[face_num];
334 #endif
335         l = lt[vert_index];
336
337         const float *co;
338
339 finally:
340         co = l->v->co;
341         copy_v3_v3(r_co, co);
342 }
343
344 static void emdm_ts_GetTextureCoordinate(
345         const SMikkTSpaceContext *pContext, float r_uv[2],
346         const int face_num, const int vert_index)
347 {
348         //assert(vert_index >= 0 && vert_index < 4);
349         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
350         const BMLoop **lt;
351         const BMLoop *l;
352
353 #ifdef USE_LOOPTRI_DETECT_QUADS
354         if (pMesh->face_as_quad_map) {
355                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
356                 if (lt[0]->f->len == 4) {
357                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
358                         goto finally;
359                 }
360                 /* fall through to regular triangle */
361         }
362         else {
363                 lt = pMesh->looptris[face_num];
364         }
365 #else
366         lt = pMesh->looptris[face_num];
367 #endif
368         l = lt[vert_index];
369
370 finally:
371         if (pMesh->cd_loop_uv_offset != -1) {
372                 const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
373                 copy_v2_v2(r_uv, uv);
374         }
375         else {
376                 const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
377                 map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
378         }
379 }
380
381 static void emdm_ts_GetNormal(
382         const SMikkTSpaceContext *pContext, float r_no[3],
383         const int face_num, const int vert_index)
384 {
385         //assert(vert_index >= 0 && vert_index < 4);
386         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
387         const BMLoop **lt;
388         const BMLoop *l;
389
390 #ifdef USE_LOOPTRI_DETECT_QUADS
391         if (pMesh->face_as_quad_map) {
392                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
393                 if (lt[0]->f->len == 4) {
394                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
395                         goto finally;
396                 }
397                 /* fall through to regular triangle */
398         }
399         else {
400                 lt = pMesh->looptris[face_num];
401         }
402 #else
403         lt = pMesh->looptris[face_num];
404 #endif
405         l = lt[vert_index];
406
407 finally:
408         if (pMesh->precomputedLoopNormals) {
409                 copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
410         }
411         else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) {  /* flat */
412                 if (pMesh->precomputedFaceNormals) {
413                         copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
414                 }
415                 else {
416                         copy_v3_v3(r_no, l->f->no);
417                 }
418         }
419         else {
420                 copy_v3_v3(r_no, l->v->no);
421         }
422 }
423
424 static void emdm_ts_SetTSpace(
425         const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
426         const int face_num, const int vert_index)
427 {
428         //assert(vert_index >= 0 && vert_index < 4);
429         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
430         const BMLoop **lt;
431         const BMLoop *l;
432
433 #ifdef USE_LOOPTRI_DETECT_QUADS
434         if (pMesh->face_as_quad_map) {
435                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
436                 if (lt[0]->f->len == 4) {
437                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
438                         goto finally;
439                 }
440                 /* fall through to regular triangle */
441         }
442         else {
443                 lt = pMesh->looptris[face_num];
444         }
445 #else
446         lt = pMesh->looptris[face_num];
447 #endif
448         l = lt[vert_index];
449
450         float *pRes;
451
452 finally:
453         pRes = pMesh->tangent[BM_elem_index_get(l)];
454         copy_v3_v3(pRes, fvTangent);
455         pRes[3] = fSign;
456 }
457
458 static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
459 {
460         struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
461         /* new computation method */
462         {
463                 SMikkTSpaceContext sContext = {NULL};
464                 SMikkTSpaceInterface sInterface = {NULL};
465                 sContext.m_pUserData = mesh2tangent;
466                 sContext.m_pInterface = &sInterface;
467                 sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
468                 sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
469                 sInterface.m_getPosition = emdm_ts_GetPosition;
470                 sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
471                 sInterface.m_getNormal = emdm_ts_GetNormal;
472                 sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
473                 /* 0 if failed */
474                 genTangSpaceDefault(&sContext);
475         }
476 }
477
478 /**
479  * \see #DM_calc_loop_tangents, same logic but used arrays instead of #BMesh data.
480  *
481  * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
482  * This is done because #CD_TANGENT is cache data used only for drawing.
483  */
484
485 static void emDM_calc_loop_tangents(
486         DerivedMesh *dm, bool calc_active_tangent,
487         const char (*tangent_names)[MAX_NAME], int tangent_names_count)
488 {
489         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
490         BMEditMesh *em = bmdm->em;
491         BMesh *bm = bmdm->em->bm;
492
493         int act_uv_n = -1;
494         int ren_uv_n = -1;
495         bool calc_act = false;
496         bool calc_ren = false;
497         char act_uv_name[MAX_NAME];
498         char ren_uv_name[MAX_NAME];
499         short tangent_mask = 0;
500
501         DM_calc_loop_tangents_step_0(
502                 &bm->ldata, calc_active_tangent, tangent_names, tangent_names_count,
503                 &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
504
505         if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) {
506                 for (int i = 0; i < tangent_names_count; i++)
507                         if (tangent_names[i][0])
508                                 DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]);
509                 if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1)
510                         CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, "");
511                 if (calc_act && act_uv_name[0])
512                         DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name);
513                 if (calc_ren && ren_uv_name[0])
514                         DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, ren_uv_name);
515                 int totface = em->tottri;
516 #ifdef USE_LOOPTRI_DETECT_QUADS
517                 int num_face_as_quad_map;
518                 int *face_as_quad_map = NULL;
519
520                 /* map faces to quads */
521                 if (bmdm->em->tottri != bm->totface) {
522                         /* over alloc, since we dont know how many ngon or quads we have */
523
524                         /* map fake face index to looptri */
525                         face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
526                         int i, j;
527                         for (i = 0, j = 0; j < totface; i++, j++) {
528                                 face_as_quad_map[i] = j;
529                                 /* step over all quads */
530                                 if (em->looptris[j][0]->f->len == 4) {
531                                         j++;  /* skips the nest looptri */
532                                 }
533                         }
534                         num_face_as_quad_map = i;
535                 }
536                 else {
537                         num_face_as_quad_map = totface;
538                 }
539 #endif
540                 /* Calculation */
541                 {
542                         TaskScheduler *scheduler = BLI_task_scheduler_get();
543                         TaskPool *task_pool;
544                         task_pool = BLI_task_pool_create(scheduler, NULL);
545
546                         dm->tangent_mask = 0;
547                         /* Calculate tangent layers */
548                         SGLSLEditMeshToTangent data_array[MAX_MTFACE];
549                         int index = 0;
550                         int n = 0;
551                         CustomData_update_typemap(&dm->loopData);
552                         const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT);
553                         for (n = 0; n < tangent_layer_num; n++) {
554                                 index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n);
555                                 BLI_assert(n < MAX_MTFACE);
556                                 SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
557                                 mesh2tangent->numTessFaces = em->tottri;
558 #ifdef USE_LOOPTRI_DETECT_QUADS
559                                 mesh2tangent->face_as_quad_map = face_as_quad_map;
560                                 mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
561 #endif
562                                 mesh2tangent->precomputedFaceNormals = bmdm->polyNos;  /* dm->getPolyDataArray(dm, CD_NORMAL) */
563                                 /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
564                                  * have to check this is valid...
565                                  */
566                                 mesh2tangent->precomputedLoopNormals = CustomData_get_layer(&dm->loopData, CD_NORMAL);
567                                 mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
568
569                                 /* needed for indexing loop-tangents */
570                                 int htype_index = BM_LOOP;
571                                 if (mesh2tangent->cd_loop_uv_offset == -1) {
572                                         mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO);
573                                         if (!mesh2tangent->orco)
574                                                 continue;
575                                         /* needed for orco lookups */
576                                         htype_index |= BM_VERT;
577                                         dm->tangent_mask |= DM_TANGENT_MASK_ORCO;
578                                 }
579                                 else {
580                                         /* Fill the resulting tangent_mask */
581                                         int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name);
582                                         int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
583                                         BLI_assert(uv_ind != -1 && uv_start != -1);
584                                         BLI_assert(uv_ind - uv_start < MAX_MTFACE);
585                                         dm->tangent_mask |= 1 << (uv_ind - uv_start);
586                                 }
587
588                                 if (mesh2tangent->precomputedFaceNormals) {
589                                         /* needed for face normal lookups */
590                                         htype_index |= BM_FACE;
591                                 }
592                                 BM_mesh_elem_index_ensure(bm, htype_index);
593
594                                 mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
595                                 mesh2tangent->tangent = dm->loopData.layers[index].data;
596
597                                 BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
598                         }
599
600                         BLI_assert(dm->tangent_mask == tangent_mask);
601                         BLI_task_pool_work_and_wait(task_pool);
602                         BLI_task_pool_free(task_pool);
603                 }
604 #ifdef USE_LOOPTRI_DETECT_QUADS
605                 if (face_as_quad_map) {
606                         MEM_freeN(face_as_quad_map);
607                 }
608 #undef USE_LOOPTRI_DETECT_QUADS
609 #endif
610         }
611
612         /* Update active layer index */
613         int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
614         if (act_uv_index >= 0) {
615                 int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
616                 CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
617         } /* else tangent has been built from orco */
618
619         /* Update render layer index */
620         int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
621         if (ren_uv_index >= 0) {
622                 int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
623                 CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
624         } /* else tangent has been built from orco */
625 }
626
627 /** \} */
628
629
630 static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
631 {
632         /* do nothing */
633 }
634
635 static void emDM_recalcLoopTri(DerivedMesh *dm)
636 {
637         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
638         BMLoop *(*looptris)[3] = bmdm->em->looptris;
639         MLoopTri *mlooptri;
640         const int tottri = bmdm->em->tottri;
641         int i;
642
643         DM_ensure_looptri_data(dm);
644         mlooptri = dm->looptris.array;
645
646         BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
647         BLI_assert(tottri == dm->looptris.num);
648
649         BM_mesh_elem_index_ensure(bmdm->em->bm, BM_FACE | BM_LOOP);
650
651         for (i = 0; i < tottri; i++) {
652                 BMLoop **ltri = looptris[i];
653                 MLoopTri *lt = &mlooptri[i];
654
655                 ARRAY_SET_ITEMS(
656                         lt->tri,
657                         BM_elem_index_get(ltri[0]),
658                         BM_elem_index_get(ltri[1]),
659                         BM_elem_index_get(ltri[2]));
660                 lt->poly = BM_elem_index_get(ltri[0]->f);
661         }
662 }
663
664 static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
665 {
666         if (dm->looptris.array) {
667                 BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
668         }
669         else {
670                 dm->recalcLoopTri(dm);
671         }
672
673         return dm->looptris.array;
674 }
675
676 static void emDM_foreachMappedVert(
677         DerivedMesh *dm,
678         void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
679         void *userData,
680         DMForeachFlag flag)
681 {
682         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
683         BMesh *bm = bmdm->em->bm;
684         BMVert *eve;
685         BMIter iter;
686         int i;
687
688         if (bmdm->vertexCos) {
689                 const float (*vertexCos)[3] = bmdm->vertexCos;
690                 const float (*vertexNos)[3];
691
692                 if (flag & DM_FOREACH_USE_NORMAL) {
693                         emDM_ensureVertNormals(bmdm);
694                         vertexNos = bmdm->vertexNos;
695                 }
696                 else {
697                         vertexNos = NULL;
698                 }
699
700                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
701                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL;
702                         func(userData, i, vertexCos[i], no, NULL);
703                 }
704         }
705         else {
706                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
707                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? eve->no : NULL;
708                         func(userData, i, eve->co, no, NULL);
709                 }
710         }
711 }
712 static void emDM_foreachMappedEdge(
713         DerivedMesh *dm,
714         void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
715         void *userData)
716 {
717         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
718         BMesh *bm = bmdm->em->bm;
719         BMEdge *eed;
720         BMIter iter;
721         int i;
722
723         if (bmdm->vertexCos) {
724
725                 BM_mesh_elem_index_ensure(bm, BM_VERT);
726
727                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
728                         func(userData, i,
729                              bmdm->vertexCos[BM_elem_index_get(eed->v1)],
730                              bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
731                 }
732         }
733         else {
734                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
735                         func(userData, i, eed->v1->co, eed->v2->co);
736                 }
737         }
738 }
739
740 static void emDM_drawMappedEdges(
741         DerivedMesh *dm,
742         DMSetDrawOptions setDrawOptions,
743         void *userData)
744 {
745         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
746         BMesh *bm = bmdm->em->bm;
747         BMEdge *eed;
748         BMIter iter;
749         int i;
750
751         if (bmdm->vertexCos) {
752
753                 BM_mesh_elem_index_ensure(bm, BM_VERT);
754
755                 glBegin(GL_LINES);
756                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
757                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
758                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
759                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
760                         }
761                 }
762                 glEnd();
763         }
764         else {
765                 glBegin(GL_LINES);
766                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
767                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
768                                 glVertex3fv(eed->v1->co);
769                                 glVertex3fv(eed->v2->co);
770                         }
771                 }
772                 glEnd();
773         }
774 }
775 static void emDM_drawEdges(
776         DerivedMesh *dm,
777         bool UNUSED(drawLooseEdges),
778         bool UNUSED(drawAllEdges))
779 {
780         emDM_drawMappedEdges(dm, NULL, NULL);
781 }
782
783 static void emDM_drawMappedEdgesInterp(
784         DerivedMesh *dm,
785         DMSetDrawOptions setDrawOptions,
786         DMSetDrawInterpOptions setDrawInterpOptions,
787         void *userData)
788 {
789         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
790         BMesh *bm = bmdm->em->bm;
791         BMEdge *eed;
792         BMIter iter;
793         int i;
794
795         if (bmdm->vertexCos) {
796
797                 BM_mesh_elem_index_ensure(bm, BM_VERT);
798
799                 glBegin(GL_LINES);
800                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
801                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
802                                 setDrawInterpOptions(userData, i, 0.0);
803                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
804                                 setDrawInterpOptions(userData, i, 1.0);
805                                 glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
806                         }
807                 }
808                 glEnd();
809         }
810         else {
811                 glBegin(GL_LINES);
812                 BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
813                         if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) {
814                                 setDrawInterpOptions(userData, i, 0.0);
815                                 glVertex3fv(eed->v1->co);
816                                 setDrawInterpOptions(userData, i, 1.0);
817                                 glVertex3fv(eed->v2->co);
818                         }
819                 }
820                 glEnd();
821         }
822 }
823
824 static void emDM_drawUVEdges(DerivedMesh *dm)
825 {
826         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
827         BMesh *bm = bmdm->em->bm;
828         BMFace *efa;
829         BMIter iter;
830
831         const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
832
833         if (UNLIKELY(cd_loop_uv_offset == -1)) {
834                 return;
835         }
836
837         glBegin(GL_LINES);
838         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
839                 BMLoop *l_iter, *l_first;
840                 const float *uv, *uv_prev;
841
842                 if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
843                         continue;
844
845                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
846                 uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv;
847                 do {
848                         uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
849                         glVertex2fv(uv);
850                         glVertex2fv(uv_prev);
851                         uv_prev = uv;
852                 } while ((l_iter = l_iter->next) != l_first);
853         }
854         glEnd();
855 }
856
857 static void emDM_foreachMappedLoop(
858         DerivedMesh *dm,
859         void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
860         void *userData,
861         DMForeachFlag flag)
862 {
863         /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
864          * return loop data from bmesh itself. */
865         const float (*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) : NULL;
866
867         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
868         BMesh *bm = bmdm->em->bm;
869         BMFace *efa;
870         BMIter iter;
871
872         const float (*vertexCos)[3] = bmdm->vertexCos;
873         int f_idx;
874
875         BM_mesh_elem_index_ensure(bm, BM_VERT);
876
877         BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) {
878                 BMLoop *l_iter, *l_first;
879
880                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
881                 do {
882                         const BMVert *eve = l_iter->v;
883                         const int v_idx = BM_elem_index_get(eve);
884                         const float *no = lnors ? *lnors++ : NULL;
885                         func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
886                 } while ((l_iter = l_iter->next) != l_first);
887         }
888 }
889
890 static void emDM_foreachMappedFaceCenter(
891         DerivedMesh *dm,
892         void (*func)(void *userData, int index, const float co[3], const float no[3]),
893         void *userData,
894         DMForeachFlag flag)
895 {
896         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
897         BMesh *bm = bmdm->em->bm;
898         const float (*polyNos)[3];
899         const float (*polyCos)[3];
900         BMFace *efa;
901         BMIter iter;
902         int i;
903
904         emDM_ensurePolyCenters(bmdm);
905         polyCos = bmdm->polyCos;  /* always set */
906
907         if (flag & DM_FOREACH_USE_NORMAL) {
908                 emDM_ensurePolyNormals(bmdm);
909                 polyNos = bmdm->polyNos;  /* maybe NULL */
910         }
911         else {
912                 polyNos = NULL;
913         }
914
915         if (polyNos) {
916                 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
917                         const float *no = polyNos[i];
918                         func(userData, i, polyCos[i], no);
919                 }
920         }
921         else {
922                 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
923                         const float *no = (flag & DM_FOREACH_USE_NORMAL) ? efa->no : NULL;
924                         func(userData, i, polyCos[i], no);
925                 }
926         }
927 }
928
929 static void emDM_drawMappedFaces(
930         DerivedMesh *dm,
931         DMSetDrawOptions setDrawOptions,
932         DMSetMaterial setMaterial,
933         /* currently unused -- each original face is handled separately */
934         DMCompareDrawOptions UNUSED(compareDrawOptions),
935         void *userData,
936         DMDrawFlag flag)
937 {
938         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
939         BMEditMesh *em = bmdm->em;
940         BMesh *bm = em->bm;
941         BMFace *efa;
942         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
943         const int tottri = bmdm->em->tottri;
944         DMDrawOption draw_option;
945         int i;
946         const int skip_normals = !(flag & DM_DRAW_NEED_NORMALS);
947         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
948         MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
949         unsigned char(*color_vert_array)[4] = em->derivedVertColor;
950         unsigned char(*color_face_array)[4] = em->derivedFaceColor;
951         bool has_vcol_preview = (color_vert_array != NULL) && !skip_normals;
952         bool has_fcol_preview = (color_face_array != NULL) && !skip_normals;
953         bool has_vcol_any = has_vcol_preview;
954
955         /* GL_ZERO is used to detect if drawing has started or not */
956         GLenum poly_prev = GL_ZERO;
957         GLenum shade_prev = GL_ZERO;
958         DMDrawOption draw_option_prev = DM_DRAW_OPTION_SKIP;
959
960         /* call again below is ok */
961         if (has_vcol_preview) {
962                 BM_mesh_elem_index_ensure(bm, BM_VERT);
963         }
964         if (has_fcol_preview) {
965                 BM_mesh_elem_index_ensure(bm, BM_FACE);
966         }
967         if (has_vcol_preview || has_fcol_preview) {
968                 flag |= DM_DRAW_ALWAYS_SMOOTH;
969                 /* weak, this logic should really be moved higher up */
970                 setMaterial = NULL;
971         }
972
973         if (bmdm->vertexCos) {
974                 short prev_mat_nr = -1;
975
976                 /* add direct access */
977                 const float (*vertexCos)[3] = bmdm->vertexCos;
978                 const float (*vertexNos)[3];
979                 const float (*polyNos)[3];
980
981                 if (skip_normals) {
982                         vertexNos = NULL;
983                         polyNos = NULL;
984                 }
985                 else {
986                         emDM_ensureVertNormals(bmdm);
987                         emDM_ensurePolyNormals(bmdm);
988                         vertexNos = bmdm->vertexNos;
989                         polyNos = bmdm->polyNos;
990                 }
991
992                 BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE);
993
994                 for (i = 0; i < tottri; i++) {
995                         BMLoop **ltri = looptris[i];
996                         int drawSmooth;
997
998                         efa = ltri[0]->f;
999                         drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
1000
1001                         draw_option = (!setDrawOptions ?
1002                                        DM_DRAW_OPTION_NORMAL :
1003                                        setDrawOptions(userData, BM_elem_index_get(efa)));
1004                         if (draw_option != DM_DRAW_OPTION_SKIP) {
1005                                 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
1006
1007                                 if (draw_option_prev != draw_option) {
1008                                         if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) {
1009                                                 if (poly_prev != GL_ZERO) glEnd();
1010                                                 poly_prev = GL_ZERO; /* force glBegin */
1011
1012                                                 GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1013                                         }
1014                                         draw_option_prev = draw_option;
1015                                 }
1016
1017
1018                                 if (efa->mat_nr != prev_mat_nr) {
1019                                         if (setMaterial) {
1020                                                 if (poly_prev != GL_ZERO) glEnd();
1021                                                 poly_prev = GL_ZERO; /* force glBegin */
1022
1023                                                 setMaterial(efa->mat_nr + 1, NULL);
1024                                         }
1025                                         prev_mat_nr = efa->mat_nr;
1026                                 }
1027
1028                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
1029
1030                                         if (poly_prev != GL_ZERO) glEnd();
1031                                         poly_prev = GL_ZERO; /* force glBegin */
1032
1033                                         GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
1034                                         GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
1035                                 }
1036
1037                                 if      (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1038                                 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
1039                                 if (skip_normals) {
1040                                         if (poly_type != poly_prev) {
1041                                                 if (poly_prev != GL_ZERO) glEnd();
1042                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1043                                         }
1044                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1045                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1046                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1047                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1048                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1049                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1050                                 }
1051                                 else {
1052                                         const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
1053                                         if (shade_type != shade_prev) {
1054                                                 if (poly_prev != GL_ZERO) glEnd();
1055                                                 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
1056                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1057                                         }
1058                                         if (poly_type != poly_prev) {
1059                                                 if (poly_prev != GL_ZERO) glEnd();
1060                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1061                                         }
1062
1063                                         if (!drawSmooth) {
1064                                                 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1065                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1066                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1067                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1068                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1069                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1070                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1071                                         }
1072                                         else {
1073                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1074                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1075                                                 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1076                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1077                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1078                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1079                                                 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1080                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1081                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1082                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1083                                                 else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1084                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1085                                         }
1086                                 }
1087                         }
1088                 }
1089         }
1090         else {
1091                 short prev_mat_nr = -1;
1092
1093                 BM_mesh_elem_index_ensure(bm, lnors ? BM_FACE | BM_LOOP : BM_FACE);
1094
1095                 for (i = 0; i < tottri; i++) {
1096                         BMLoop **ltri = looptris[i];
1097                         int drawSmooth;
1098
1099                         efa = ltri[0]->f;
1100                         drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH));
1101                         
1102                         draw_option = (setDrawOptions ?
1103                                            setDrawOptions(userData, BM_elem_index_get(efa)) :
1104                                            DM_DRAW_OPTION_NORMAL);
1105
1106                         if (draw_option != DM_DRAW_OPTION_SKIP) {
1107                                 const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
1108
1109                                 if (draw_option_prev != draw_option) {
1110                                         if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) {
1111                                                 if (poly_prev != GL_ZERO) glEnd();
1112                                                 poly_prev = GL_ZERO; /* force glBegin */
1113
1114                                                 GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1115                                         }
1116                                         draw_option_prev = draw_option;
1117                                 }
1118
1119                                 if (efa->mat_nr != prev_mat_nr) {
1120                                         if (setMaterial) {
1121                                                 if (poly_prev != GL_ZERO) glEnd();
1122                                                 poly_prev = GL_ZERO; /* force glBegin */
1123
1124                                                 setMaterial(efa->mat_nr + 1, NULL);
1125                                         }
1126                                         prev_mat_nr = efa->mat_nr;
1127                                 }
1128                                 
1129                                 if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */
1130
1131                                         if (poly_prev != GL_ZERO) glEnd();
1132                                         poly_prev = GL_ZERO; /* force glBegin */
1133
1134                                         GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
1135                                         GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
1136                                 }
1137
1138                                 if      (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1139                                 else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)]));
1140
1141                                 if (skip_normals) {
1142                                         if (poly_type != poly_prev) {
1143                                                 if (poly_prev != GL_ZERO) glEnd();
1144                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1145                                         }
1146                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1147                                         glVertex3fv(ltri[0]->v->co);
1148                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1149                                         glVertex3fv(ltri[1]->v->co);
1150                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1151                                         glVertex3fv(ltri[2]->v->co);
1152                                 }
1153                                 else {
1154                                         const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT;
1155                                         if (shade_type != shade_prev) {
1156                                                 if (poly_prev != GL_ZERO) glEnd();
1157                                                 glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */
1158                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1159                                         }
1160                                         if (poly_type != poly_prev) {
1161                                                 if (poly_prev != GL_ZERO) glEnd();
1162                                                 glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
1163                                         }
1164
1165                                         if (!drawSmooth) {
1166                                                 glNormal3fv(efa->no);
1167                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1168                                                 glVertex3fv(ltri[0]->v->co);
1169                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1170                                                 glVertex3fv(ltri[1]->v->co);
1171                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1172                                                 glVertex3fv(ltri[2]->v->co);
1173                                         }
1174                                         else {
1175                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1176                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1177                                                 else glNormal3fv(ltri[0]->v->no);
1178                                                 glVertex3fv(ltri[0]->v->co);
1179                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1180                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1181                                                 else glNormal3fv(ltri[1]->v->no);
1182                                                 glVertex3fv(ltri[1]->v->co);
1183                                                 if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1184                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1185                                                 else glNormal3fv(ltri[2]->v->no);
1186                                                 glVertex3fv(ltri[2]->v->co);
1187                                         }
1188                                 }
1189                         }
1190                 }
1191         }
1192
1193         /* if non zero we know a face was rendered */
1194         if (poly_prev != GL_ZERO) glEnd();
1195
1196         if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) {
1197                 GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1198         }
1199
1200         if (shade_prev == GL_FLAT) {
1201                 glShadeModel(GL_SMOOTH);
1202         }
1203 }
1204
1205 static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
1206 {
1207         luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset);
1208         luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset);
1209         luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset);
1210 }
1211
1212 static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset)
1213 {
1214         lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset);
1215         lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset);
1216         lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset);
1217 }
1218
1219 static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4])
1220 {
1221         lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)];
1222         lcol[1] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[1]->v)];
1223         lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)];
1224 }
1225
1226 static void emDM_drawFacesTex_common(
1227         DerivedMesh *dm,
1228         DMSetDrawOptionsTex drawParams,
1229         DMSetDrawOptionsMappedTex drawParamsMapped,
1230         DMCompareDrawOptions compareDrawOptions,
1231         void *userData)
1232 {
1233         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1234         BMEditMesh *em = bmdm->em;
1235         BMesh *bm = em->bm;
1236         struct BMLoop *(*looptris)[3] = em->looptris;
1237         BMFace *efa;
1238         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1239         MLoopUV *luv[3], dummyluv = {{0}};
1240         MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
1241         const int cd_loop_uv_offset    = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
1242         const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
1243         const int cd_poly_tex_offset   = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
1244         unsigned char(*color_vert_array)[4] = em->derivedVertColor;
1245         bool has_uv   = (cd_loop_uv_offset    != -1);
1246         bool has_vcol_preview = (color_vert_array != NULL);
1247         bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false);
1248         bool has_vcol_any = (has_vcol_preview || has_vcol);
1249         int i;
1250
1251         (void) compareDrawOptions;
1252
1253         luv[0] = luv[1] = luv[2] = &dummyluv;
1254
1255         // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255;  /* UNUSED */
1256
1257         /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
1258         BM_mesh_elem_index_ensure(bm, BM_FACE);
1259
1260         /* call again below is ok */
1261         if (has_vcol_preview) {
1262                 BM_mesh_elem_index_ensure(bm, BM_VERT);
1263         }
1264
1265         if (bmdm->vertexCos) {
1266                 /* add direct access */
1267                 const float (*vertexCos)[3] = bmdm->vertexCos;
1268                 const float (*vertexNos)[3];
1269                 const float (*polyNos)[3];
1270
1271                 emDM_ensureVertNormals(bmdm);
1272                 emDM_ensurePolyNormals(bmdm);
1273                 vertexNos = bmdm->vertexNos;
1274                 polyNos = bmdm->polyNos;
1275
1276                 BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
1277
1278                 for (i = 0; i < em->tottri; i++) {
1279                         BMLoop **ltri = looptris[i];
1280                         MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
1281                         /*unsigned char *cp = NULL;*/ /*UNUSED*/
1282                         int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
1283                         DMDrawOption draw_option;
1284
1285                         efa = ltri[0]->f;
1286
1287                         if (drawParams) {
1288                                 draw_option = drawParams(tp, has_vcol, efa->mat_nr);
1289                         }
1290                         else if (drawParamsMapped)
1291                                 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
1292                         else
1293                                 draw_option = DM_DRAW_OPTION_NORMAL;
1294
1295                         if (draw_option != DM_DRAW_OPTION_SKIP) {
1296
1297                                 if      (has_uv)            bmdm_get_tri_uv(ltri,  luv,  cd_loop_uv_offset);
1298                                 if      (has_vcol)          bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
1299                                 else if (has_vcol_preview)  bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1300
1301                                 glBegin(GL_TRIANGLES);
1302                                 if (!drawSmooth) {
1303                                         glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1304
1305                                         glTexCoord2fv(luv[0]->uv);
1306                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1307                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1308
1309                                         glTexCoord2fv(luv[1]->uv);
1310                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1311                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1312
1313                                         glTexCoord2fv(luv[2]->uv);
1314                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1315                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1316                                 }
1317                                 else {
1318                                         glTexCoord2fv(luv[0]->uv);
1319                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1320                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1321                                         else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
1322                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
1323
1324                                         glTexCoord2fv(luv[1]->uv);
1325                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1326                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1327                                         else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
1328                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
1329
1330                                         glTexCoord2fv(luv[2]->uv);
1331                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1332                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1333                                         else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
1334                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
1335                                 }
1336                                 glEnd();
1337                         }
1338                 }
1339         }
1340         else {
1341                 BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
1342
1343                 for (i = 0; i < em->tottri; i++) {
1344                         BMLoop **ltri = looptris[i];
1345                         MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
1346                         /*unsigned char *cp = NULL;*/ /*UNUSED*/
1347                         int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
1348                         DMDrawOption draw_option;
1349
1350                         efa = ltri[0]->f;
1351
1352                         if (drawParams)
1353                                 draw_option = drawParams(tp, has_vcol, efa->mat_nr);
1354                         else if (drawParamsMapped)
1355                                 draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
1356                         else
1357                                 draw_option = DM_DRAW_OPTION_NORMAL;
1358
1359                         if (draw_option != DM_DRAW_OPTION_SKIP) {
1360
1361                                 if      (has_uv)            bmdm_get_tri_uv(ltri,  luv,  cd_loop_uv_offset);
1362                                 if      (has_vcol)          bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
1363                                 else if (has_vcol_preview)  bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
1364
1365                                 glBegin(GL_TRIANGLES);
1366                                 if (!drawSmooth) {
1367                                         glNormal3fv(efa->no);
1368
1369                                         glTexCoord2fv(luv[0]->uv);
1370                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1371                                         glVertex3fv(ltri[0]->v->co);
1372
1373                                         glTexCoord2fv(luv[1]->uv);
1374                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1375                                         glVertex3fv(ltri[1]->v->co);
1376
1377                                         glTexCoord2fv(luv[2]->uv);
1378                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1379                                         glVertex3fv(ltri[2]->v->co);
1380                                 }
1381                                 else {
1382                                         glTexCoord2fv(luv[0]->uv);
1383                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
1384                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
1385                                         else glNormal3fv(ltri[0]->v->no);
1386                                         glVertex3fv(ltri[0]->v->co);
1387
1388                                         glTexCoord2fv(luv[1]->uv);
1389                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
1390                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
1391                                         else glNormal3fv(ltri[1]->v->no);
1392                                         glVertex3fv(ltri[1]->v->co);
1393
1394                                         glTexCoord2fv(luv[2]->uv);
1395                                         if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
1396                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
1397                                         else glNormal3fv(ltri[2]->v->no);
1398                                         glVertex3fv(ltri[2]->v->co);
1399                                 }
1400                                 glEnd();
1401                         }
1402                 }
1403         }
1404 }
1405
1406 static void emDM_drawFacesTex(
1407         DerivedMesh *dm,
1408         DMSetDrawOptionsTex setDrawOptions,
1409         DMCompareDrawOptions compareDrawOptions,
1410         void *userData, DMDrawFlag UNUSED(flag))
1411 {
1412         emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
1413 }
1414
1415 static void emDM_drawMappedFacesTex(
1416         DerivedMesh *dm,
1417         DMSetDrawOptionsMappedTex setDrawOptions,
1418         DMCompareDrawOptions compareDrawOptions,
1419         void *userData, DMDrawFlag UNUSED(flag))
1420 {
1421         emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
1422 }
1423
1424 /**
1425  * \note
1426  *
1427  * For UV's:
1428  *   const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
1429  *
1430  * This is intentionally different to calling:
1431  *   CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i);
1432  *
1433  * ... because the material may use layer names to select different UV's
1434  * see: [#34378]
1435  */
1436 static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const BMLoop *loop)
1437 {
1438         BMVert *eve = loop->v;
1439         int i;
1440         const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1441
1442         if (attribs->totorco) {
1443                 int index = BM_elem_index_get(eve);
1444                 const float *orco = (attribs->orco.array) ? attribs->orco.array[index] : zero;
1445
1446                 if (attribs->orco.gl_texco)
1447                         glTexCoord3fv(orco);
1448                 else
1449                         glVertexAttrib3fv(attribs->orco.gl_index, orco);
1450         }
1451         for (i = 0; i < attribs->tottface; i++) {
1452                 const float *uv;
1453
1454                 if (attribs->tface[i].em_offset != -1) {
1455                         const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
1456                         uv = luv->uv;
1457                 }
1458                 else {
1459                         uv = zero;
1460                 }
1461
1462                 if (attribs->tface[i].gl_texco)
1463                         glTexCoord2fv(uv);
1464                 else
1465                         glVertexAttrib2fv(attribs->tface[i].gl_index, uv);
1466         }
1467         for (i = 0; i < attribs->totmcol; i++) {
1468                 float col[4];
1469                 if (attribs->mcol[i].em_offset != -1) {
1470                         const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
1471                         rgba_uchar_to_float(col, &cp->r);
1472                 }
1473                 else {
1474                         col[0] = 0.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 0.0f;
1475                 }
1476                 glVertexAttrib4fv(attribs->mcol[i].gl_index, col);
1477         }
1478
1479         for (i = 0; i < attribs->tottang; i++) {
1480                 const float *tang;
1481                 if (attribs->tang[i].em_offset != -1) {
1482                         tang = attribs->tang[i].array[BM_elem_index_get(loop)];
1483                 }
1484                 else {
1485                         tang = zero;
1486                 }
1487                 glVertexAttrib4fv(attribs->tang[i].gl_index, tang);
1488         }
1489 }
1490
1491 static void emDM_drawMappedFacesGLSL(
1492         DerivedMesh *dm,
1493         DMSetMaterial setMaterial,
1494         DMSetDrawOptions setDrawOptions,
1495         void *userData)
1496 {
1497         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1498         BMEditMesh *em = bmdm->em;
1499         BMesh *bm = em->bm;
1500         struct BMLoop *(*looptris)[3] = em->looptris;
1501         /* add direct access */
1502         const float (*vertexCos)[3] = bmdm->vertexCos;
1503         const float (*vertexNos)[3];
1504         const float (*polyNos)[3];
1505         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1506
1507         BMFace *efa;
1508         DMVertexAttribs attribs;
1509         GPUVertexAttribs gattribs;
1510
1511         int i, matnr, new_matnr, fi;
1512         bool do_draw;
1513
1514         do_draw = false;
1515         matnr = -1;
1516
1517         memset(&attribs, 0, sizeof(attribs));
1518
1519         emDM_ensureVertNormals(bmdm);
1520         emDM_ensurePolyNormals(bmdm);
1521         vertexNos = bmdm->vertexNos;
1522         polyNos = bmdm->polyNos;
1523
1524         BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
1525
1526         for (i = 0; i < em->tottri; i++) {
1527                 BMLoop **ltri = looptris[i];
1528                 int drawSmooth;
1529
1530                 efa = ltri[0]->f;
1531
1532                 if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP))
1533                         continue;
1534
1535                 /* material */
1536                 new_matnr = efa->mat_nr + 1;
1537                 if (new_matnr != matnr) {
1538                         if (matnr != -1)
1539                                 glEnd();
1540
1541                         do_draw = setMaterial(matnr = new_matnr, &gattribs);
1542                         if (do_draw) {
1543                                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1544                                 DM_draw_attrib_vertex_uniforms(&attribs);
1545                                 if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
1546                                         BM_mesh_elem_index_ensure(bm, BM_LOOP);
1547                                 }
1548                         }
1549
1550                         glBegin(GL_TRIANGLES);
1551                 }
1552
1553                 if (do_draw) {
1554
1555                         /* draw face */
1556                         drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1557
1558                         if (!drawSmooth) {
1559                                 if (vertexCos) {
1560                                         glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1561                                         for (fi = 0; fi < 3; fi++) {
1562                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1563                                                 glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
1564                                         }
1565                                 }
1566                                 else {
1567                                         glNormal3fv(efa->no);
1568                                         for (fi = 0; fi < 3; fi++) {
1569                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1570                                                 glVertex3fv(ltri[fi]->v->co);
1571                                         }
1572                                 }
1573                         }
1574                         else {
1575                                 if (vertexCos) {
1576                                         for (fi = 0; fi < 3; fi++) {
1577                                                 const int j = BM_elem_index_get(ltri[fi]->v);
1578                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1579                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1580                                                 else glNormal3fv(vertexNos[j]);
1581                                                 glVertex3fv(vertexCos[j]);
1582                                         }
1583                                 }
1584                                 else {
1585                                         for (fi = 0; fi < 3; fi++) {
1586                                                 emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1587                                                 if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1588                                                 else glNormal3fv(ltri[fi]->v->no);
1589                                                 glVertex3fv(ltri[fi]->v->co);
1590                                         }
1591                                 }
1592                         }
1593                 }
1594         }
1595
1596         if (matnr != -1) {
1597                 glEnd();
1598         }
1599 }
1600
1601 static void emDM_drawFacesGLSL(
1602         DerivedMesh *dm,
1603         int (*setMaterial)(int matnr, void *attribs))
1604 {
1605         dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1606 }
1607
1608 static void emDM_drawMappedFacesMat(
1609         DerivedMesh *dm,
1610         void (*setMaterial)(void *userData, int matnr, void *attribs),
1611         bool (*setFace)(void *userData, int index), void *userData)
1612 {
1613         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1614         BMEditMesh *em = bmdm->em;
1615         BMesh *bm = em->bm;
1616         struct BMLoop *(*looptris)[3] = em->looptris;
1617         const float (*vertexCos)[3] = bmdm->vertexCos;
1618         const float (*vertexNos)[3];
1619         const float (*polyNos)[3];
1620         const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
1621         BMFace *efa;
1622         DMVertexAttribs attribs = {{{NULL}}};
1623         GPUVertexAttribs gattribs;
1624         int i, matnr, new_matnr, fi;
1625
1626         matnr = -1;
1627
1628         emDM_ensureVertNormals(bmdm);
1629         emDM_ensurePolyNormals(bmdm);
1630
1631         vertexNos = bmdm->vertexNos;
1632         polyNos = bmdm->polyNos;
1633
1634         BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
1635
1636         for (i = 0; i < em->tottri; i++) {
1637                 BMLoop **ltri = looptris[i];
1638                 int drawSmooth;
1639
1640                 efa = ltri[0]->f;
1641
1642                 /* face hiding */
1643                 if (setFace && !setFace(userData, BM_elem_index_get(efa)))
1644                         continue;
1645
1646                 /* material */
1647                 new_matnr = efa->mat_nr + 1;
1648                 if (new_matnr != matnr) {
1649                         if (matnr != -1)
1650                                 glEnd();
1651
1652                         setMaterial(userData, matnr = new_matnr, &gattribs);
1653                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1654                         if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
1655                                 BM_mesh_elem_index_ensure(bm, BM_LOOP);
1656                         }
1657
1658                         glBegin(GL_TRIANGLES);
1659                 }
1660
1661                 /* draw face */
1662                 drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
1663
1664                 if (!drawSmooth) {
1665                         if (vertexCos) {
1666                                 glNormal3fv(polyNos[BM_elem_index_get(efa)]);
1667                                 for (fi = 0; fi < 3; fi++) {
1668                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1669                                         glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]);
1670                                 }
1671                         }
1672                         else {
1673                                 glNormal3fv(efa->no);
1674                                 for (fi = 0; fi < 3; fi++) {
1675                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1676                                         glVertex3fv(ltri[fi]->v->co);
1677                                 }
1678                         }
1679                 }
1680                 else {
1681                         if (vertexCos) {
1682                                 for (fi = 0; fi < 3; fi++) {
1683                                         const int j = BM_elem_index_get(ltri[fi]->v);
1684                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1685                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1686                                         else glNormal3fv(vertexNos[j]);
1687                                         glVertex3fv(vertexCos[j]);
1688                                 }
1689                         }
1690                         else {
1691                                 for (fi = 0; fi < 3; fi++) {
1692                                         emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]);
1693                                         if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]);
1694                                         else glNormal3fv(ltri[fi]->v->no);
1695                                         glVertex3fv(ltri[fi]->v->co);
1696                                 }
1697                         }
1698                 }
1699         }
1700
1701         if (matnr != -1) {
1702                 glEnd();
1703         }
1704 }
1705
1706 static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
1707 {
1708         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1709         BMesh *bm = bmdm->em->bm;
1710         BMVert *eve;
1711         BMIter iter;
1712         int i;
1713
1714         if (bm->totvert) {
1715                 if (bmdm->vertexCos) {
1716                         BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1717                                 minmax_v3v3_v3(r_min, r_max, bmdm->vertexCos[i]);
1718                         }
1719                 }
1720                 else {
1721                         BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1722                                 minmax_v3v3_v3(r_min, r_max, eve->co);
1723                         }
1724                 }
1725         }
1726         else {
1727                 zero_v3(r_min);
1728                 zero_v3(r_max);
1729         }
1730 }
1731 static int emDM_getNumVerts(DerivedMesh *dm)
1732 {
1733         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1734
1735         return bmdm->em->bm->totvert;
1736 }
1737
1738 static int emDM_getNumEdges(DerivedMesh *dm)
1739 {
1740         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1741
1742         return bmdm->em->bm->totedge;
1743 }
1744
1745 static int emDM_getNumTessFaces(DerivedMesh *dm)
1746 {
1747         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1748
1749         return bmdm->em->tottri;
1750 }
1751
1752 static int emDM_getNumLoops(DerivedMesh *dm)
1753 {
1754         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1755
1756         return bmdm->em->bm->totloop;
1757 }
1758
1759 static int emDM_getNumPolys(DerivedMesh *dm)
1760 {
1761         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1762
1763         return bmdm->em->bm->totface;
1764 }
1765
1766 static void bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *r_vert)
1767 {
1768         const float *f;
1769
1770         copy_v3_v3(r_vert->co, ev->co);
1771
1772         normal_float_to_short_v3(r_vert->no, ev->no);
1773
1774         r_vert->flag = BM_vert_flag_to_mflag(ev);
1775
1776         if ((f = CustomData_bmesh_get(&bm->vdata, ev->head.data, CD_BWEIGHT))) {
1777                 r_vert->bweight = (unsigned char)((*f) * 255.0f);
1778         }
1779 }
1780
1781 static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
1782 {
1783         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1784         BMesh *bm = bmdm->em->bm;
1785         BMVert *ev;
1786
1787         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1788                 BLI_assert(!"error in emDM_getVert");
1789                 return;
1790         }
1791
1792         BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1793         ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1794         // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1795
1796         bmvert_to_mvert(bm, ev, r_vert);
1797         if (bmdm->vertexCos)
1798                 copy_v3_v3(r_vert->co, bmdm->vertexCos[index]);
1799 }
1800
1801 static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
1802 {
1803         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1804         BMesh *bm = bmdm->em->bm;
1805
1806         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1807                 BLI_assert(!"error in emDM_getVertCo");
1808                 return;
1809         }
1810
1811         if (bmdm->vertexCos) {
1812                 copy_v3_v3(r_co, bmdm->vertexCos[index]);
1813         }
1814         else {
1815                 BMVert *ev;
1816
1817                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1818                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1819                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1820                 copy_v3_v3(r_co, ev->co);
1821         }
1822 }
1823
1824 static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
1825 {
1826         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1827         BMesh *bm = bmdm->em->bm;
1828
1829         if (UNLIKELY(index < 0 || index >= bm->totvert)) {
1830                 BLI_assert(!"error in emDM_getVertNo");
1831                 return;
1832         }
1833
1834
1835         if (bmdm->vertexCos) {
1836                 emDM_ensureVertNormals(bmdm);
1837                 copy_v3_v3(r_no, bmdm->vertexNos[index]);
1838         }
1839         else {
1840                 BMVert *ev;
1841
1842                 BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
1843                 ev = bm->vtable[index];  /* should be BM_vert_at_index() */
1844                 // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1845                 copy_v3_v3(r_no, ev->no);
1846         }
1847 }
1848
1849 static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3])
1850 {
1851         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1852         BMesh *bm = bmdm->em->bm;
1853
1854         if (UNLIKELY(index < 0 || index >= bm->totface)) {
1855                 BLI_assert(!"error in emDM_getPolyNo");
1856                 return;
1857         }
1858
1859         if (bmdm->vertexCos) {
1860                 emDM_ensurePolyNormals(bmdm);
1861                 copy_v3_v3(r_no, bmdm->polyNos[index]);
1862         }
1863         else {
1864                 BMFace *efa;
1865
1866                 BLI_assert((bm->elem_table_dirty & BM_FACE) == 0);
1867                 efa = bm->ftable[index];  /* should be BM_vert_at_index() */
1868                 // efa = BM_face_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1869                 copy_v3_v3(r_no, efa->no);
1870         }
1871 }
1872
1873 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
1874 {
1875         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1876         BMesh *bm = bmdm->em->bm;
1877         BMEdge *e;
1878         const float *f;
1879
1880         if (UNLIKELY(index < 0 || index >= bm->totedge)) {
1881                 BLI_assert(!"error in emDM_getEdge");
1882                 return;
1883         }
1884
1885         BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
1886         e = bm->etable[index];  /* should be BM_edge_at_index() */
1887         // e = BM_edge_at_index(bm, index); /* warning, does list loop, _not_ ideal */
1888
1889         r_edge->flag = BM_edge_flag_to_mflag(e);
1890
1891         r_edge->v1 = BM_elem_index_get(e->v1);
1892         r_edge->v2 = BM_elem_index_get(e->v2);
1893
1894         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT))) {
1895                 r_edge->bweight = (unsigned char)((*f) * 255.0f);
1896         }
1897         if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE))) {
1898                 r_edge->crease = (unsigned char)((*f) * 255.0f);
1899         }
1900 }
1901
1902 static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
1903 {
1904         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1905         BMFace *ef;
1906         BMLoop **ltri;
1907
1908         if (UNLIKELY(index < 0 || index >= bmdm->em->tottri)) {
1909                 BLI_assert(!"error in emDM_getTessFace");
1910                 return;
1911         }
1912
1913         ltri = bmdm->em->looptris[index];
1914
1915         ef = ltri[0]->f;
1916
1917         r_face->mat_nr = (unsigned char) ef->mat_nr;
1918         r_face->flag = BM_face_flag_to_mflag(ef);
1919
1920         r_face->v1 = BM_elem_index_get(ltri[0]->v);
1921         r_face->v2 = BM_elem_index_get(ltri[1]->v);
1922         r_face->v3 = BM_elem_index_get(ltri[2]->v);
1923         r_face->v4 = 0;
1924
1925         test_index_face(r_face, NULL, 0, 3);
1926 }
1927
1928 static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
1929 {
1930         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1931         BMesh *bm = bmdm->em->bm;
1932         BMVert *eve;
1933         BMIter iter;
1934         const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
1935
1936         if (bmdm->vertexCos) {
1937                 int i;
1938
1939                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1940                         copy_v3_v3(r_vert->co, bmdm->vertexCos[i]);
1941                         normal_float_to_short_v3(r_vert->no, eve->no);
1942                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1943
1944                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1945
1946                         r_vert++;
1947                 }
1948         }
1949         else {
1950                 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1951                         copy_v3_v3(r_vert->co, eve->co);
1952                         normal_float_to_short_v3(r_vert->no, eve->no);
1953                         r_vert->flag = BM_vert_flag_to_mflag(eve);
1954
1955                         r_vert->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
1956
1957                         r_vert++;
1958                 }
1959         }
1960 }
1961
1962 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
1963 {
1964         BMesh *bm = ((EditDerivedBMesh *)dm)->em->bm;
1965         BMEdge *eed;
1966         BMIter iter;
1967
1968         const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
1969         const int cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
1970
1971         BM_mesh_elem_index_ensure(bm, BM_VERT);
1972
1973         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1974                 r_edge->v1 = BM_elem_index_get(eed->v1);
1975                 r_edge->v2 = BM_elem_index_get(eed->v2);
1976
1977                 r_edge->flag = BM_edge_flag_to_mflag(eed);
1978
1979                 r_edge->crease  = (cd_edge_crease_offset  != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset)  : 0;
1980                 r_edge->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0;
1981
1982                 r_edge++;
1983         }
1984 }
1985
1986 static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
1987 {
1988         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
1989         BMesh *bm = bmdm->em->bm;
1990         struct BMLoop *(*looptris)[3] = bmdm->em->looptris;
1991         BMFace *ef;
1992         int i;
1993
1994         BM_mesh_elem_index_ensure(bm, BM_VERT);
1995
1996         for (i = 0; i < bmdm->em->tottri; i++, r_face++) {
1997                 BMLoop **ltri = looptris[i];
1998                 ef = ltri[0]->f;
1999
2000                 r_face->mat_nr = (unsigned char) ef->mat_nr;
2001
2002                 r_face->flag = BM_face_flag_to_mflag(ef);
2003                 r_face->edcode = 0;
2004
2005                 r_face->v1 = BM_elem_index_get(ltri[0]->v);
2006                 r_face->v2 = BM_elem_index_get(ltri[1]->v);
2007                 r_face->v3 = BM_elem_index_get(ltri[2]->v);
2008                 r_face->v4 = 0;
2009
2010                 test_index_face(r_face, NULL, 0, 3);
2011         }
2012 }
2013
2014 static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
2015 {
2016         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2017         BMesh *bm = bmdm->em->bm;
2018         BMIter iter;
2019         BMFace *efa;
2020
2021         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
2022
2023         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2024                 BMLoop *l_iter, *l_first;
2025                 l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
2026                 do {
2027                         r_loop->v = BM_elem_index_get(l_iter->v);
2028                         r_loop->e = BM_elem_index_get(l_iter->e);
2029                         r_loop++;
2030                 } while ((l_iter = l_iter->next) != l_first);
2031         }
2032 }
2033
2034 static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
2035 {
2036         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2037         BMesh *bm = bmdm->em->bm;
2038         BMIter iter;
2039         BMFace *efa;
2040         int i;
2041
2042         i = 0;
2043         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
2044                 r_poly->flag = BM_face_flag_to_mflag(efa);
2045                 r_poly->loopstart = i;
2046                 r_poly->totloop = efa->len;
2047                 r_poly->mat_nr = efa->mat_nr;
2048
2049                 r_poly++;
2050                 i += efa->len;
2051         }
2052 }
2053
2054 static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
2055 {
2056         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2057         BMesh *bm = bmdm->em->bm;
2058         void *datalayer;
2059
2060         datalayer = DM_get_tessface_data_layer(dm, type);
2061         if (datalayer)
2062                 return datalayer;
2063
2064         /* layers are store per face for editmesh, we convert to a temporary
2065          * data layer array in the derivedmesh when these are requested */
2066         if (type == CD_MTFACE || type == CD_MCOL) {
2067                 const char *bmdata;
2068                 char *data;
2069                 bool has_type_source = false;
2070
2071                 if (type == CD_MTFACE) {
2072                         has_type_source = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
2073                 }
2074                 else {
2075                         has_type_source = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
2076                 }
2077
2078                 if (has_type_source) {
2079                         /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
2080                         BMLoop *(*looptris)[3] = bmdm->em->looptris;
2081                         const int size = CustomData_sizeof(type);
2082                         int i, j;
2083
2084                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
2085                         const int index = CustomData_get_layer_index(&dm->faceData, type);
2086                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
2087
2088                         data = datalayer = DM_get_tessface_data_layer(dm, type);
2089
2090                         if (type == CD_MTFACE) {
2091                                 const int cd_loop_uv_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
2092                                 const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
2093
2094                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
2095                                         BMFace *efa = looptris[i][0]->f;
2096
2097                                         // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
2098                                         bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
2099
2100                                         ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata));
2101                                         for (j = 0; j < 3; j++) {
2102                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
2103                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
2104                                                 copy_v2_v2(((MTFace *)data)->uv[j], ((const MLoopUV *)bmdata)->uv);
2105                                         }
2106                                 }
2107                         }
2108                         else {
2109                                 const int cd_loop_color_offset  = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
2110                                 for (i = 0; i < bmdm->em->tottri; i++, data += size) {
2111                                         for (j = 0; j < 3; j++) {
2112                                                 // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPCOL);
2113                                                 bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_color_offset);
2114                                                 MESH_MLOOPCOL_TO_MCOL(((const MLoopCol *)bmdata), (((MCol *)data) + j));
2115                                         }
2116                                 }
2117                         }
2118                 }
2119         }
2120
2121         /* Special handling for CD_TESSLOOPNORMAL, we generate it on demand as well. */
2122         if (type == CD_TESSLOOPNORMAL) {
2123                 const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
2124
2125                 if (lnors) {
2126                         BMLoop *(*looptris)[3] = bmdm->em->looptris;
2127                         short (*tlnors)[4][3], (*tlnor)[4][3];
2128                         int index, i, j;
2129
2130                         DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
2131                         index = CustomData_get_layer_index(&dm->faceData, type);
2132                         dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
2133
2134                         tlnor = tlnors = DM_get_tessface_data_layer(dm, type);
2135
2136                         BM_mesh_elem_index_ensure(bm, BM_LOOP);
2137
2138                         for (i = 0; i < bmdm->em->tottri; i++, tlnor++, looptris++) {
2139                                 for (j = 0; j < 3; j++) {
2140                                         normal_float_to_short_v3((*tlnor)[j], lnors[BM_elem_index_get((*looptris)[j])]);
2141                                 }
2142                         }
2143                 }
2144         }
2145
2146         return datalayer;
2147 }
2148
2149 static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3])
2150 {
2151         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2152         BMesh *bm = bmdm->em->bm;
2153         BMVert *eve;
2154         BMIter iter;
2155         int i;
2156
2157         if (bmdm->vertexCos) {
2158                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2159                         copy_v3_v3(r_cos[i], bmdm->vertexCos[i]);
2160                 }
2161         }
2162         else {
2163                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2164                         copy_v3_v3(r_cos[i], eve->co);
2165                 }
2166         }
2167 }
2168
2169 static void emDM_release(DerivedMesh *dm)
2170 {
2171         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2172
2173         if (DM_release(dm)) {
2174                 if (bmdm->vertexCos) {
2175                         MEM_freeN((void *)bmdm->vertexCos);
2176                         if (bmdm->vertexNos) {
2177                                 MEM_freeN((void *)bmdm->vertexNos);
2178                         }
2179                         if (bmdm->polyNos) {
2180                                 MEM_freeN((void *)bmdm->polyNos);
2181                         }
2182                 }
2183
2184                 if (bmdm->polyCos) {
2185                         MEM_freeN((void *)bmdm->polyCos);
2186                 }
2187
2188                 MEM_freeN(bmdm);
2189         }
2190 }
2191
2192 static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
2193 {
2194         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2195
2196         return &bmdm->em->bm->vdata;
2197 }
2198
2199 static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
2200 {
2201         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2202
2203         return &bmdm->em->bm->edata;
2204 }
2205
2206 static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
2207 {
2208         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2209
2210         return &bmdm->dm.faceData;
2211 }
2212
2213 static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
2214 {
2215         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2216
2217         return &bmdm->em->bm->ldata;
2218 }
2219
2220 static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
2221 {
2222         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2223
2224         return &bmdm->em->bm->pdata;
2225 }
2226
2227 /**
2228  * \note This may be called per-draw,
2229  * avoid allocating large arrays where possible and keep this a thin wrapper for #BMesh.
2230  */
2231 DerivedMesh *getEditDerivedBMesh(
2232         BMEditMesh *em, struct Object *UNUSED(ob),
2233         CustomDataMask data_mask,
2234         float (*vertexCos)[3])
2235 {
2236         EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
2237         BMesh *bm = em->bm;
2238
2239         bmdm->em = em;
2240
2241         DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, bm->totvert,
2242                 bm->totedge, em->tottri, bm->totloop, bm->totface);
2243
2244         /* could also get from the objects mesh directly */
2245         bmdm->dm.cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
2246
2247         bmdm->dm.getVertCos = emDM_getVertCos;
2248         bmdm->dm.getMinMax = emDM_getMinMax;
2249
2250         bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
2251         bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
2252         bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
2253         bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
2254         bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
2255
2256         bmdm->dm.getNumVerts = emDM_getNumVerts;
2257         bmdm->dm.getNumEdges = emDM_getNumEdges;
2258         bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
2259         bmdm->dm.getNumLoops = emDM_getNumLoops;
2260         bmdm->dm.getNumPolys = emDM_getNumPolys;
2261
2262         bmdm->dm.getLoopTriArray = emDM_getLoopTriArray;
2263
2264         bmdm->dm.getVert = emDM_getVert;
2265         bmdm->dm.getVertCo = emDM_getVertCo;
2266         bmdm->dm.getVertNo = emDM_getVertNo;
2267         bmdm->dm.getPolyNo = emDM_getPolyNo;
2268         bmdm->dm.getEdge = emDM_getEdge;
2269         bmdm->dm.getTessFace = emDM_getTessFace;
2270         bmdm->dm.copyVertArray = emDM_copyVertArray;
2271         bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
2272         bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
2273         bmdm->dm.copyLoopArray = emDM_copyLoopArray;
2274         bmdm->dm.copyPolyArray = emDM_copyPolyArray;
2275
2276         bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
2277
2278         bmdm->dm.calcNormals = emDM_calcNormals;
2279         bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
2280         bmdm->dm.calcLoopNormalsSpaceArray = emDM_calcLoopNormalsSpaceArray;
2281         bmdm->dm.calcLoopTangents = emDM_calc_loop_tangents;
2282         bmdm->dm.recalcTessellation = emDM_recalcTessellation;
2283         bmdm->dm.recalcLoopTri = emDM_recalcLoopTri;
2284
2285         bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
2286         bmdm->dm.foreachMappedLoop = emDM_foreachMappedLoop;
2287         bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
2288         bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
2289
2290         bmdm->dm.drawEdges = emDM_drawEdges;
2291         bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
2292         bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
2293         bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
2294         bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
2295         bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
2296         bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
2297         bmdm->dm.drawFacesTex = emDM_drawFacesTex;
2298         bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
2299         bmdm->dm.drawUVEdges = emDM_drawUVEdges;
2300
2301         bmdm->dm.release = emDM_release;
2302
2303         bmdm->vertexCos = (const float (*)[3])vertexCos;
2304         bmdm->dm.deformedOnly = (vertexCos != NULL);
2305
2306         const int cd_dvert_offset = (data_mask & CD_MASK_MDEFORMVERT) ?
2307                 CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT) : -1;
2308
2309         if (cd_dvert_offset != -1) {
2310                 BMIter iter;
2311                 BMVert *eve;
2312                 int i;
2313
2314                 DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
2315
2316                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2317                         DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
2318                                          BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
2319                 }
2320         }
2321
2322         const int cd_skin_offset = (data_mask & CD_MASK_MVERT_SKIN) ?
2323                 CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN) : -1;
2324
2325         if (cd_skin_offset != -1) {
2326                 BMIter iter;
2327                 BMVert *eve;
2328                 int i;
2329
2330                 DM_add_vert_layer(&bmdm->dm, CD_MVERT_SKIN, CD_CALLOC, NULL);
2331
2332                 BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
2333                         DM_set_vert_data(&bmdm->dm, i, CD_MVERT_SKIN,
2334                                          BM_ELEM_CD_GET_VOID_P(eve, cd_skin_offset));
2335                 }
2336         }
2337
2338         return (DerivedMesh *)bmdm;
2339 }
2340
2341
2342
2343 /* -------------------------------------------------------------------- */
2344 /* StatVis Functions */
2345
2346 static void axis_from_enum_v3(float v[3], const char axis)
2347 {
2348         zero_v3(v);
2349         if (axis < 3) v[axis]     =  1.0f;
2350         else          v[axis - 3] = -1.0f;
2351 }
2352
2353 static void statvis_calc_overhang(
2354         BMEditMesh *em,
2355         const float (*polyNos)[3],
2356         /* values for calculating */
2357         const float min, const float max, const char axis,
2358         /* result */
2359         unsigned char (*r_face_colors)[4])
2360 {
2361         BMIter iter;
2362         BMesh *bm = em->bm;
2363         BMFace *f;
2364         float dir[3];
2365         int index;
2366         const float minmax_irange = 1.0f / (max - min);
2367         bool is_max;
2368
2369         /* fallback */
2370         unsigned char col_fallback[4] = {64, 64, 64, 255}; /* gray */
2371         unsigned char col_fallback_max[4] = {0,  0,  0,  255}; /* max color */
2372
2373         BLI_assert(min <= max);
2374
2375         axis_from_enum_v3(dir, axis);
2376
2377         if (LIKELY(em->ob)) {
2378                 mul_transposed_mat3_m4_v3(em->ob->obmat, dir);
2379                 normalize_v3(dir);
2380         }
2381
2382         /* fallback max */
2383         {
2384                 float fcol[3];
2385                 weight_to_rgb(fcol, 1.0f);
2386                 rgb_float_to_uchar(col_fallback_max, fcol);
2387         }
2388
2389         /* now convert into global space */
2390         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2391                 float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI;
2392
2393                 /* remap */
2394                 if ((is_max = (fac <= max)) && (fac >= min)) {
2395                         float fcol[3];
2396                         fac = (fac - min) * minmax_irange;
2397                         fac = 1.0f - fac;
2398                         CLAMP(fac, 0.0f, 1.0f);
2399                         weight_to_rgb(fcol, fac);
2400                         rgb_float_to_uchar(r_face_colors[index], fcol);
2401                 }
2402                 else {
2403                         const unsigned char *fallback = is_max ? col_fallback_max : col_fallback;
2404                         copy_v4_v4_uchar(r_face_colors[index], fallback);
2405                 }
2406         }
2407 }
2408
2409 /* so we can use jitter values for face interpolation */
2410 static void uv_from_jitter_v2(float uv[2])
2411 {
2412         uv[0] += 0.5f;
2413         uv[1] += 0.5f;
2414         if (uv[0] + uv[1] > 1.0f) {
2415                 uv[0] = 1.0f - uv[0];
2416                 uv[1] = 1.0f - uv[1];
2417         }
2418
2419         CLAMP(uv[0], 0.0f, 1.0f);
2420         CLAMP(uv[1], 0.0f, 1.0f);
2421 }
2422
2423 static void statvis_calc_thickness(
2424         BMEditMesh *em,
2425         const float (*vertexCos)[3],
2426         /* values for calculating */
2427         const float min, const float max, const int samples,
2428         /* result */
2429         unsigned char (*r_face_colors)[4])
2430 {
2431         const float eps_offset = 0.00002f;  /* values <= 0.00001 give errors */
2432         float *face_dists = (float *)r_face_colors;  /* cheating */
2433         const bool use_jit = samples < 32;
2434         float jit_ofs[32][2];
2435         BMesh *bm = em->bm;
2436         const int tottri = em->tottri;
2437         const float minmax_irange = 1.0f / (max - min);
2438         int i;
2439
2440         struct BMLoop *(*looptris)[3] = em->looptris;
2441
2442         /* fallback */
2443         const unsigned char col_fallback[4] = {64, 64, 64, 255};
2444
2445         struct BMBVHTree *bmtree;
2446
2447         BLI_assert(min <= max);
2448
2449         copy_vn_fl(face_dists, em->bm->totface, max);
2450
2451         if (use_jit) {
2452                 int j;
2453                 BLI_assert(samples < 32);
2454                 BLI_jitter_init(jit_ofs, samples);
2455
2456                 for (j = 0; j < samples; j++) {
2457                         uv_from_jitter_v2(jit_ofs[j]);
2458                 }
2459         }
2460
2461         BM_mesh_elem_index_ensure(bm, BM_FACE);
2462         if (vertexCos) {
2463                 BM_mesh_elem_index_ensure(bm, BM_VERT);
2464         }
2465
2466         bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
2467
2468         for (i = 0; i < tottri; i++) {
2469                 BMFace *f_hit;
2470                 BMLoop **ltri = looptris[i];
2471                 const int index = BM_elem_index_get(ltri[0]->f);
2472                 const float *cos[3];
2473                 float ray_co[3];
2474                 float ray_no[3];
2475
2476                 if (vertexCos) {
2477                         cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)];
2478                         cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)];
2479                         cos[2] = vertexCos[BM_elem_index_get(ltri[2]->v)];
2480                 }
2481                 else {
2482                         cos[0] = ltri[0]->v->co;
2483                         cos[1] = ltri[1]->v->co;
2484                         cos[2] = ltri[2]->v->co;
2485                 }
2486
2487                 normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
2488
2489 #define FACE_RAY_TEST_ANGLE \
2490                 f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, \
2491                                            &dist, NULL, NULL); \
2492                 if (f_hit && dist < face_dists[index]) { \
2493                         float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
2494                         angle_fac = 1.0f - angle_fac; \
2495                         angle_fac = angle_fac * angle_fac * angle_fac; \
2496                         angle_fac = 1.0f - angle_fac; \
2497                         dist /= angle_fac; \
2498                         if (dist < face_dists[index]) { \
2499                                 face_dists[index] = dist; \
2500                         } \
2501                 } (void)0
2502
2503                 if (use_jit) {
2504                         int j;
2505                         for (j = 0; j < samples; j++) {
2506                                 float dist = face_dists[index];
2507                                 interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]);
2508                                 madd_v3_v3fl(ray_co, ray_no, eps_offset);
2509
2510                                 FACE_RAY_TEST_ANGLE;
2511                         }
2512                 }
2513                 else {
2514                         float dist = face_dists[index];
2515                         mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]);
2516                         madd_v3_v3fl(ray_co, ray_no, eps_offset);
2517
2518                         FACE_RAY_TEST_ANGLE;
2519                 }
2520         }
2521
2522         BKE_bmbvh_free(bmtree);
2523
2524         /* convert floats into color! */
2525         for (i = 0; i < bm->totface; i++) {
2526                 float fac = face_dists[i];
2527
2528                 /* important not '<=' */
2529                 if (fac < max) {
2530                         float fcol[3];
2531                         fac = (fac - min) * minmax_irange;
2532                         fac = 1.0f - fac;
2533                         CLAMP(fac, 0.0f, 1.0f);
2534                         weight_to_rgb(fcol, fac);
2535                         rgb_float_to_uchar(r_face_colors[i], fcol);
2536                 }
2537                 else {
2538                         copy_v4_v4_uchar(r_face_colors[i], col_fallback);
2539                 }
2540         }
2541 }
2542
2543 static void statvis_calc_intersect(
2544         BMEditMesh *em,
2545         const float (*vertexCos)[3],
2546         /* result */
2547         unsigned char (*r_face_colors)[4])
2548 {
2549         BMesh *bm = em->bm;
2550         int i;
2551
2552         /* fallback */
2553         // const char col_fallback[4] = {64, 64, 64, 255};
2554         float fcol[3];
2555         unsigned char col[3];
2556
2557         struct BMBVHTree *bmtree;
2558         BVHTreeOverlap *overlap;
2559         unsigned int overlap_len;
2560
2561         memset(r_face_colors, 64, sizeof(int) * em->bm->totface);
2562
2563         BM_mesh_elem_index_ensure(bm, BM_FACE);
2564         if (vertexCos) {
2565                 BM_mesh_elem_index_ensure(bm, BM_VERT);
2566         }
2567
2568         bmtree = BKE_bmbvh_new_from_editmesh(em, 0, vertexCos, false);
2569
2570         overlap = BKE_bmbvh_overlap(bmtree, bmtree, &overlap_len);
2571
2572         /* same for all faces */
2573         weight_to_rgb(fcol, 1.0f);
2574         rgb_float_to_uchar(col, fcol);
2575
2576         if (overlap) {
2577                 for (i = 0; i < overlap_len; i++) {
2578                         BMFace *f_hit_pair[2] = {
2579                             em->looptris[overlap[i].indexA][0]->f,
2580                             em->looptris[overlap[i].indexB][0]->f,
2581                         };
2582                         int j;
2583
2584                         for (j = 0; j < 2; j++) {
2585                                 BMFace *f_hit = f_hit_pair[j];
2586                                 int index;
2587
2588                                 index = BM_elem_index_get(f_hit);
2589
2590                                 copy_v3_v3_uchar(r_face_colors[index], col);
2591                         }
2592                 }
2593                 MEM_freeN(overlap);
2594         }
2595
2596         BKE_bmbvh_free(bmtree);
2597 }
2598
2599 static void statvis_calc_distort(
2600         BMEditMesh *em,
2601         const float (*vertexCos)[3], const float (*polyNos)[3],
2602         /* values for calculating */
2603         const float min, const float max,
2604         /* result */
2605         unsigned char (*r_face_colors)[4])
2606 {
2607         BMIter iter;
2608         BMesh *bm = em->bm;
2609         BMFace *f;
2610         const float *f_no;
2611         int index;
2612         const float minmax_irange = 1.0f / (max - min);
2613
2614         /* fallback */
2615         const unsigned char col_fallback[4] = {64, 64, 64, 255};
2616
2617         /* now convert into global space */
2618         BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
2619                 float fac;
2620
2621                 if (f->len == 3) {
2622                         fac = -1.0f;
2623                 }
2624                 else {
2625                         BMLoop *l_iter, *l_first;
2626                         if (vertexCos) {
2627                                 f_no = polyNos[index];
2628                         }
2629                         else {
2630                                 f_no = f->no;
2631                         }
2632
2633                         fac = 0.0f;
2634                         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2635                         do {
2636                                 float no_corner[3];
2637                                 if (vertexCos) {
2638                                         normal_tri_v3(no_corner,
2639                                                       vertexCos[BM_elem_index_get(l_iter->prev->v)],
2640                                                       vertexCos[BM_elem_index_get(l_iter->v)],
2641                                                       vertexCos[BM_elem_index_get(l_iter->next->v)]);
2642                                 }
2643                                 else {
2644                                         BM_loop_calc_face_normal_safe(l_iter, no_corner);
2645                                 }
2646                                 /* simple way to detect (what is most likely) concave */
2647                                 if (dot_v3v3(f_no, no_corner) < 0.0f) {
2648                                         negate_v3(no_corner);
2649                                 }
2650                                 fac = max_ff(fac, angle_normalized_v3v3(f_no, no_corner));
2651                         } while ((l_iter = l_iter->next) != l_first);
2652                         fac *= 2.0f;
2653                 }
2654
2655                 /* remap */
2656                 if (fac >= min) {
2657                         float fcol[3];
2658                         fac = (fac - min) * minmax_irange;
2659                         CLAMP(fac, 0.0f, 1.0f);
2660                         weight_to_rgb(fcol, fac);
2661                         rgb_float_to_uchar(r_face_colors[index], fcol);
2662                 }
2663                 else {
2664                         copy_v4_v4_uchar(r_face_colors[index], col_fallback);
2665                 }
2666         }
2667 }
2668
2669 static void statvis_calc_sharp(
2670         BMEditMesh *em,
2671         const float (*vertexCos)[3],
2672         /* values for calculating */
2673         const float min, const float max,
2674         /* result */
2675         unsigned char (*r_vert_colors)[4])
2676 {
2677         float *vert_angles = (float *)r_vert_colors;  /* cheating */
2678         BMIter iter;
2679         BMesh *bm = em->bm;
2680         BMEdge *e;
2681         //float f_no[3];
2682         const float minmax_irange = 1.0f / (max - min);
2683         int i;
2684
2685         /* fallback */
2686         const unsigned char col_fallback[4] = {64, 64, 64, 255};
2687
2688         (void)vertexCos;  /* TODO */
2689
2690         copy_vn_fl(vert_angles, em->bm->totvert, -M_PI);
2691
2692         /* first assign float values to verts */
2693         BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
2694                 float angle = BM_edge_calc_face_angle_signed(e);
2695                 float *col1 = &vert_angles[BM_elem_index_get(e->v1)];
2696                 float *col2 = &vert_angles[BM_elem_index_get(e->v2)];
2697                 *col1 = max_ff(*col1, angle);
2698                 *col2 = max_ff(*col2, angle);
2699         }
2700
2701         /* convert floats into color! */
2702         for (i = 0; i < bm->totvert; i++) {
2703                 float fac = vert_angles[i];
2704
2705                 /* important not '<=' */
2706                 if (fac > min) {
2707                         float fcol[3];
2708                         fac = (fac - min) * minmax_irange;
2709                         CLAMP(fac, 0.0f, 1.0f);
2710                         weight_to_rgb(fcol, fac);
2711                         rgb_float_to_uchar(r_vert_colors[i], fcol);
2712                 }
2713                 else {
2714                         copy_v4_v4_uchar(r_vert_colors[i], col_fallback);
2715                 }
2716         }
2717 }
2718
2719 void BKE_editmesh_statvis_calc(
2720         BMEditMesh *em, DerivedMesh *dm,
2721         const MeshStatVis *statvis)
2722 {
2723         EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
2724         BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH);
2725
2726         switch (statvis->type) {
2727                 case SCE_STATVIS_OVERHANG:
2728                 {
2729                         BKE_editmesh_color_ensure(em, BM_FACE);
2730                         statvis_calc_overhang(
2731                                     em, bmdm ? bmdm->polyNos : NULL,
2732                                     statvis->overhang_min / (float)M_PI,
2733                                     statvis->overhang_max / (float)M_PI,
2734                                     statvis->overhang_axis,
2735                                     em->derivedFaceColor);
2736                         break;
2737                 }
2738                 case SCE_STATVIS_THICKNESS:
2739                 {
2740                         const float scale = 1.0f / mat4_to_scale(em->ob->obmat);
2741                         BKE_editmesh_color_ensure(em, BM_FACE);
2742                         statvis_calc_thickness(
2743                                     em, bmdm ? bmdm->vertexCos : NULL,
2744                                     statvis->thickness_min * scale,
2745                                     statvis->thickness_max * scale,
2746                                     statvis->thickness_samples,
2747                                     em->derivedFaceColor);
2748                         break;
2749                 }
2750                 case SCE_STATVIS_INTERSECT:
2751                 {
2752                         BKE_editmesh_color_ensure(em, BM_FACE);
2753                         statvis_calc_intersect(
2754                                     em, bmdm ? bmdm->vertexCos : NULL,
2755                                     em->derivedFaceColor);
2756                         break;
2757                 }
2758                 case SCE_STATVIS_DISTORT:
2759                 {
2760                         BKE_editmesh_color_ensure(em, BM_FACE);
2761
2762                         if (bmdm)
2763                                 emDM_ensurePolyNormals(bmdm);
2764
2765                         statvis_calc_distort(
2766                                 em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL,
2767                                 statvis->distort_min,
2768                                 statvis->distort_max,
2769                                 em->derivedFaceColor);
2770                         break;
2771                 }
2772                 case SCE_STATVIS_SHARP:
2773                 {
2774                         BKE_editmesh_color_ensure(em, BM_VERT);
2775                         statvis_calc_sharp(
2776                                 em, bmdm ? bmdm->vertexCos : NULL,
2777                                 statvis->sharp_min,
2778                                 statvis->sharp_max,
2779                                 /* in this case they are vertex colors */
2780                                 em->derivedVertColor);
2781                         break;
2782                 }
2783         }
2784 }
2785
2786
2787
2788 /* -------------------------------------------------------------------- */
2789 /* Editmesh Vert Coords */
2790
2791 struct CageUserData {
2792         int totvert;
2793         float (*cos_cage)[3];
2794         BLI_bitmap *visit_bitmap;
2795 };
2796
2797 static void cage_mapped_verts_callback(
2798         void *userData, int index, const float co[3],
2799         const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2800 {
2801         struct CageUserData *data = userData;
2802
2803         if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
2804                 BLI_BITMAP_ENABLE(data->visit_bitmap, index);
2805                 copy_v3_v3(data->cos_cage[index], co);
2806         }
2807 }
2808
2809 float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
2810 {
2811         DerivedMesh *cage, *final;
2812         BLI_bitmap *visit_bitmap;
2813         struct CageUserData data;
2814         float (*cos_cage)[3];
2815
2816         cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, CD_MASK_BAREMESH, &final);
2817         cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
2818
2819         /* when initializing cage verts, we only want the first cage coordinate for each vertex,
2820          * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
2821         visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2822
2823         data.totvert = em->bm->totvert;
2824         data.cos_cage = cos_cage;
2825         data.visit_bitmap = visit_bitmap;
2826
2827         cage->foreachMappedVert(cage, cage_mapped_verts_callback, &data, DM_FOREACH_NOP);
2828
2829         MEM_freeN(visit_bitmap);
2830
2831         if (r_numVerts) {
2832                 *r_numVerts = em->bm->totvert;
2833         }
2834
2835         return cos_cage;
2836 }