f1a7ab8c9d8715f7b76ab3e4dca64223b78635ae
[blender.git] / source / blender / draw / intern / draw_cache_extract_mesh.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2017 by Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup draw
22  *
23  * \brief Extraction of Mesh data into VBO to feed to GPU.
24  */
25
26 #include "MEM_guardedalloc.h"
27
28 #include "BLI_alloca.h"
29 #include "BLI_bitmap.h"
30 #include "BLI_buffer.h"
31 #include "BLI_edgehash.h"
32 #include "BLI_jitter_2d.h"
33 #include "BLI_math_bits.h"
34 #include "BLI_math_vector.h"
35 #include "BLI_string.h"
36 #include "BLI_task.h"
37 #include "BLI_utildefines.h"
38
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_scene_types.h"
43
44 #include "BKE_bvhutils.h"
45 #include "BKE_customdata.h"
46 #include "BKE_deform.h"
47 #include "BKE_editmesh.h"
48 #include "BKE_editmesh_bvh.h"
49 #include "BKE_editmesh_cache.h"
50 #include "BKE_editmesh_tangent.h"
51 #include "BKE_mesh.h"
52 #include "BKE_mesh_runtime.h"
53 #include "BKE_mesh_tangent.h"
54 #include "BKE_modifier.h"
55 #include "BKE_object_deform.h"
56
57 #include "atomic_ops.h"
58
59 #include "bmesh.h"
60
61 #include "GPU_batch.h"
62 #include "GPU_extensions.h"
63
64 #include "DRW_render.h"
65
66 #include "ED_mesh.h"
67 #include "ED_uvedit.h"
68
69 #include "draw_cache_impl.h"
70 #include "draw_cache_inline.h"
71
72 #include "draw_cache_extract.h"
73
74 // #define DEBUG_TIME
75
76 #ifdef DEBUG_TIME
77 #  include "PIL_time_utildefines.h"
78 #endif
79
80 /* ---------------------------------------------------------------------- */
81 /** \name Mesh/BMesh Interface (indirect, partially cached access to complex data).
82  * \{ */
83
84 typedef struct MeshRenderData {
85   eMRExtractType extract_type;
86
87   int poly_len, edge_len, vert_len, loop_len;
88   int edge_loose_len;
89   int vert_loose_len;
90   int loop_loose_len;
91   int tri_len;
92   int mat_len;
93
94   bool use_hide;
95   bool use_subsurf_fdots;
96   bool use_final_mesh;
97
98   /** Use for #MeshStatVis calculation which use world-space coords. */
99   float obmat[4][4];
100
101   const ToolSettings *toolsettings;
102   /* HACK not supposed to be there but it's needed. */
103   struct MeshBatchCache *cache;
104   /** Edit Mesh */
105   BMEditMesh *edit_bmesh;
106   BMesh *bm;
107   EditMeshData *edit_data;
108
109   /* For deformed edit-mesh data. */
110   /* Use for #ME_WRAPPER_TYPE_BMESH. */
111   const float (*bm_vert_coords)[3];
112   const float (*bm_vert_normals)[3];
113   const float (*bm_poly_normals)[3];
114   const float (*bm_poly_centers)[3];
115
116   int *v_origindex, *e_origindex, *p_origindex;
117   int crease_ofs;
118   int bweight_ofs;
119   int freestyle_edge_ofs;
120   int freestyle_face_ofs;
121   /** Mesh */
122   Mesh *me;
123   const MVert *mvert;
124   const MEdge *medge;
125   const MLoop *mloop;
126   const MPoly *mpoly;
127   BMVert *eve_act;
128   BMEdge *eed_act;
129   BMFace *efa_act;
130   BMFace *efa_act_uv;
131   /* Data created on-demand (usually not for #BMesh based data). */
132   MLoopTri *mlooptri;
133   float (*loop_normals)[3];
134   float (*poly_normals)[3];
135   int *lverts, *ledges;
136 } MeshRenderData;
137
138 static void mesh_render_data_update_loose_geom(MeshRenderData *mr,
139                                                const eMRIterType iter_type,
140                                                const eMRDataType UNUSED(data_flag))
141 {
142   if (mr->extract_type != MR_EXTRACT_BMESH) {
143     /* Mesh */
144     if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) {
145       mr->vert_loose_len = 0;
146       mr->edge_loose_len = 0;
147
148       BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, __func__);
149
150       mr->ledges = MEM_mallocN(mr->edge_len * sizeof(int), __func__);
151       const MEdge *medge = mr->medge;
152       for (int e = 0; e < mr->edge_len; e++, medge++) {
153         if (medge->flag & ME_LOOSEEDGE) {
154           mr->ledges[mr->edge_loose_len++] = e;
155         }
156         /* Tag verts as not loose. */
157         BLI_BITMAP_ENABLE(lvert_map, medge->v1);
158         BLI_BITMAP_ENABLE(lvert_map, medge->v2);
159       }
160       if (mr->edge_loose_len < mr->edge_len) {
161         mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges));
162       }
163
164       mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__);
165       for (int v = 0; v < mr->vert_len; v++) {
166         if (!BLI_BITMAP_TEST(lvert_map, v)) {
167           mr->lverts[mr->vert_loose_len++] = v;
168         }
169       }
170       if (mr->vert_loose_len < mr->vert_len) {
171         mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts));
172       }
173
174       MEM_freeN(lvert_map);
175
176       mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
177     }
178   }
179   else {
180     /* #BMesh */
181     BMesh *bm = mr->bm;
182     if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) {
183       int elem_id;
184       BMIter iter;
185       BMVert *eve;
186       BMEdge *ede;
187       mr->vert_loose_len = 0;
188       mr->edge_loose_len = 0;
189
190       mr->lverts = MEM_mallocN(mr->vert_len * sizeof(*mr->lverts), __func__);
191       BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, elem_id) {
192         if (eve->e == NULL) {
193           mr->lverts[mr->vert_loose_len++] = elem_id;
194         }
195       }
196       if (mr->vert_loose_len < mr->vert_len) {
197         mr->lverts = MEM_reallocN(mr->lverts, mr->vert_loose_len * sizeof(*mr->lverts));
198       }
199
200       mr->ledges = MEM_mallocN(mr->edge_len * sizeof(*mr->ledges), __func__);
201       BM_ITER_MESH_INDEX (ede, &iter, bm, BM_EDGES_OF_MESH, elem_id) {
202         if (ede->l == NULL) {
203           mr->ledges[mr->edge_loose_len++] = elem_id;
204         }
205       }
206       if (mr->edge_loose_len < mr->edge_len) {
207         mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges));
208       }
209
210       mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
211     }
212   }
213 }
214
215 /**
216  * Part of the creation of the #MeshRenderData that happens in a thread.
217  */
218 static void mesh_render_data_update_looptris(MeshRenderData *mr,
219                                              const eMRIterType iter_type,
220                                              const eMRDataType data_flag)
221 {
222   Mesh *me = mr->me;
223   if (mr->extract_type != MR_EXTRACT_BMESH) {
224     /* Mesh */
225     if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
226       mr->mlooptri = MEM_mallocN(sizeof(*mr->mlooptri) * mr->tri_len, "MR_DATATYPE_LOOPTRI");
227       BKE_mesh_recalc_looptri(
228           me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mr->mlooptri);
229     }
230   }
231   else {
232     /* #BMesh */
233     if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
234       /* Edit mode ensures this is valid, no need to calculate. */
235       BLI_assert((mr->bm->totloop == 0) || (mr->edit_bmesh->looptris != NULL));
236     }
237   }
238 }
239
240 static void mesh_render_data_update_normals(MeshRenderData *mr,
241                                             const eMRIterType UNUSED(iter_type),
242                                             const eMRDataType data_flag)
243 {
244   Mesh *me = mr->me;
245   const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
246   const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
247
248   if (mr->extract_type != MR_EXTRACT_BMESH) {
249     /* Mesh */
250     if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
251       mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__);
252       BKE_mesh_calc_normals_poly((MVert *)mr->mvert,
253                                  NULL,
254                                  mr->vert_len,
255                                  mr->mloop,
256                                  mr->mpoly,
257                                  mr->loop_len,
258                                  mr->poly_len,
259                                  mr->poly_normals,
260                                  true);
261     }
262     if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
263       mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
264       short(*clnors)[2] = CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL);
265       BKE_mesh_normals_loop_split(mr->me->mvert,
266                                   mr->vert_len,
267                                   mr->me->medge,
268                                   mr->edge_len,
269                                   mr->me->mloop,
270                                   mr->loop_normals,
271                                   mr->loop_len,
272                                   mr->me->mpoly,
273                                   mr->poly_normals,
274                                   mr->poly_len,
275                                   is_auto_smooth,
276                                   split_angle,
277                                   NULL,
278                                   clnors,
279                                   NULL);
280     }
281   }
282   else {
283     /* #BMesh */
284     if (data_flag & MR_DATA_POLY_NOR) {
285       /* Use #BMFace.no instead. */
286     }
287     if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
288
289       const float(*vert_coords)[3] = NULL;
290       const float(*vert_normals)[3] = NULL;
291       const float(*poly_normals)[3] = NULL;
292
293       if (mr->edit_data && mr->edit_data->vertexCos) {
294         vert_coords = mr->bm_vert_coords;
295         vert_normals = mr->bm_vert_normals;
296         poly_normals = mr->bm_poly_normals;
297       }
298
299       mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
300       int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
301       BM_loops_calc_normal_vcos(mr->bm,
302                                 vert_coords,
303                                 vert_normals,
304                                 poly_normals,
305                                 is_auto_smooth,
306                                 split_angle,
307                                 mr->loop_normals,
308                                 NULL,
309                                 NULL,
310                                 clnors_offset,
311                                 false);
312     }
313   }
314 }
315
316 static MeshRenderData *mesh_render_data_create(Mesh *me,
317                                                const bool is_editmode,
318                                                const bool is_paint_mode,
319                                                const float obmat[4][4],
320                                                const bool do_final,
321                                                const bool do_uvedit,
322                                                const DRW_MeshCDMask *UNUSED(cd_used),
323                                                const ToolSettings *ts,
324                                                const eMRIterType iter_type,
325                                                const eMRDataType data_flag)
326 {
327   MeshRenderData *mr = MEM_callocN(sizeof(*mr), __func__);
328   mr->toolsettings = ts;
329   mr->mat_len = mesh_render_mat_len_get(me);
330
331   copy_m4_m4(mr->obmat, obmat);
332
333   if (is_editmode) {
334     BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final);
335     mr->bm = me->edit_mesh->bm;
336     mr->edit_bmesh = me->edit_mesh;
337     mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage;
338     mr->edit_data = mr->me->runtime.edit_data;
339
340     if (mr->edit_data) {
341       EditMeshData *emd = mr->edit_data;
342       if (emd->vertexCos) {
343         BKE_editmesh_cache_ensure_vert_normals(mr->edit_bmesh, emd);
344         BKE_editmesh_cache_ensure_poly_normals(mr->edit_bmesh, emd);
345       }
346
347       mr->bm_vert_coords = mr->edit_data->vertexCos;
348       mr->bm_vert_normals = mr->edit_data->vertexNos;
349       mr->bm_poly_normals = mr->edit_data->polyNos;
350       mr->bm_poly_centers = mr->edit_data->polyCos;
351     }
352
353     bool has_mdata = (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
354     bool use_mapped = has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original;
355
356     int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
357
358     BM_mesh_elem_index_ensure(mr->bm, bm_ensure_types);
359     BM_mesh_elem_table_ensure(mr->bm, bm_ensure_types & ~BM_LOOP);
360
361     mr->efa_act_uv = EDBM_uv_active_face_get(mr->edit_bmesh, false, false);
362     mr->efa_act = BM_mesh_active_face_get(mr->bm, false, true);
363     mr->eed_act = BM_mesh_active_edge_get(mr->bm);
364     mr->eve_act = BM_mesh_active_vert_get(mr->bm);
365
366     mr->crease_ofs = CustomData_get_offset(&mr->bm->edata, CD_CREASE);
367     mr->bweight_ofs = CustomData_get_offset(&mr->bm->edata, CD_BWEIGHT);
368 #ifdef WITH_FREESTYLE
369     mr->freestyle_edge_ofs = CustomData_get_offset(&mr->bm->edata, CD_FREESTYLE_EDGE);
370     mr->freestyle_face_ofs = CustomData_get_offset(&mr->bm->pdata, CD_FREESTYLE_FACE);
371 #endif
372
373     if (use_mapped) {
374       mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
375       mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
376       mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
377
378       use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex);
379     }
380
381     mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_BMESH;
382
383     /* Seems like the mesh_eval_final do not have the right origin indices.
384      * Force not mapped in this case. */
385     if (has_mdata && do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) {
386       // mr->edit_bmesh = NULL;
387       mr->extract_type = MR_EXTRACT_MESH;
388     }
389   }
390   else {
391     mr->me = me;
392     mr->edit_bmesh = NULL;
393
394     bool use_mapped = is_paint_mode && mr->me && !mr->me->runtime.is_original;
395     if (use_mapped) {
396       mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
397       mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
398       mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
399
400       use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex);
401     }
402
403     mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_MESH;
404   }
405
406   if (mr->extract_type != MR_EXTRACT_BMESH) {
407     /* Mesh */
408     mr->vert_len = mr->me->totvert;
409     mr->edge_len = mr->me->totedge;
410     mr->loop_len = mr->me->totloop;
411     mr->poly_len = mr->me->totpoly;
412     mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
413
414     mr->mvert = CustomData_get_layer(&mr->me->vdata, CD_MVERT);
415     mr->medge = CustomData_get_layer(&mr->me->edata, CD_MEDGE);
416     mr->mloop = CustomData_get_layer(&mr->me->ldata, CD_MLOOP);
417     mr->mpoly = CustomData_get_layer(&mr->me->pdata, CD_MPOLY);
418
419     mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
420     mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
421     mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
422   }
423   else {
424     /* #BMesh */
425     BMesh *bm = mr->bm;
426
427     mr->vert_len = bm->totvert;
428     mr->edge_len = bm->totedge;
429     mr->loop_len = bm->totloop;
430     mr->poly_len = bm->totface;
431     mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
432   }
433   mesh_render_data_update_loose_geom(mr, iter_type, data_flag);
434
435   return mr;
436 }
437
438 static void mesh_render_data_free(MeshRenderData *mr)
439 {
440   MEM_SAFE_FREE(mr->mlooptri);
441   MEM_SAFE_FREE(mr->poly_normals);
442   MEM_SAFE_FREE(mr->loop_normals);
443
444   MEM_SAFE_FREE(mr->lverts);
445   MEM_SAFE_FREE(mr->ledges);
446
447   MEM_freeN(mr);
448 }
449
450 BLI_INLINE BMFace *bm_original_face_get(const MeshRenderData *mr, int idx)
451 {
452   return ((mr->p_origindex != NULL) && (mr->p_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
453              BM_face_at_index(mr->bm, mr->p_origindex[idx]) :
454              NULL;
455 }
456
457 BLI_INLINE BMEdge *bm_original_edge_get(const MeshRenderData *mr, int idx)
458 {
459   return ((mr->e_origindex != NULL) && (mr->e_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
460              BM_edge_at_index(mr->bm, mr->e_origindex[idx]) :
461              NULL;
462 }
463
464 BLI_INLINE BMVert *bm_original_vert_get(const MeshRenderData *mr, int idx)
465 {
466   return ((mr->v_origindex != NULL) && (mr->v_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ?
467              BM_vert_at_index(mr->bm, mr->v_origindex[idx]) :
468              NULL;
469 }
470
471 BLI_INLINE const float *bm_vert_co_get(const MeshRenderData *mr, const BMVert *eve)
472 {
473   const float(*vert_coords)[3] = mr->bm_vert_coords;
474   if (vert_coords != NULL) {
475     return vert_coords[BM_elem_index_get(eve)];
476   }
477   else {
478     UNUSED_VARS(mr);
479     return eve->co;
480   }
481 }
482
483 BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *eve)
484 {
485   const float(*vert_normals)[3] = mr->bm_vert_normals;
486   if (vert_normals != NULL) {
487     return vert_normals[BM_elem_index_get(eve)];
488   }
489   else {
490     UNUSED_VARS(mr);
491     return eve->no;
492   }
493 }
494
495 BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *efa)
496 {
497   const float(*poly_normals)[3] = mr->bm_poly_normals;
498   if (poly_normals != NULL) {
499     return poly_normals[BM_elem_index_get(efa)];
500   }
501   else {
502     UNUSED_VARS(mr);
503     return efa->no;
504   }
505 }
506
507 /** \} */
508
509 /* ---------------------------------------------------------------------- */
510 /** \name Mesh Elements Extract Iter
511  * \{ */
512
513 typedef void *(ExtractInitFn)(const MeshRenderData *mr, void *buffer);
514
515 typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr,
516                                 int tri_index,
517                                 BMLoop **ltri,
518                                 void *data);
519 typedef void(ExtractTriMeshFn)(const MeshRenderData *mr,
520                                int tri_index,
521                                const MLoopTri *mlt,
522                                void *data);
523
524 typedef void(ExtractLoopBMeshFn)(const MeshRenderData *mr, int loop_index, BMLoop *el, void *data);
525 typedef void(ExtractLoopMeshFn)(const MeshRenderData *mr,
526                                 int loop_index,
527                                 const MLoop *mloop,
528                                 int poly_index,
529                                 const MPoly *mpoly,
530                                 void *data);
531
532 typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr,
533                                   int ledge_index,
534                                   BMEdge *eed,
535                                   void *data);
536 typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr,
537                                  int ledge_index,
538                                  const MEdge *medge,
539                                  void *data);
540
541 typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr,
542                                   int lvert_index,
543                                   BMVert *eve,
544                                   void *data);
545 typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr,
546                                  int lvert_index,
547                                  const MVert *mvert,
548                                  void *data);
549 typedef void(ExtractFinishFn)(const MeshRenderData *mr, void *buffer, void *data);
550
551 typedef struct MeshExtract {
552   /** Executed on main thread and return user data for iteration functions. */
553   ExtractInitFn *init;
554   /** Executed on one (or more if use_threading) worker thread(s). */
555   ExtractTriBMeshFn *iter_looptri_bm;
556   ExtractTriMeshFn *iter_looptri_mesh;
557   ExtractLoopBMeshFn *iter_loop_bm;
558   ExtractLoopMeshFn *iter_loop_mesh;
559   ExtractLEdgeBMeshFn *iter_ledge_bm;
560   ExtractLEdgeMeshFn *iter_ledge_mesh;
561   ExtractLVertBMeshFn *iter_lvert_bm;
562   ExtractLVertMeshFn *iter_lvert_mesh;
563   /** Executed on one worker thread after all elements iterations. */
564   ExtractFinishFn *finish;
565   /** Used to request common data. */
566   const eMRDataType data_flag;
567   /** Used to know if the element callbacks are thread-safe and can be parallelized. */
568   const bool use_threading;
569 } MeshExtract;
570
571 BLI_INLINE eMRIterType mesh_extract_iter_type(const MeshExtract *ext)
572 {
573   eMRIterType type = 0;
574   SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri_mesh), MR_ITER_LOOPTRI);
575   SET_FLAG_FROM_TEST(type, (ext->iter_loop_bm || ext->iter_loop_mesh), MR_ITER_LOOP);
576   SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge_mesh), MR_ITER_LEDGE);
577   SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert_mesh), MR_ITER_LVERT);
578   return type;
579 }
580
581 /** \} */
582
583 /* ---------------------------------------------------------------------- */
584 /** \name Extract Triangles Indices
585  * \{ */
586
587 typedef struct MeshExtract_Tri_Data {
588   GPUIndexBufBuilder elb;
589   int *tri_mat_start;
590   int *tri_mat_end;
591 } MeshExtract_Tri_Data;
592
593 static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
594 {
595   MeshExtract_Tri_Data *data = MEM_callocN(sizeof(*data), __func__);
596
597   size_t mat_tri_idx_size = sizeof(int) * mr->mat_len;
598   data->tri_mat_start = MEM_callocN(mat_tri_idx_size, __func__);
599   data->tri_mat_end = MEM_callocN(mat_tri_idx_size, __func__);
600
601   int *mat_tri_len = data->tri_mat_start;
602   /* Count how many triangle for each material. */
603   if (mr->extract_type == MR_EXTRACT_BMESH) {
604     BMIter iter;
605     BMFace *efa;
606     BM_ITER_MESH (efa, &iter, mr->bm, BM_FACES_OF_MESH) {
607       if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
608         int mat = min_ii(efa->mat_nr, mr->mat_len - 1);
609         mat_tri_len[mat] += efa->len - 2;
610       }
611     }
612   }
613   else {
614     const MPoly *mpoly = mr->mpoly;
615     for (int p = 0; p < mr->poly_len; p++, mpoly++) {
616       if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
617         int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
618         mat_tri_len[mat] += mpoly->totloop - 2;
619       }
620     }
621   }
622   /* Accumulate triangle lengths per material to have correct offsets. */
623   int ofs = mat_tri_len[0];
624   mat_tri_len[0] = 0;
625   for (int i = 1; i < mr->mat_len; i++) {
626     int tmp = mat_tri_len[i];
627     mat_tri_len[i] = ofs;
628     ofs += tmp;
629   }
630
631   memcpy(data->tri_mat_end, mat_tri_len, mat_tri_idx_size);
632
633   int visible_tri_tot = ofs;
634   GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, visible_tri_tot, mr->loop_len);
635
636   return data;
637 }
638
639 static void extract_tris_looptri_bmesh(const MeshRenderData *mr,
640                                        int UNUSED(t),
641                                        BMLoop **elt,
642                                        void *_data)
643 {
644   if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
645     MeshExtract_Tri_Data *data = _data;
646     int *mat_tri_ofs = data->tri_mat_end;
647     int mat = min_ii(elt[0]->f->mat_nr, mr->mat_len - 1);
648     GPU_indexbuf_set_tri_verts(&data->elb,
649                                mat_tri_ofs[mat]++,
650                                BM_elem_index_get(elt[0]),
651                                BM_elem_index_get(elt[1]),
652                                BM_elem_index_get(elt[2]));
653   }
654 }
655
656 static void extract_tris_looptri_mesh(const MeshRenderData *mr,
657                                       int UNUSED(t),
658                                       const MLoopTri *mlt,
659                                       void *_data)
660 {
661   const MPoly *mpoly = &mr->mpoly[mlt->poly];
662   if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
663     MeshExtract_Tri_Data *data = _data;
664     int *mat_tri_ofs = data->tri_mat_end;
665     int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
666     GPU_indexbuf_set_tri_verts(
667         &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
668   }
669 }
670
671 static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data)
672 {
673   MeshExtract_Tri_Data *data = _data;
674   GPU_indexbuf_build_in_place(&data->elb, ibo);
675   /* HACK: Create ibo sub-ranges and assign them to each #GPUBatch. */
676   if (mr->use_final_mesh && mr->cache->surface_per_mat && mr->cache->surface_per_mat[0]) {
677     BLI_assert(mr->cache->surface_per_mat[0]->elem == ibo);
678     for (int i = 0; i < mr->mat_len; i++) {
679       /* Multiply by 3 because these are triangle indices. */
680       int start = data->tri_mat_start[i] * 3;
681       int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3;
682       GPUIndexBuf *sub_ibo = GPU_indexbuf_create_subrange(ibo, start, len);
683       /* WARNING: We modify the #GPUBatch here! */
684       GPU_batch_elembuf_set(mr->cache->surface_per_mat[i], sub_ibo, true);
685     }
686   }
687   MEM_freeN(data->tri_mat_start);
688   MEM_freeN(data->tri_mat_end);
689   MEM_freeN(data);
690 }
691
692 static const MeshExtract extract_tris = {
693     .init = extract_tris_init,
694     .iter_looptri_bm = extract_tris_looptri_bmesh,
695     .iter_looptri_mesh = extract_tris_looptri_mesh,
696     .finish = extract_tris_finish,
697     .data_flag = 0,
698     .use_threading = false,
699 };
700
701 /** \} */
702
703 /* ---------------------------------------------------------------------- */
704 /** \name Extract Edges Indices
705  * \{ */
706
707 static void *extract_lines_init(const MeshRenderData *mr, void *UNUSED(buf))
708 {
709   GPUIndexBufBuilder *elb = MEM_mallocN(sizeof(*elb), __func__);
710   /* Put loose edges at the end. */
711   GPU_indexbuf_init(
712       elb, GPU_PRIM_LINES, mr->edge_len + mr->edge_loose_len, mr->loop_len + mr->loop_loose_len);
713   return elb;
714 }
715
716 static void extract_lines_loop_bmesh(const MeshRenderData *UNUSED(mr),
717                                      int l,
718                                      BMLoop *loop,
719                                      void *elb)
720 {
721   if (!BM_elem_flag_test(loop->e, BM_ELEM_HIDDEN)) {
722     GPU_indexbuf_set_line_verts(elb, BM_elem_index_get(loop->e), l, BM_elem_index_get(loop->next));
723   }
724   else {
725     GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(loop->e));
726   }
727 }
728
729 static void extract_lines_loop_mesh(const MeshRenderData *mr,
730                                     int l,
731                                     const MLoop *mloop,
732                                     int UNUSED(p),
733                                     const MPoly *mpoly,
734                                     void *elb)
735 {
736   const MEdge *medge = &mr->medge[mloop->e];
737   if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
738         ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
739          (mr->e_origindex[mloop->e] == ORIGINDEX_NONE)))) {
740     int loopend = mpoly->totloop + mpoly->loopstart - 1;
741     int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
742     GPU_indexbuf_set_line_verts(elb, mloop->e, l, other_loop);
743   }
744   else {
745     GPU_indexbuf_set_line_restart(elb, mloop->e);
746   }
747 }
748
749 static void extract_lines_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb)
750 {
751   int ledge_idx = mr->edge_len + e;
752   if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
753     int l = mr->loop_len + e * 2;
754     GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1);
755   }
756   else {
757     GPU_indexbuf_set_line_restart(elb, ledge_idx);
758   }
759   /* Don't render the edge twice. */
760   GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed));
761 }
762
763 static void extract_lines_ledge_mesh(const MeshRenderData *mr,
764                                      int e,
765                                      const MEdge *medge,
766                                      void *elb)
767 {
768   int ledge_idx = mr->edge_len + e;
769   int edge_idx = mr->ledges[e];
770   if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
771         ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
772          (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) {
773     int l = mr->loop_len + e * 2;
774     GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1);
775   }
776   else {
777     GPU_indexbuf_set_line_restart(elb, ledge_idx);
778   }
779   /* Don't render the edge twice. */
780   GPU_indexbuf_set_line_restart(elb, edge_idx);
781 }
782
783 static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
784 {
785   GPU_indexbuf_build_in_place(elb, ibo);
786   MEM_freeN(elb);
787 }
788
789 static const MeshExtract extract_lines = {
790     .init = extract_lines_init,
791     .iter_loop_bm = extract_lines_loop_bmesh,
792     .iter_loop_mesh = extract_lines_loop_mesh,
793     .iter_ledge_bm = extract_lines_ledge_bmesh,
794     .iter_ledge_mesh = extract_lines_ledge_mesh,
795     .finish = extract_lines_finish,
796     .data_flag = 0,
797     .use_threading = false,
798 };
799 /** \} */
800
801 /* ---------------------------------------------------------------------- */
802 /** \name Extract Loose Edges Sub Buffer
803  * \{ */
804
805 static void extract_lines_loose_subbuffer(const MeshRenderData *mr)
806 {
807   BLI_assert(mr->cache->final.ibo.lines);
808   /* Multiply by 2 because these are edges indices. */
809   const int start = mr->edge_len * 2;
810   const int len = mr->edge_loose_len * 2;
811   GPU_indexbuf_create_subrange_in_place(
812       mr->cache->final.ibo.lines_loose, mr->cache->final.ibo.lines, start, len);
813   mr->cache->no_loose_wire = (len == 0);
814 }
815
816 static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void *ibo, void *elb)
817 {
818   GPU_indexbuf_build_in_place(elb, ibo);
819   extract_lines_loose_subbuffer(mr);
820   MEM_freeN(elb);
821 }
822
823 static const MeshExtract extract_lines_with_lines_loose = {
824     .init = extract_lines_init,
825     .iter_loop_bm = extract_lines_loop_bmesh,
826     .iter_loop_mesh = extract_lines_loop_mesh,
827     .iter_ledge_bm = extract_lines_ledge_bmesh,
828     .iter_ledge_mesh = extract_lines_ledge_mesh,
829     .finish = extract_lines_with_lines_loose_finish,
830     .data_flag = 0,
831     .use_threading = false,
832 };
833
834 /** \} */
835
836 /* ---------------------------------------------------------------------- */
837 /** \name Extract Point Indices
838  * \{ */
839
840 static void *extract_points_init(const MeshRenderData *mr, void *UNUSED(buf))
841 {
842   GPUIndexBufBuilder *elb = MEM_mallocN(sizeof(*elb), __func__);
843   GPU_indexbuf_init(elb, GPU_PRIM_POINTS, mr->vert_len, mr->loop_len + mr->loop_loose_len);
844   return elb;
845 }
846
847 BLI_INLINE void vert_set_bmesh(GPUIndexBufBuilder *elb, BMVert *eve, int loop)
848 {
849   int vert_idx = BM_elem_index_get(eve);
850   if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
851     GPU_indexbuf_set_point_vert(elb, vert_idx, loop);
852   }
853   else {
854     GPU_indexbuf_set_point_restart(elb, vert_idx);
855   }
856 }
857
858 BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb,
859                               const MeshRenderData *mr,
860                               int vert_idx,
861                               int loop)
862 {
863   const MVert *mvert = &mr->mvert[vert_idx];
864   if (!((mr->use_hide && (mvert->flag & ME_HIDE)) ||
865         ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
866          (mr->v_origindex[vert_idx] == ORIGINDEX_NONE)))) {
867     GPU_indexbuf_set_point_vert(elb, vert_idx, loop);
868   }
869   else {
870     GPU_indexbuf_set_point_restart(elb, vert_idx);
871   }
872 }
873
874 static void extract_points_loop_bmesh(const MeshRenderData *UNUSED(mr),
875                                       int l,
876                                       BMLoop *loop,
877                                       void *elb)
878 {
879   vert_set_bmesh(elb, loop->v, l);
880 }
881
882 static void extract_points_loop_mesh(const MeshRenderData *mr,
883                                      int l,
884                                      const MLoop *mloop,
885                                      int UNUSED(p),
886                                      const MPoly *UNUSED(mpoly),
887                                      void *elb)
888 {
889   vert_set_mesh(elb, mr, mloop->v, l);
890 }
891
892 static void extract_points_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb)
893 {
894   vert_set_bmesh(elb, eed->v1, mr->loop_len + e * 2);
895   vert_set_bmesh(elb, eed->v2, mr->loop_len + e * 2 + 1);
896 }
897
898 static void extract_points_ledge_mesh(const MeshRenderData *mr,
899                                       int e,
900                                       const MEdge *medge,
901                                       void *elb)
902 {
903   vert_set_mesh(elb, mr, medge->v1, mr->loop_len + e * 2);
904   vert_set_mesh(elb, mr, medge->v2, mr->loop_len + e * 2 + 1);
905 }
906
907 static void extract_points_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *elb)
908 {
909   vert_set_bmesh(elb, eve, mr->loop_len + mr->edge_loose_len * 2 + v);
910 }
911
912 static void extract_points_lvert_mesh(const MeshRenderData *mr,
913                                       int v,
914                                       const MVert *UNUSED(mvert),
915                                       void *elb)
916 {
917   vert_set_mesh(elb, mr, mr->lverts[v], mr->loop_len + mr->edge_loose_len * 2 + v);
918 }
919
920 static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
921 {
922   GPU_indexbuf_build_in_place(elb, ibo);
923   MEM_freeN(elb);
924 }
925
926 static const MeshExtract extract_points = {
927     .init = extract_points_init,
928     .iter_loop_bm = extract_points_loop_bmesh,
929     .iter_loop_mesh = extract_points_loop_mesh,
930     .iter_ledge_bm = extract_points_ledge_bmesh,
931     .iter_ledge_mesh = extract_points_ledge_mesh,
932     .iter_lvert_bm = extract_points_lvert_bmesh,
933     .iter_lvert_mesh = extract_points_lvert_mesh,
934     .finish = extract_points_finish,
935     .data_flag = 0,
936     .use_threading = false,
937 };
938
939 /** \} */
940
941 /* ---------------------------------------------------------------------- */
942 /** \name Extract Facedots Indices
943  * \{ */
944
945 static void *extract_fdots_init(const MeshRenderData *mr, void *UNUSED(buf))
946 {
947   GPUIndexBufBuilder *elb = MEM_mallocN(sizeof(*elb), __func__);
948   GPU_indexbuf_init(elb, GPU_PRIM_POINTS, mr->poly_len, mr->poly_len);
949   return elb;
950 }
951
952 static void extract_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr),
953                                      int UNUSED(l),
954                                      BMLoop *loop,
955                                      void *elb)
956 {
957   int face_idx = BM_elem_index_get(loop->f);
958   if (!BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN)) {
959     GPU_indexbuf_set_point_vert(elb, face_idx, face_idx);
960   }
961   else {
962     GPU_indexbuf_set_point_restart(elb, face_idx);
963   }
964 }
965
966 static void extract_fdots_loop_mesh(const MeshRenderData *mr,
967                                     int UNUSED(l),
968                                     const MLoop *mloop,
969                                     int p,
970                                     const MPoly *mpoly,
971                                     void *elb)
972 {
973   const MVert *mvert = &mr->mvert[mloop->v];
974   if ((!mr->use_subsurf_fdots || (mvert->flag & ME_VERT_FACEDOT)) &&
975       !(mr->use_hide && (mpoly->flag & ME_HIDE))) {
976     GPU_indexbuf_set_point_vert(elb, p, p);
977   }
978   else {
979     GPU_indexbuf_set_point_restart(elb, p);
980   }
981 }
982
983 static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
984 {
985   GPU_indexbuf_build_in_place(elb, ibo);
986   MEM_freeN(elb);
987 }
988
989 static const MeshExtract extract_fdots = {
990     .init = extract_fdots_init,
991     .iter_loop_bm = extract_fdots_loop_bmesh,
992     .iter_loop_mesh = extract_fdots_loop_mesh,
993     .finish = extract_fdots_finish,
994     .data_flag = 0,
995     .use_threading = false,
996 };
997
998 /** \} */
999
1000 /* ---------------------------------------------------------------------- */
1001 /** \name Extract Paint Mask Line Indices
1002  * \{ */
1003
1004 typedef struct MeshExtract_LinePaintMask_Data {
1005   GPUIndexBufBuilder elb;
1006   /** One bit per edge set if face is selected. */
1007   BLI_bitmap select_map[0];
1008 } MeshExtract_LinePaintMask_Data;
1009
1010 static void *extract_lines_paint_mask_init(const MeshRenderData *mr, void *UNUSED(buf))
1011 {
1012   size_t bitmap_size = BLI_BITMAP_SIZE(mr->edge_len);
1013   MeshExtract_LinePaintMask_Data *data = MEM_callocN(sizeof(*data) + bitmap_size, __func__);
1014   GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr->edge_len, mr->loop_len);
1015   return data;
1016 }
1017
1018 static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr,
1019                                                int l,
1020                                                const MLoop *mloop,
1021                                                int UNUSED(p),
1022                                                const MPoly *mpoly,
1023                                                void *_data)
1024 {
1025   MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data;
1026   const int edge_idx = mloop->e;
1027   const MEdge *medge = &mr->medge[edge_idx];
1028   if (!((mr->use_hide && (medge->flag & ME_HIDE)) ||
1029         ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
1030          (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) {
1031
1032     int loopend = mpoly->totloop + mpoly->loopstart - 1;
1033     int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
1034     if (mpoly->flag & ME_FACE_SEL) {
1035       if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, edge_idx)) {
1036         /* Hide edge as it has more than 2 selected loop. */
1037         GPU_indexbuf_set_line_restart(&data->elb, edge_idx);
1038       }
1039       else {
1040         /* First selected loop. Set edge visible, overwriting any unselected loop. */
1041         GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop);
1042       }
1043     }
1044     else {
1045       /* Set theses unselected loop only if this edge has no other selected loop. */
1046       if (!BLI_BITMAP_TEST(data->select_map, edge_idx)) {
1047         GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop);
1048       }
1049     }
1050   }
1051   else {
1052     GPU_indexbuf_set_line_restart(&data->elb, edge_idx);
1053   }
1054 }
1055 static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
1056                                             void *ibo,
1057                                             void *_data)
1058 {
1059   MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data;
1060
1061   GPU_indexbuf_build_in_place(&data->elb, ibo);
1062   MEM_freeN(data);
1063 }
1064
1065 static const MeshExtract extract_lines_paint_mask = {
1066     .init = extract_lines_paint_mask_init,
1067     .iter_loop_mesh = extract_lines_paint_mask_loop_mesh,
1068     .finish = extract_lines_paint_mask_finish,
1069     .data_flag = 0,
1070     .use_threading = false,
1071 };
1072
1073 /** \} */
1074
1075 /* ---------------------------------------------------------------------- */
1076 /** \name Extract Line Adjacency Indices
1077  * \{ */
1078
1079 #define NO_EDGE INT_MAX
1080
1081 typedef struct MeshExtract_LineAdjacency_Data {
1082   GPUIndexBufBuilder elb;
1083   EdgeHash *eh;
1084   bool is_manifold;
1085   /* Array to convert vert index to any loop index of this vert. */
1086   uint vert_to_loop[0];
1087 } MeshExtract_LineAdjacency_Data;
1088
1089 static void *extract_lines_adjacency_init(const MeshRenderData *mr, void *UNUSED(buf))
1090 {
1091   /* Similar to poly_to_tri_count().
1092    * There is always (loop + triangle - 1) edges inside a polygon.
1093    * Accumulate for all polys and you get : */
1094   uint tess_edge_len = mr->loop_len + mr->tri_len - mr->poly_len;
1095
1096   size_t vert_to_loop_size = sizeof(uint) * mr->vert_len;
1097
1098   MeshExtract_LineAdjacency_Data *data = MEM_callocN(sizeof(*data) + vert_to_loop_size, __func__);
1099   GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES_ADJ, tess_edge_len, mr->loop_len);
1100   data->eh = BLI_edgehash_new_ex(__func__, tess_edge_len);
1101   data->is_manifold = true;
1102   return data;
1103 }
1104
1105 BLI_INLINE void lines_adjacency_triangle(
1106     uint v1, uint v2, uint v3, uint l1, uint l2, uint l3, MeshExtract_LineAdjacency_Data *data)
1107 {
1108   GPUIndexBufBuilder *elb = &data->elb;
1109   /* Iterate around the triangle's edges. */
1110   for (int e = 0; e < 3; e++) {
1111     SHIFT3(uint, v3, v2, v1);
1112     SHIFT3(uint, l3, l2, l1);
1113
1114     bool inv_indices = (v2 > v3);
1115     void **pval;
1116     bool value_is_init = BLI_edgehash_ensure_p(data->eh, v2, v3, &pval);
1117     int v_data = POINTER_AS_INT(*pval);
1118     if (!value_is_init || v_data == NO_EDGE) {
1119       /* Save the winding order inside the sign bit. Because the
1120        * Edge-hash sort the keys and we need to compare winding later. */
1121       int value = (int)l1 + 1; /* 0 cannot be signed so add one. */
1122       *pval = POINTER_FROM_INT((inv_indices) ? -value : value);
1123       /* Store loop indices for remaining non-manifold edges. */
1124       data->vert_to_loop[v2] = l2;
1125       data->vert_to_loop[v3] = l3;
1126     }
1127     else {
1128       /* HACK Tag as not used. Prevent overhead of BLI_edgehash_remove. */
1129       *pval = POINTER_FROM_INT(NO_EDGE);
1130       bool inv_opposite = (v_data < 0);
1131       uint l_opposite = (uint)abs(v_data) - 1;
1132       /* TODO Make this part thread-safe. */
1133       if (inv_opposite == inv_indices) {
1134         /* Don't share edge if triangles have non matching winding. */
1135         GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l1);
1136         GPU_indexbuf_add_line_adj_verts(elb, l_opposite, l2, l3, l_opposite);
1137         data->is_manifold = false;
1138       }
1139       else {
1140         GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l_opposite);
1141       }
1142     }
1143   }
1144 }
1145
1146 static void extract_lines_adjacency_looptri_bmesh(const MeshRenderData *UNUSED(mr),
1147                                                   int UNUSED(t),
1148                                                   BMLoop **elt,
1149                                                   void *data)
1150 {
1151   if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
1152     lines_adjacency_triangle(BM_elem_index_get(elt[0]->v),
1153                              BM_elem_index_get(elt[1]->v),
1154                              BM_elem_index_get(elt[2]->v),
1155                              BM_elem_index_get(elt[0]),
1156                              BM_elem_index_get(elt[1]),
1157                              BM_elem_index_get(elt[2]),
1158                              data);
1159   }
1160 }
1161
1162 static void extract_lines_adjacency_looptri_mesh(const MeshRenderData *mr,
1163                                                  int UNUSED(t),
1164                                                  const MLoopTri *mlt,
1165                                                  void *data)
1166 {
1167   const MPoly *mpoly = &mr->mpoly[mlt->poly];
1168   if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
1169     lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v,
1170                              mr->mloop[mlt->tri[1]].v,
1171                              mr->mloop[mlt->tri[2]].v,
1172                              mlt->tri[0],
1173                              mlt->tri[1],
1174                              mlt->tri[2],
1175                              data);
1176   }
1177 }
1178
1179 static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo, void *_data)
1180 {
1181   MeshExtract_LineAdjacency_Data *data = (MeshExtract_LineAdjacency_Data *)_data;
1182   /* Create edges for remaining non manifold edges. */
1183   EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh);
1184   for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
1185     uint v2, v3, l1, l2, l3;
1186     int v_data = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi));
1187     if (v_data != NO_EDGE) {
1188       BLI_edgehashIterator_getKey(ehi, &v2, &v3);
1189       l1 = (uint)abs(v_data) - 1;
1190       if (v_data < 0) { /* inv_opposite  */
1191         SWAP(uint, v2, v3);
1192       }
1193       l2 = data->vert_to_loop[v2];
1194       l3 = data->vert_to_loop[v3];
1195       GPU_indexbuf_add_line_adj_verts(&data->elb, l1, l2, l3, l1);
1196       data->is_manifold = false;
1197     }
1198   }
1199   BLI_edgehashIterator_free(ehi);
1200   BLI_edgehash_free(data->eh, NULL);
1201
1202   mr->cache->is_manifold = data->is_manifold;
1203
1204   GPU_indexbuf_build_in_place(&data->elb, ibo);
1205   MEM_freeN(data);
1206 }
1207
1208 #undef NO_EDGE
1209
1210 static const MeshExtract extract_lines_adjacency = {
1211     .init = extract_lines_adjacency_init,
1212     .iter_looptri_bm = extract_lines_adjacency_looptri_bmesh,
1213     .iter_looptri_mesh = extract_lines_adjacency_looptri_mesh,
1214     .finish = extract_lines_adjacency_finish,
1215     .data_flag = 0,
1216     .use_threading = false,
1217 };
1218
1219 /** \} */
1220
1221 /* ---------------------------------------------------------------------- */
1222 /** \name Extract Edit UV Triangles Indices
1223  * \{ */
1224
1225 typedef struct MeshExtract_EditUvElem_Data {
1226   GPUIndexBufBuilder elb;
1227   bool sync_selection;
1228 } MeshExtract_EditUvElem_Data;
1229
1230 static void *extract_edituv_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
1231 {
1232   MeshExtract_EditUvElem_Data *data = MEM_callocN(sizeof(*data), __func__);
1233   GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, mr->tri_len, mr->loop_len);
1234   data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
1235   return data;
1236 }
1237
1238 BLI_INLINE void edituv_tri_add(
1239     MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2, int v3)
1240 {
1241   if (!hidden && (data->sync_selection || selected)) {
1242     GPU_indexbuf_add_tri_verts(&data->elb, v1, v2, v3);
1243   }
1244 }
1245
1246 static void extract_edituv_tris_looptri_bmesh(const MeshRenderData *UNUSED(mr),
1247                                               int UNUSED(t),
1248                                               BMLoop **elt,
1249                                               void *data)
1250 {
1251   edituv_tri_add(data,
1252                  BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN),
1253                  BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT),
1254                  BM_elem_index_get(elt[0]),
1255                  BM_elem_index_get(elt[1]),
1256                  BM_elem_index_get(elt[2]));
1257 }
1258
1259 static void extract_edituv_tris_looptri_mesh(const MeshRenderData *mr,
1260                                              int UNUSED(t),
1261                                              const MLoopTri *mlt,
1262                                              void *data)
1263 {
1264   const MPoly *mpoly = &mr->mpoly[mlt->poly];
1265   edituv_tri_add(data,
1266                  (mpoly->flag & ME_HIDE) != 0,
1267                  (mpoly->flag & ME_FACE_SEL) != 0,
1268                  mlt->tri[0],
1269                  mlt->tri[1],
1270                  mlt->tri[2]);
1271 }
1272
1273 static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
1274 {
1275   MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
1276   GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
1277   MEM_freeN(extract_data);
1278 }
1279
1280 static const MeshExtract extract_edituv_tris = {
1281     .init = extract_edituv_tris_init,
1282     .iter_looptri_bm = extract_edituv_tris_looptri_bmesh,
1283     .iter_looptri_mesh = extract_edituv_tris_looptri_mesh,
1284     .finish = extract_edituv_tris_finish,
1285     .data_flag = 0,
1286     .use_threading = false,
1287 };
1288
1289 /** \} */
1290
1291 /* ---------------------------------------------------------------------- */
1292 /** \name Extract Edit UV Line Indices around faces
1293  * \{ */
1294
1295 static void *extract_edituv_lines_init(const MeshRenderData *mr, void *UNUSED(ibo))
1296 {
1297   MeshExtract_EditUvElem_Data *data = MEM_callocN(sizeof(*data), __func__);
1298   GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr->loop_len, mr->loop_len);
1299
1300   data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
1301   return data;
1302 }
1303
1304 BLI_INLINE void edituv_edge_add(
1305     MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2)
1306 {
1307   if (!hidden && (data->sync_selection || selected)) {
1308     GPU_indexbuf_add_line_verts(&data->elb, v1, v2);
1309   }
1310 }
1311
1312 static void extract_edituv_lines_loop_bmesh(const MeshRenderData *UNUSED(mr),
1313                                             int l,
1314                                             BMLoop *loop,
1315                                             void *data)
1316 {
1317   edituv_edge_add(data,
1318                   BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
1319                   BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
1320                   l,
1321                   BM_elem_index_get(loop->next));
1322 }
1323
1324 static void extract_edituv_lines_loop_mesh(const MeshRenderData *mr,
1325                                            int loop_idx,
1326                                            const MLoop *mloop,
1327                                            int UNUSED(p),
1328                                            const MPoly *mpoly,
1329                                            void *data)
1330 {
1331   int loopend = mpoly->totloop + mpoly->loopstart - 1;
1332   int loop_next_idx = (loop_idx == loopend) ? mpoly->loopstart : (loop_idx + 1);
1333   const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[mloop->e] != ORIGINDEX_NONE);
1334   edituv_edge_add(data,
1335                   (mpoly->flag & ME_HIDE) != 0 || !real_edge,
1336                   (mpoly->flag & ME_FACE_SEL) != 0,
1337                   loop_idx,
1338                   loop_next_idx);
1339 }
1340
1341 static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
1342 {
1343   MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
1344   GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
1345   MEM_freeN(extract_data);
1346 }
1347
1348 static const MeshExtract extract_edituv_lines = {
1349     .init = extract_edituv_lines_init,
1350     .iter_loop_bm = extract_edituv_lines_loop_bmesh,
1351     .iter_loop_mesh = extract_edituv_lines_loop_mesh,
1352     .finish = extract_edituv_lines_finish,
1353     .data_flag = 0,
1354     .use_threading = false,
1355 };
1356
1357 /** \} */
1358
1359 /* ---------------------------------------------------------------------- */
1360 /** \name Extract Edit UV Points Indices
1361  * \{ */
1362
1363 static void *extract_edituv_points_init(const MeshRenderData *mr, void *UNUSED(ibo))
1364 {
1365   MeshExtract_EditUvElem_Data *data = MEM_callocN(sizeof(*data), __func__);
1366   GPU_indexbuf_init(&data->elb, GPU_PRIM_POINTS, mr->loop_len, mr->loop_len);
1367
1368   data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
1369   return data;
1370 }
1371
1372 BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data,
1373                                  bool hidden,
1374                                  bool selected,
1375                                  int v1)
1376 {
1377   if (!hidden && (data->sync_selection || selected)) {
1378     GPU_indexbuf_add_point_vert(&data->elb, v1);
1379   }
1380 }
1381
1382 static void extract_edituv_points_loop_bmesh(const MeshRenderData *UNUSED(mr),
1383                                              int l,
1384                                              BMLoop *loop,
1385                                              void *data)
1386 {
1387   edituv_point_add(data,
1388                    BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
1389                    BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
1390                    l);
1391 }
1392
1393 static void extract_edituv_points_loop_mesh(const MeshRenderData *mr,
1394                                             int l,
1395                                             const MLoop *mloop,
1396                                             int UNUSED(p),
1397                                             const MPoly *mpoly,
1398                                             void *data)
1399 {
1400   const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
1401                           mr->v_origindex[mloop->v] != ORIGINDEX_NONE);
1402   edituv_point_add(
1403       data, ((mpoly->flag & ME_HIDE) != 0) || !real_vert, (mpoly->flag & ME_FACE_SEL) != 0, l);
1404 }
1405
1406 static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data)
1407 {
1408   MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data;
1409   GPU_indexbuf_build_in_place(&extract_data->elb, ibo);
1410   MEM_freeN(extract_data);
1411 }
1412
1413 static const MeshExtract extract_edituv_points = {
1414     .init = extract_edituv_points_init,
1415     .iter_loop_bm = extract_edituv_points_loop_bmesh,
1416     .iter_loop_mesh = extract_edituv_points_loop_mesh,
1417     .finish = extract_edituv_points_finish,
1418     .data_flag = 0,
1419     .use_threading = false,
1420 };
1421
1422 /** \} */
1423
1424 /* ---------------------------------------------------------------------- */
1425 /** \name Extract Edit UV Facedots Indices
1426  * \{ */
1427
1428 static void *extract_edituv_fdots_init(const MeshRenderData *mr, void *UNUSED(ibo))
1429 {
1430   MeshExtract_EditUvElem_Data *data = MEM_callocN(sizeof(*data), __func__);
1431   GPU_indexbuf_init(&data->elb, GPU_PRIM_POINTS, mr->poly_len, mr->poly_len);
1432
1433   data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
1434   return data;
1435 }
1436
1437 BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data,
1438                                    bool hidden,
1439                                    bool selected,
1440                                    int face_idx)
1441 {
1442   if (!hidden && (data->sync_selection || selected)) {
1443     GPU_indexbuf_set_point_vert(&data->elb, face_idx, face_idx);
1444   }
1445   else {
1446     GPU_indexbuf_set_point_restart(&data->elb, face_idx);
1447   }
1448 }
1449
1450 static void extract_edituv_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr),
1451                                             int UNUSED(l),
1452                                             BMLoop *loop,
1453                                             void *data)
1454 {
1455   edituv_facedot_add(data,
1456                      BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN),
1457                      BM_elem_flag_test(loop->f, BM_ELEM_SELECT),
1458                      BM_elem_index_get(loop->f));
1459 }
1460
1461 static void extract_edituv_fdots_loop_mesh(const MeshRenderData *mr,
1462                                            int UNUSED(l),
1463                                            const MLoop *mloop,
1464                                            int p,
1465                                            const MPoly *mpoly,
1466                                            void *data)
1467 {
1468   const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex &&
1469                           mr->p_origindex[p] != ORIGINDEX_NONE);
1470   const bool subd_fdot = (!mr->use_subsurf_fdots ||
1471                           (mr->mvert[mloop->v].flag & ME_VERT_FACEDOT) != 0);
1472   edituv_facedot_add(data,
1473                      ((mpoly->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot,
1474                      (mpoly->flag & ME_FACE_SEL) != 0,
1475                      p);
1476 }
1477
1478 static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *_data)
1479 {
1480   MeshExtract_EditUvElem_Data *data = (MeshExtract_EditUvElem_Data *)_data;
1481   GPU_indexbuf_build_in_place(&data->elb, ibo);
1482   MEM_freeN(data);
1483 }
1484
1485 static const MeshExtract extract_edituv_fdots = {
1486     .init = extract_edituv_fdots_init,
1487     .iter_loop_bm = extract_edituv_fdots_loop_bmesh,
1488     .iter_loop_mesh = extract_edituv_fdots_loop_mesh,
1489     .finish = extract_edituv_fdots_finish,
1490     .data_flag = 0,
1491     .use_threading = false,
1492 };
1493
1494 /** \} */
1495
1496 /* ---------------------------------------------------------------------- */
1497 /** \name Extract Position and Vertex Normal
1498  * \{ */
1499
1500 typedef struct PosNorLoop {
1501   float pos[3];
1502   GPUPackedNormal nor;
1503 } PosNorLoop;
1504
1505 typedef struct MeshExtract_PosNor_Data {
1506   PosNorLoop *vbo_data;
1507   GPUPackedNormal packed_nor[];
1508 } MeshExtract_PosNor_Data;
1509
1510 static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf)
1511 {
1512   static GPUVertFormat format = {0};
1513   if (format.attr_len == 0) {
1514     /* WARNING Adjust #PosNorLoop struct accordingly. */
1515     GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1516     GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
1517     GPU_vertformat_alias_add(&format, "vnor");
1518   }
1519   GPUVertBuf *vbo = buf;
1520   GPU_vertbuf_init_with_format(vbo, &format);
1521   GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
1522
1523   /* Pack normals per vert, reduce amount of computation. */
1524   size_t packed_nor_len = sizeof(GPUPackedNormal) * mr->vert_len;
1525   MeshExtract_PosNor_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__);
1526   data->vbo_data = (PosNorLoop *)vbo->data;
1527
1528   /* Quicker than doing it for each loop. */
1529   if (mr->extract_type == MR_EXTRACT_BMESH) {
1530     BMIter iter;
1531     BMVert *eve;
1532     int v;
1533     BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) {
1534       data->packed_nor[v] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve));
1535     }
1536   }
1537   else {
1538     const MVert *mvert = mr->mvert;
1539     for (int v = 0; v < mr->vert_len; v++, mvert++) {
1540       data->packed_nor[v] = GPU_normal_convert_i10_s3(mvert->no);
1541     }
1542   }
1543   return data;
1544 }
1545
1546 static void extract_pos_nor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
1547 {
1548   MeshExtract_PosNor_Data *data = _data;
1549   PosNorLoop *vert = data->vbo_data + l;
1550   copy_v3_v3(vert->pos, bm_vert_co_get(mr, loop->v));
1551   vert->nor = data->packed_nor[BM_elem_index_get(loop->v)];
1552   BMFace *efa = loop->f;
1553   vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
1554 }
1555
1556 static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
1557                                       int l,
1558                                       const MLoop *mloop,
1559                                       int UNUSED(p),
1560                                       const MPoly *mpoly,
1561                                       void *_data)
1562 {
1563   MeshExtract_PosNor_Data *data = _data;
1564   PosNorLoop *vert = data->vbo_data + l;
1565   const MVert *mvert = &mr->mvert[mloop->v];
1566   copy_v3_v3(vert->pos, mvert->co);
1567   vert->nor = data->packed_nor[mloop->v];
1568   /* Flag for paint mode overlay. */
1569   if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE ||
1570       ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) &&
1571        (mr->v_origindex[mloop->v] == ORIGINDEX_NONE))) {
1572     vert->nor.w = -1;
1573   }
1574   else if (mvert->flag & SELECT) {
1575     vert->nor.w = 1;
1576   }
1577   else {
1578     vert->nor.w = 0;
1579   }
1580 }
1581
1582 static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *_data)
1583 {
1584   int l = mr->loop_len + e * 2;
1585   MeshExtract_PosNor_Data *data = _data;
1586   PosNorLoop *vert = data->vbo_data + l;
1587   copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1));
1588   copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2));
1589   vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)];
1590   vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)];
1591 }
1592
1593 static void extract_pos_nor_ledge_mesh(const MeshRenderData *mr,
1594                                        int e,
1595                                        const MEdge *medge,
1596                                        void *_data)
1597 {
1598   int l = mr->loop_len + e * 2;
1599   MeshExtract_PosNor_Data *data = _data;
1600   PosNorLoop *vert = data->vbo_data + l;
1601   copy_v3_v3(vert[0].pos, mr->mvert[medge->v1].co);
1602   copy_v3_v3(vert[1].pos, mr->mvert[medge->v2].co);
1603   vert[0].nor = data->packed_nor[medge->v1];
1604   vert[1].nor = data->packed_nor[medge->v2];
1605 }
1606
1607 static void extract_pos_nor_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *_data)
1608 {
1609   int l = mr->loop_len + mr->edge_loose_len * 2 + v;
1610   MeshExtract_PosNor_Data *data = _data;
1611   PosNorLoop *vert = data->vbo_data + l;
1612   copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve));
1613   vert->nor = data->packed_nor[BM_elem_index_get(eve)];
1614 }
1615
1616 static void extract_pos_nor_lvert_mesh(const MeshRenderData *mr,
1617                                        int v,
1618                                        const MVert *mvert,
1619                                        void *_data)
1620 {
1621   int l = mr->loop_len + mr->edge_loose_len * 2 + v;
1622   int v_idx = mr->lverts[v];
1623   MeshExtract_PosNor_Data *data = _data;
1624   PosNorLoop *vert = data->vbo_data + l;
1625   copy_v3_v3(vert->pos, mvert->co);
1626   vert->nor = data->packed_nor[v_idx];
1627 }
1628
1629 static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(vbo), void *data)
1630 {
1631   MEM_freeN(data);
1632 }
1633
1634 static const MeshExtract extract_pos_nor = {
1635     .init = extract_pos_nor_init,
1636     .iter_loop_bm = extract_pos_nor_loop_bmesh,
1637     .iter_loop_mesh = extract_pos_nor_loop_mesh,
1638     .iter_ledge_bm = extract_pos_nor_ledge_bmesh,
1639     .iter_ledge_mesh = extract_pos_nor_ledge_mesh,
1640     .iter_lvert_bm = extract_pos_nor_lvert_bmesh,
1641     .iter_lvert_mesh = extract_pos_nor_lvert_mesh,
1642     .finish = extract_pos_nor_finish,
1643     .data_flag = 0,
1644     .use_threading = true,
1645 };
1646 /** \} */
1647
1648 /* ---------------------------------------------------------------------- */
1649 /** \name Extract HQ Loop Normal
1650  * \{ */
1651
1652 typedef struct gpuHQNor {
1653   short x, y, z, w;
1654 } gpuHQNor;
1655
1656 static void *extract_lnor_hq_init(const MeshRenderData *mr, void *buf)
1657 {
1658   static GPUVertFormat format = {0};
1659   if (format.attr_len == 0) {
1660     GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
1661     GPU_vertformat_alias_add(&format, "lnor");
1662   }
1663   GPUVertBuf *vbo = buf;
1664   GPU_vertbuf_init_with_format(vbo, &format);
1665   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
1666
1667   return vbo->data;
1668 }
1669
1670 static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data)
1671 {
1672   if (mr->loop_normals) {
1673     normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]);
1674   }
1675   else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
1676     normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_vert_no_get(mr, loop->v));
1677   }
1678   else {
1679     normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_face_no_get(mr, loop->f));
1680   }
1681 }
1682
1683 static void extract_lnor_hq_loop_mesh(
1684     const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
1685 {
1686   gpuHQNor *lnor_data = &((gpuHQNor *)data)[l];
1687   if (mr->loop_normals) {
1688     normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[l]);
1689   }
1690   else if (mpoly->flag & ME_SMOOTH) {
1691     copy_v3_v3_short(&lnor_data->x, mr->mvert[mloop->v].no);
1692   }
1693   else {
1694     normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[p]);
1695   }
1696
1697   /* Flag for paint mode overlay.
1698    * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
1699    * In paint mode it will use the un-mapped data to draw the wire-frame. */
1700   if (mpoly->flag & ME_HIDE ||
1701       (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
1702        mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
1703     lnor_data->w = -1;
1704   }
1705   else if (mpoly->flag & ME_FACE_SEL) {
1706     lnor_data->w = 1;
1707   }
1708   else {
1709     lnor_data->w = 0;
1710   }
1711 }
1712
1713 static const MeshExtract extract_lnor_hq = {
1714     .init = extract_lnor_hq_init,
1715     .iter_loop_bm = extract_lnor_hq_loop_bmesh,
1716     .iter_loop_mesh = extract_lnor_hq_loop_mesh,
1717     .data_flag = MR_DATA_LOOP_NOR,
1718     .use_threading = true,
1719 };
1720
1721 /** \} */
1722 /* ---------------------------------------------------------------------- */
1723 /** \name Extract Loop Normal
1724  * \{ */
1725
1726 static void *extract_lnor_init(const MeshRenderData *mr, void *buf)
1727 {
1728   static GPUVertFormat format = {0};
1729   if (format.attr_len == 0) {
1730     GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
1731     GPU_vertformat_alias_add(&format, "lnor");
1732   }
1733   GPUVertBuf *vbo = buf;
1734   GPU_vertbuf_init_with_format(vbo, &format);
1735   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
1736
1737   return vbo->data;
1738 }
1739
1740 static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data)
1741 {
1742   if (mr->loop_normals) {
1743     ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
1744   }
1745   else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) {
1746     ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v));
1747   }
1748   else {
1749     ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, loop->f));
1750   }
1751   BMFace *efa = loop->f;
1752   ((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
1753 }
1754
1755 static void extract_lnor_loop_mesh(
1756     const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data)
1757 {
1758   GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[l];
1759   if (mr->loop_normals) {
1760     *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[l]);
1761   }
1762   else if (mpoly->flag & ME_SMOOTH) {
1763     *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no);
1764   }
1765   else {
1766     *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[p]);
1767   }
1768
1769   /* Flag for paint mode overlay.
1770    * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals.
1771    * In paint mode it will use the un-mapped data to draw the wire-frame. */
1772   if (mpoly->flag & ME_HIDE ||
1773       (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
1774        mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
1775     lnor_data->w = -1;
1776   }
1777   else if (mpoly->flag & ME_FACE_SEL) {
1778     lnor_data->w = 1;
1779   }
1780   else {
1781     lnor_data->w = 0;
1782   }
1783 }
1784
1785 static const MeshExtract extract_lnor = {
1786     .init = extract_lnor_init,
1787     .iter_loop_bm = extract_lnor_loop_bmesh,
1788     .iter_loop_mesh = extract_lnor_loop_mesh,
1789     .data_flag = MR_DATA_LOOP_NOR,
1790     .use_threading = true,
1791 };
1792
1793 /** \} */
1794
1795 /* ---------------------------------------------------------------------- */
1796 /** \name Extract UV  layers
1797  * \{ */
1798
1799 static void *extract_uv_init(const MeshRenderData *mr, void *buf)
1800 {
1801   GPUVertFormat format = {0};
1802   GPU_vertformat_deinterleave(&format);
1803
1804   CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
1805   uint32_t uv_layers = mr->cache->cd_used.uv;
1806
1807   /* HACK to fix T68857 */
1808   if (mr->extract_type == MR_EXTRACT_BMESH && mr->cache->cd_used.edit_uv == 1) {
1809     int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
1810     if (layer != -1) {
1811       uv_layers |= (1 << layer);
1812     }
1813   }
1814
1815   for (int i = 0; i < MAX_MTFACE; i++) {
1816     if (uv_layers & (1 << i)) {
1817       char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
1818       const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
1819
1820       GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
1821       /* UV layer name. */
1822       BLI_snprintf(attr_name, sizeof(attr_name), "u%s", attr_safe_name);
1823       GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1824       /* Auto layer name. */
1825       BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
1826       GPU_vertformat_alias_add(&format, attr_name);
1827       /* Active render layer name. */
1828       if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
1829         GPU_vertformat_alias_add(&format, "u");
1830       }
1831       /* Active display layer name. */
1832       if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
1833         GPU_vertformat_alias_add(&format, "au");
1834         /* Alias to `pos` for edit uvs. */
1835         GPU_vertformat_alias_add(&format, "pos");
1836       }
1837       /* Stencil mask uv layer name. */
1838       if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) {
1839         GPU_vertformat_alias_add(&format, "mu");
1840       }
1841     }
1842   }
1843
1844   int v_len = mr->loop_len;
1845   if (format.attr_len == 0) {
1846     GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
1847     /* VBO will not be used, only allocate minimum of memory. */
1848     v_len = 1;
1849   }
1850
1851   GPUVertBuf *vbo = buf;
1852   GPU_vertbuf_init_with_format(vbo, &format);
1853   GPU_vertbuf_data_alloc(vbo, v_len);
1854
1855   float(*uv_data)[2] = (float(*)[2])vbo->data;
1856   for (int i = 0; i < MAX_MTFACE; i++) {
1857     if (uv_layers & (1 << i)) {
1858       if (mr->extract_type == MR_EXTRACT_BMESH) {
1859         int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i);
1860         BMIter f_iter;
1861         BMFace *efa;
1862         BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
1863           BMLoop *l_iter, *l_first;
1864           l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
1865           do {
1866             MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
1867             memcpy(uv_data, luv->uv, sizeof(*uv_data));
1868             uv_data++;
1869           } while ((l_iter = l_iter->next) != l_first);
1870         }
1871       }
1872       else {
1873         MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i);
1874         for (int l = 0; l < mr->loop_len; l++, uv_data++, layer_data++) {
1875           memcpy(uv_data, layer_data->uv, sizeof(*uv_data));
1876         }
1877       }
1878     }
1879   }
1880
1881   return NULL;
1882 }
1883
1884 static const MeshExtract extract_uv = {
1885     .init = extract_uv_init,
1886     .data_flag = 0,
1887     .use_threading = false,
1888 };
1889
1890 /** \} */
1891
1892 /* ---------------------------------------------------------------------- */
1893 /** \name Extract Tangent layers
1894  * \{ */
1895
1896 static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool do_hq)
1897 {
1898   GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10;
1899   GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT;
1900
1901   GPUVertFormat format = {0};
1902   GPU_vertformat_deinterleave(&format);
1903
1904   CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
1905   CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
1906   uint32_t tan_layers = mr->cache->cd_used.tan;
1907   float(*orco)[3] = CustomData_get_layer(cd_vdata, CD_ORCO);
1908   bool orco_allocated = false;
1909   const bool use_orco_tan = mr->cache->cd_used.tan_orco != 0;
1910
1911   int tan_len = 0;
1912   char tangent_names[MAX_MTFACE][MAX_CUSTOMDATA_LAYER_NAME];
1913
1914   for (int i = 0; i < MAX_MTFACE; i++) {
1915     if (tan_layers & (1 << i)) {
1916       char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
1917       const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
1918       GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
1919       /* Tangent layer name. */
1920       BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name);
1921       GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode);
1922       /* Active render layer name. */
1923       if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
1924         GPU_vertformat_alias_add(&format, "t");
1925       }
1926       /* Active display layer name. */
1927       if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
1928         GPU_vertformat_alias_add(&format, "at");
1929       }
1930
1931       BLI_strncpy(tangent_names[tan_len++], layer_name, MAX_CUSTOMDATA_LAYER_NAME);
1932     }
1933   }
1934   if (use_orco_tan && orco == NULL) {
1935     /* If `orco` is not available compute it ourselves */
1936     orco_allocated = true;
1937     orco = MEM_mallocN(sizeof(*orco) * mr->vert_len, __func__);
1938
1939     if (mr->extract_type == MR_EXTRACT_BMESH) {
1940       BMesh *bm = mr->bm;
1941       for (int v = 0; v < mr->vert_len; v++) {
1942         const BMVert *eve = BM_vert_at_index(bm, v);
1943         /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords.
1944          * not the distorted ones. */
1945         copy_v3_v3(orco[v], eve->co);
1946       }
1947     }
1948     else {
1949       const MVert *mvert = mr->mvert;
1950       for (int v = 0; v < mr->vert_len; v++, mvert++) {
1951         copy_v3_v3(orco[v], mvert->co);
1952       }
1953     }
1954     BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0);
1955   }
1956
1957   /* Start Fresh */
1958   CustomData loop_data;
1959   CustomData_reset(&loop_data);
1960   CustomData *ldata = cd_ldata;
1961   if (tan_len != 0 || use_orco_tan) {
1962     short tangent_mask = 0;
1963     bool calc_active_tangent = false;
1964     if (mr->extract_type == MR_EXTRACT_BMESH) {
1965       BKE_editmesh_loop_tangent_calc(mr->edit_bmesh,
1966                                      calc_active_tangent,
1967                                      tangent_names,
1968                                      tan_len,
1969                                      mr->poly_normals,
1970                                      mr->loop_normals,
1971                                      orco,
1972                                      cd_ldata,
1973                                      mr->loop_len,
1974                                      &tangent_mask);
1975     }
1976     else {
1977       BKE_mesh_calc_loop_tangent_ex(mr->mvert,
1978                                     mr->mpoly,
1979                                     mr->poly_len,
1980                                     mr->mloop,
1981                                     mr->mlooptri,
1982                                     mr->tri_len,
1983                                     cd_ldata,
1984                                     calc_active_tangent,
1985                                     tangent_names,
1986                                     tan_len,
1987                                     mr->poly_normals,
1988                                     mr->loop_normals,
1989                                     orco,
1990                                     &loop_data,
1991                                     mr->loop_len,
1992                                     &tangent_mask);
1993       ldata = &loop_data;
1994     }
1995   }
1996
1997   if (use_orco_tan) {
1998     char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
1999     const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_TANGENT, 0);
2000     GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
2001     BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name);
2002     GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode);
2003     GPU_vertformat_alias_add(&format, "t");
2004     GPU_vertformat_alias_add(&format, "at");
2005   }
2006
2007   if (orco_allocated) {
2008     MEM_SAFE_FREE(orco);
2009   }
2010
2011   int v_len = mr->loop_len;
2012   if (format.attr_len == 0) {
2013     GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2014     /* VBO will not be used, only allocate minimum of memory. */
2015     v_len = 1;
2016   }
2017
2018   GPU_vertbuf_init_with_format(vbo, &format);
2019   GPU_vertbuf_data_alloc(vbo, v_len);
2020
2021   if (do_hq) {
2022     short(*tan_data)[4] = (short(*)[4])vbo->data;
2023     for (int i = 0; i < tan_len; i++) {
2024       const char *name = tangent_names[i];
2025       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
2026       for (int l = 0; l < mr->loop_len; l++) {
2027         normal_float_to_short_v3(*tan_data, layer_data[l]);
2028         (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
2029         tan_data++;
2030       }
2031     }
2032     if (use_orco_tan) {
2033       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
2034       for (int l = 0; l < mr->loop_len; l++) {
2035         normal_float_to_short_v3(*tan_data, layer_data[l]);
2036         (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN;
2037         tan_data++;
2038       }
2039     }
2040   }
2041   else {
2042     GPUPackedNormal *tan_data = (GPUPackedNormal *)vbo->data;
2043     for (int i = 0; i < tan_len; i++) {
2044       const char *name = tangent_names[i];
2045       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name);
2046       for (int l = 0; l < mr->loop_len; l++) {
2047         *tan_data = GPU_normal_convert_i10_v3(layer_data[l]);
2048         tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2;
2049         tan_data++;
2050       }
2051     }
2052     if (use_orco_tan) {
2053       float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0);
2054       for (int l = 0; l < mr->loop_len; l++) {
2055         *tan_data = GPU_normal_convert_i10_v3(layer_data[l]);
2056         tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2;
2057         tan_data++;
2058       }
2059     }
2060   }
2061
2062   CustomData_free_layers(ldata, CD_TANGENT, mr->loop_len);
2063   CustomData_free(&loop_data, mr->loop_len);
2064 }
2065
2066 static void *extract_tan_init(const MeshRenderData *mr, void *buf)
2067 {
2068   extract_tan_ex(mr, buf, false);
2069   return NULL;
2070 }
2071
2072 static const MeshExtract extract_tan = {
2073     .init = extract_tan_init,
2074     .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
2075     .use_threading = false,
2076 };
2077
2078 /** \} */
2079
2080 /* ---------------------------------------------------------------------- */
2081 /** \name Extract HQ Tangent layers
2082  * \{ */
2083
2084 static void *extract_tan_hq_init(const MeshRenderData *mr, void *buf)
2085 {
2086   extract_tan_ex(mr, buf, true);
2087   return NULL;
2088 }
2089
2090 static const MeshExtract extract_tan_hq = {
2091     .init = extract_tan_hq_init,
2092     .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
2093     .use_threading = false,
2094 };
2095
2096 /** \} */
2097
2098 /* ---------------------------------------------------------------------- */
2099 /** \name Extract VCol
2100  * \{ */
2101
2102 static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
2103 {
2104   GPUVertFormat format = {0};
2105   GPU_vertformat_deinterleave(&format);
2106
2107   CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
2108   CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
2109   uint32_t vcol_layers = mr->cache->cd_used.vcol;
2110   uint32_t svcol_layers = mr->cache->cd_used.sculpt_vcol;
2111
2112   for (int i = 0; i < MAX_MCOL; i++) {
2113     if (vcol_layers & (1 << i)) {
2114       char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
2115       const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
2116       GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
2117
2118       BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
2119       GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
2120
2121       if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) {
2122         GPU_vertformat_alias_add(&format, "c");
2123       }
2124       if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) {
2125         GPU_vertformat_alias_add(&format, "ac");
2126       }
2127
2128       /* Gather number of auto layers. */
2129       /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */
2130       if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 &&
2131           CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) {
2132         BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
2133         GPU_vertformat_alias_add(&format, attr_name);
2134       }
2135     }
2136   }
2137
2138   /* Sculpt Vertex Colors */
2139   for (int i = 0; i < 8; i++) {
2140     if (svcol_layers & (1 << i)) {
2141       char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
2142       const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i);
2143       GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
2144
2145       BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
2146       GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
2147
2148       if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) {
2149         GPU_vertformat_alias_add(&format, "c");
2150       }
2151       if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) {
2152         GPU_vertformat_alias_add(&format, "ac");
2153       }
2154       /* Gather number of auto layers. */
2155       /* We only do `vcols` that are not overridden by `uvs`. */
2156       if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) {
2157         BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
2158         GPU_vertformat_alias_add(&format, attr_name);
2159       }
2160     }
2161   }
2162
2163   GPUVertBuf *vbo = buf;
2164   GPU_vertbuf_init_with_format(vbo, &format);
2165   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
2166
2167   typedef struct gpuMeshVcol {
2168     ushort r, g, b, a;
2169   } gpuMeshVcol;
2170
2171   gpuMeshVcol *vcol_data = (gpuMeshVcol *)vbo->data;
2172   MLoop *loops = CustomData_get_layer(cd_ldata, CD_MLOOP);
2173
2174   for (int i = 0; i < MAX_MCOL; i++) {
2175     if (vcol_layers & (1 << i)) {
2176       if (mr->extract_type == MR_EXTRACT_BMESH) {
2177         int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
2178         BMIter f_iter;
2179         BMFace *efa;
2180         BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
2181           BMLoop *l_iter, *l_first;
2182           l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
2183           do {
2184             const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
2185             vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
2186             vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
2187             vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
2188             vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
2189             vcol_data++;
2190           } while ((l_iter = l_iter->next) != l_first);
2191         }
2192       }
2193       else {
2194         const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
2195         for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) {
2196           vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
2197           vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
2198           vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
2199           vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
2200         }
2201       }
2202     }
2203
2204     if (svcol_layers & (1 << i)) {
2205       if (mr->extract_type == MR_EXTRACT_BMESH) {
2206         int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i);
2207         BMIter f_iter;
2208         BMFace *efa;
2209         BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
2210           BMLoop *l_iter, *l_first;
2211           l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
2212           do {
2213             const MPropCol *prop_col = BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs);
2214             vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]);
2215             vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]);
2216             vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]);
2217             vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]);
2218             vcol_data++;
2219           } while ((l_iter = l_iter->next) != l_first);
2220         }
2221       }
2222       else {
2223         MPropCol *vcol = CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i);
2224         for (int l = 0; l < mr->loop_len; l++, vcol_data++) {
2225           vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[l].v].color[0]);
2226           vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[l].v].color[1]);
2227           vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[l].v].color[2]);
2228           vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[l].v].color[3]);
2229         }
2230       }
2231
2232       vcol_data += mr->loop_len;
2233     }
2234   }
2235   return NULL;
2236 }
2237
2238 static const MeshExtract extract_vcol = {
2239     .init = extract_vcol_init,
2240     .data_flag = 0,
2241     .use_threading = false,
2242 };
2243
2244 /** \} */
2245
2246 /* ---------------------------------------------------------------------- */
2247 /** \name Extract Orco
2248  * \{ */
2249
2250 typedef struct MeshExtract_Orco_Data {
2251   float (*vbo_data)[4];
2252   float (*orco)[3];
2253 } MeshExtract_Orco_Data;
2254
2255 static void *extract_orco_init(const MeshRenderData *mr, void *buf)
2256 {
2257   static GPUVertFormat format = {0};
2258   if (format.attr_len == 0) {
2259     /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex
2260      * attributes. This is a substantial waste of video-ram and should be done another way.
2261      * Unfortunately, at the time of writing, I did not found any other "non disruptive"
2262      * alternative. */
2263     GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
2264   }
2265
2266   GPUVertBuf *vbo = buf;
2267   GPU_vertbuf_init_with_format(vbo, &format);
2268   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
2269
2270   CustomData *cd_vdata = &mr->me->vdata;
2271
2272   MeshExtract_Orco_Data *data = MEM_mallocN(sizeof(*data), __func__);
2273   data->vbo_data = (float(*)[4])vbo->data;
2274   data->orco = CustomData_get_layer(cd_vdata, CD_ORCO);
2275   /* Make sure `orco` layer was requested only if needed! */
2276   BLI_assert(data->orco);
2277   return data;
2278 }
2279
2280 static void extract_orco_loop_bmesh(const MeshRenderData *UNUSED(mr),
2281                                     int l,
2282                                     BMLoop *loop,
2283                                     void *data)
2284 {
2285   MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
2286   float *loop_orco = orco_data->vbo_data[l];
2287   copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]);
2288   loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
2289 }
2290
2291 static void extract_orco_loop_mesh(const MeshRenderData *UNUSED(mr),
2292                                    int l,
2293                                    const MLoop *mloop,
2294                                    int UNUSED(p),
2295                                    const MPoly *UNUSED(mpoly),
2296                                    void *data)
2297 {
2298   MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data;
2299   float *loop_orco = orco_data->vbo_data[l];
2300   copy_v3_v3(loop_orco, orco_data->orco[mloop->v]);
2301   loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
2302 }
2303
2304 static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data)
2305 {
2306   MEM_freeN(data);
2307 }
2308
2309 static const MeshExtract extract_orco = {
2310     .init = extract_orco_init,
2311     .iter_loop_bm = extract_orco_loop_bmesh,
2312     .iter_loop_mesh = extract_orco_loop_mesh,
2313     .finish = extract_orco_finish,
2314     .data_flag = 0,
2315     .use_threading = true,
2316 };
2317
2318 /** \} */
2319
2320 /* ---------------------------------------------------------------------- */
2321 /** \name Extract Edge Factor
2322  * Defines how much an edge is visible.
2323  * \{ */
2324
2325 typedef struct MeshExtract_EdgeFac_Data {
2326   uchar *vbo_data;
2327   bool use_edge_render;
2328   /* Number of loop per edge. */
2329   uchar edge_loop_count[0];
2330 } MeshExtract_EdgeFac_Data;
2331
2332 static float loop_edge_factor_get(const float f_no[3],
2333                                   const float v_co[3],
2334                                   const float v_no[3],
2335                                   const float v_next_co[3])
2336 {
2337   float enor[3], evec[3];
2338   sub_v3_v3v3(evec, v_next_co, v_co);
2339   cross_v3_v3v3(enor, v_no, evec);
2340   normalize_v3(enor);
2341   float d = fabsf(dot_v3v3(enor, f_no));
2342   /* Re-scale to the slider range. */
2343   d *= (1.0f / 0.065f);
2344   CLAMP(d, 0.0f, 1.0f);
2345   return d;
2346 }
2347
2348 static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf)
2349 {
2350   static GPUVertFormat format = {0};
2351   if (format.attr_len == 0) {
2352     GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
2353   }
2354   GPUVertBuf *vbo = buf;
2355   GPU_vertbuf_init_with_format(vbo, &format);
2356   GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
2357
2358   MeshExtract_EdgeFac_Data *data;
2359
2360   if (mr->extract_type == MR_EXTRACT_MESH) {
2361     size_t edge_loop_count_size = sizeof(uint32_t) * mr->edge_len;
2362     data = MEM_callocN(sizeof(*data) + edge_loop_count_size, __func__);
2363
2364     /* HACK(fclem) Detecting the need for edge render.
2365      * We could have a flag in the mesh instead or check the modifier stack. */
2366     const MEdge *medge = mr->medge;
2367     for (int e = 0; e < mr->edge_len; e++, medge++) {
2368       if ((medge->flag & ME_EDGERENDER) == 0) {
2369         data->use_edge_render = true;
2370         break;
2371       }
2372     }
2373   }
2374   else {
2375     data = MEM_callocN(sizeof(*data), __func__);
2376     /* HACK to bypass non-manifold check in mesh_edge_fac_finish(). */
2377     data->use_edge_render = true;
2378   }
2379
2380   data->vbo_data = vbo->data;
2381   return data;
2382 }
2383
2384 static void extract_edge_fac_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data)
2385 {
2386   MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
2387   if (BM_edge_is_manifold(loop->e)) {
2388     float ratio = loop_edge_factor_get(bm_face_no_get(mr, loop->f),
2389                                        bm_vert_co_get(mr, loop->v),
2390                                        bm_vert_no_get(mr, loop->v),
2391                                        bm_vert_co_get(mr, loop->next->v));
2392     data->vbo_data[l] = ratio * 253 + 1;
2393   }
2394   else {
2395     data->vbo_data[l] = 255;
2396   }
2397 }
2398
2399 static void extract_edge_fac_loop_mesh(
2400     const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
2401 {
2402   MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
2403   if (data->use_edge_render) {
2404     const MEdge *medge = &mr->medge[mloop->e];
2405     data->vbo_data[l] = (medge->flag & ME_EDGERENDER) ? 255 : 0;
2406   }
2407   else {
2408     /* Count loop per edge to detect non-manifold. */
2409     if (data->edge_loop_count[mloop->e] < 3) {
2410       data->edge_loop_count[mloop->e]++;
2411     }
2412     if (data->edge_loop_count[mloop->e] == 2) {
2413       /* Manifold */
2414       int loopend = mpoly->totloop + mpoly->loopstart - 1;
2415       int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1);
2416       const MLoop *mloop_next = &mr->mloop[other_loop];
2417       const MVert *v1 = &mr->mvert[mloop->v];
2418       const MVert *v2 = &mr->mvert[mloop_next->v];
2419       float vnor_f[3];
2420       normal_short_to_float_v3(vnor_f, v1->no);
2421       float ratio = loop_edge_factor_get(mr->poly_normals[p], v1->co, vnor_f, v2->co);
2422       data->vbo_data[l] = ratio * 253 + 1;
2423     }
2424     else {
2425       /* Non-manifold */
2426       data->vbo_data[l] = 255;
2427     }
2428   }
2429 }
2430
2431 static void extract_edge_fac_ledge_bmesh(const MeshRenderData *mr,
2432                                          int e,
2433                                          BMEdge *UNUSED(eed),
2434                                          void *_data)
2435 {
2436   MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
2437   data->vbo_data[mr->loop_len + e * 2 + 0] = 255;
2438   data->vbo_data[mr->loop_len + e * 2 + 1] = 255;
2439 }
2440
2441 static void extract_edge_fac_ledge_mesh(const MeshRenderData *mr,
2442                                         int e,
2443                                         const MEdge *UNUSED(edge),
2444                                         void *_data)
2445 {
2446   MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
2447   data->vbo_data[mr->loop_len + e * 2 + 0] = 255;
2448   data->vbo_data[mr->loop_len + e * 2 + 1] = 255;
2449 }
2450
2451 static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_data)
2452 {
2453   MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data;
2454
2455   if (GPU_crappy_amd_driver()) {
2456     GPUVertBuf *vbo = (GPUVertBuf *)buf;
2457     /* Some AMD drivers strangely crash with VBO's with a one byte format.
2458      * To workaround we reinitialize the VBO with another format and convert
2459      * all bytes to floats. */
2460     static GPUVertFormat format = {0};
2461     if (format.attr_len == 0) {
2462       GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2463     }
2464     /* We keep the data reference in data->vbo_data. */
2465     vbo->data = NULL;
2466     GPU_vertbuf_clear(vbo);
2467
2468     int buf_len = mr->loop_len + mr->loop_loose_len;
2469     GPU_vertbuf_init_with_format(vbo, &format);
2470     GPU_vertbuf_data_alloc(vbo, buf_len);
2471
2472     float *fdata = (float *)vbo->data;
2473     for (int l = 0; l < buf_len; l++, fdata++) {
2474       *fdata = data->vbo_data[l] / 255.0f;
2475     }
2476     /* Free old byte data. */
2477     MEM_freeN(data->vbo_data);
2478   }
2479   MEM_freeN(data);
2480 }
2481
2482 static const MeshExtract extract_edge_fac = {
2483     .init = extract_edge_fac_init,
2484     .iter_loop_bm = extract_edge_fac_loop_bmesh,
2485     .iter_loop_mesh = extract_edge_fac_loop_mesh,
2486     .iter_ledge_bm = extract_edge_fac_ledge_bmesh,
2487     .iter_ledge_mesh = extract_edge_fac_ledge_mesh,
2488     .finish = extract_edge_fac_finish,
2489     .data_flag = MR_DATA_POLY_NOR,
2490     .use_threading = false,
2491 };
2492
2493 /** \} */
2494 /* ---------------------------------------------------------------------- */
2495 /** \name Extract Vertex Weight
2496  * \{ */
2497
2498 typedef struct MeshExtract_Weight_Data {
2499   float *vbo_data;
2500   const DRW_MeshWeightState *wstate;
2501   const MDeformVert *dvert; /* For #Mesh. */
2502   int cd_ofs;               /* For #BMesh. */
2503 } MeshExtract_Weight_Data;
2504
2505 static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate)
2506 {
2507   /* Error state. */
2508   if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) {
2509     return -2.0f;
2510   }
2511   else if (dvert == NULL) {
2512     return (wstate->alert_mode != OB_DRAW_GROUPUSER_NONE) ? -1.0f : 0.0f;
2513   }
2514
2515   float input = 0.0f;
2516   if (wstate->flags & DRW_MESH_WEIGHT_STATE_MULTIPAINT) {
2517     /* Multi-Paint feature */
2518     bool is_normalized = (wstate->flags & (DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE |
2519                                            DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE));
2520     input = BKE_defvert_multipaint_collective_weight(dvert,
2521                                                      wstate->defgroup_len,
2522                                                      wstate->defgroup_sel,
2523                                                      wstate->defgroup_sel_count,
2524                                                      is_normalized);
2525     /* make it black if the selected groups have no weight on a vertex */
2526     if (input == 0.0f) {
2527       return -1.0f;
2528     }
2529   }
2530   else {
2531     /* default, non tricky behavior */
2532     input = BKE_defvert_find_weight(dvert, wstate->defgroup_active);
2533
2534     if (input == 0.0f) {
2535       switch (wstate->alert_mode) {
2536         case OB_DRAW_GROUPUSER_ACTIVE:
2537           return -1.0f;
2538           break;
2539         case OB_DRAW_GROUPUSER_ALL:
2540           if (BKE_defvert_is_weight_zero(dvert, wstate->defgroup_len)) {
2541             return -1.0f;
2542           }
2543           break;
2544       }
2545     }
2546   }
2547
2548   /* Lock-Relative: display the fraction of current weight vs total unlocked weight. */
2549   if (wstate->flags & DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE) {
2550     input = BKE_defvert_lock_relative_weight(
2551         input, dvert, wstate->defgroup_len, wstate->defgroup_locked, wstate->defgroup_unlocked);
2552   }
2553
2554   CLAMP(input, 0.0f, 1.0f);
2555   return input;
2556 }
2557
2558 static void *extract_weights_init(const MeshRenderData *mr, void *buf)
2559 {
2560   static GPUVertFormat format = {0};
2561   if (format.attr_len == 0) {
2562     GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2563   }
2564   GPUVertBuf *vbo = buf;
2565   GPU_vertbuf_init_with_format(vbo, &format);
2566   GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
2567
2568   MeshExtract_Weight_Data *data = MEM_callocN(sizeof(*data), __func__);
2569   data->vbo_data = (float *)vbo->data;
2570   data->wstate = &mr->cache->weight_state;
2571
2572   if (data->wstate->defgroup_active == -1) {
2573     /* Nothing to show. */
2574     data->dvert = NULL;
2575     data->cd_ofs = -1;
2576   }
2577   else if (mr->extract_type == MR_EXTRACT_BMESH) {
2578     data->dvert = NULL;
2579     data->cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MDEFORMVERT);
2580   }
2581   else {
2582     data->dvert = CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT);
2583     data->cd_ofs = -1;
2584   }
2585   return data;
2586 }
2587
2588 static void extract_weights_loop_bmesh(const MeshRenderData *UNUSED(mr),
2589                                        int l,
2590                                        BMLoop *loop,
2591                                        void *_data)
2592 {
2593   MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data;
2594   const MDeformVert *dvert = (data->cd_ofs != -1) ? BM_ELEM_CD_GET_VOID_P(loop->v, data->cd_ofs) :
2595                                                     NULL;
2596   data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate);
2597 }
2598
2599 static void extract_weights_loop_mesh(const MeshRenderData *UNUSED(mr),
2600                                       int l,
2601                                       const MLoop *mloop,
2602                                       int UNUSED(p),
2603                                       const MPoly *UNUSED(mpoly),
2604                                       void *_data)
2605 {
2606   MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data;
2607   const MDeformVert *dvert = data->dvert ? &data->dvert[mloop->v] : NULL;
2608   data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate);
2609 }
2610
2611 static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data)
2612 {
2613   MEM_freeN(data);
2614 }
2615
2616 static const MeshExtract extract_weights = {
2617     .init = extract_weights_init,
2618     .iter_loop_bm = extract_weights_loop_bmesh,
2619     .iter_loop_mesh = extract_weights_loop_mesh,
2620     .finish = extract_weights_finish,
2621     .data_flag = 0,
2622     .use_threading = true,
2623 };
2624
2625 /** \} */
2626
2627 /* ---------------------------------------------------------------------- */
2628 /** \name Extract Edit Mode Data / Flags
2629  * \{ */
2630
2631 typedef struct EditLoopData {
2632   uchar v_flag;
2633   uchar e_flag;
2634   uchar crease;
2635   uchar bweight;
2636 } EditLoopData;
2637
2638 static void mesh_render_data_face_flag(const MeshRenderData *mr,
2639                                        BMFace *efa,
2640                                        const int cd_ofs,
2641                                        EditLoopData *eattr)
2642 {
2643   if (efa == mr->efa_act) {
2644     eattr->v_flag |= VFLAG_FACE_ACTIVE;
2645   }
2646   if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
2647     eattr->v_flag |= VFLAG_FACE_SELECTED;
2648   }
2649
2650   if (efa == mr->efa_act_uv) {
2651     eattr->v_flag |= VFLAG_FACE_UV_ACTIVE;
2652   }
2653   if ((cd_ofs != -1) && uvedit_face_select_test_ex(mr->toolsettings, (BMFace *)efa, cd_ofs)) {
2654     eattr->v_flag |= VFLAG_FACE_UV_SELECT;
2655   }
2656
2657 #ifdef WITH_FREESTYLE
2658   if (mr->freestyle_face_ofs != -1) {
2659     const FreestyleFace *ffa = BM_ELEM_CD_GET_VOID_P(efa, mr->freestyle_face_ofs);
2660     if (ffa->flag & FREESTYLE_FACE_MARK) {
2661       eattr->v_flag |= VFLAG_FACE_FREESTYLE;
2662     }
2663   }
2664 #endif
2665 }
2666
2667 static void mesh_render_data_edge_flag(const MeshRenderData *mr, BMEdge *eed, EditLoopData *eattr)
2668 {
2669   const ToolSettings *ts = mr->toolsettings;
2670   const bool is_vertex_select_mode = (ts != NULL) && (ts->selectmode & SCE_SELECT_VERTEX) != 0;
2671   const bool is_face_only_select_mode = (ts != NULL) && (ts->selectmode == SCE_SELECT_FACE);
2672
2673   if (eed == mr->eed_act) {
2674     eattr->e_flag |= VFLAG_EDGE_ACTIVE;
2675   }
2676   if (!is_vertex_select_mode && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
2677     eattr->e_flag |= VFLAG_EDGE_SELECTED;
2678   }
2679   if (is_vertex_select_mode && BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) &&
2680       BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)) {
2681     eattr->e_flag |= VFLAG_EDGE_SELECTED;
2682     eattr->e_flag |= VFLAG_VERT_SELECTED;
2683   }
2684   if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
2685     eattr->e_flag |= VFLAG_EDGE_SEAM;
2686   }
2687   if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) {
2688     eattr->e_flag |= VFLAG_EDGE_SHARP;
2689   }
2690
2691   /* Use active edge color for active face edges because
2692    * specular highlights make it hard to see T55456#510873.
2693    *
2694    * This isn't ideal since it can't be used when mixing edge/face modes
2695    * but it's still better then not being able to see the active face. */
2696   if (is_face_only_select_mode) {
2697     if (mr->efa_act != NULL) {
2698       if (BM_edge_in_face(eed, mr->efa_act)) {
2699         eattr->e_flag |= VFLAG_EDGE_ACTIVE;
2700       }
2701     }
2702   }
2703
2704   /* Use a byte for value range */
2705   if (mr->crease_ofs != -1) {
2706     float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->crease_ofs);
2707     if (crease > 0) {
2708       eattr->crease = (uchar)(crease * 255.0f);
2709     }
2710   }
2711   /* Use a byte for value range */
2712   if (mr->bweight_ofs != -1) {
2713     float bweight = BM_ELEM_CD_GET_FLOAT(eed, mr->bweight_ofs);
2714     if (bweight > 0) {
2715       eattr->bweight = (uchar)(bweight * 255.0f);
2716     }
2717   }
2718 #ifdef WITH_FREESTYLE
2719   if (mr->freestyle_edge_ofs != -1) {
2720     const FreestyleEdge *fed = BM_ELEM_CD_GET_VOID_P(eed, mr->freestyle_edge_ofs);
2721     if (fed->flag & FREESTYLE_EDGE_MARK) {
2722       eattr->e_flag |= VFLAG_EDGE_FREESTYLE;
2723     }
2724   }
2725 #endif
2726 }
2727
2728 static void mesh_render_data_loop_flag(const MeshRenderData *mr,
2729                                        BMLoop *loop,
2730                                        const int cd_ofs,
2731                                        EditLoopData *eattr)
2732 {
2733   if (cd_ofs == -1) {
2734     return;
2735   }
2736   MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
2737   if (luv != NULL && (luv->flag & MLOOPUV_PINNED)) {
2738     eattr->v_flag |= VFLAG_VERT_UV_PINNED;
2739   }
2740   if (uvedit_uv_select_test_ex(mr->toolsettings, loop, cd_ofs)) {
2741     eattr->v_flag |= VFLAG_VERT_UV_SELECT;
2742   }
2743 }
2744
2745 static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
2746                                             BMLoop *loop,
2747                                             const int cd_ofs,
2748                                             EditLoopData *eattr)
2749 {
2750   if (cd_ofs == -1) {
2751     return;
2752   }
2753   if (uvedit_edge_select_test_ex(mr->toolsettings, loop, cd_ofs)) {
2754     eattr->v_flag |= VFLAG_EDGE_UV_SELECT;
2755     eattr->v_flag |= VFLAG_VERT_UV_SELECT;
2756   }
2757 }
2758
2759 static void mesh_render_data_vert_flag(const MeshRenderData *mr, BMVert *eve, EditLoopData *eattr)
2760 {
2761   if (eve == mr->eve_act) {
2762     eattr->e_flag |= VFLAG_VERT_ACTIVE;
2763   }
2764   if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
2765     eattr->e_flag |= VFLAG_VERT_SELECTED;
2766   }
2767 }
2768
2769 static void *extract_edit_data_init(const MeshRenderData *mr, void *buf)
2770 {
2771   static GPUVertFormat format = {0};
2772   if (format.attr_len == 0) {
2773     /* WARNING: Adjust #EditLoopData struct accordingly. */
2774     GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
2775     GPU_vertformat_alias_add(&format, "flag");
2776   }
2777   GPUVertBuf *vbo = buf;
2778   GPU_vertbuf_init_with_format(vbo, &format);
2779   GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
2780   return vbo->data;
2781 }
2782
2783 static void extract_edit_data_loop_bmesh(const MeshRenderData *mr,
2784                                          int l,
2785                                          BMLoop *loop,
2786                                          void *_data)
2787 {
2788   EditLoopData *data = (EditLoopData *)_data + l;
2789   memset(data, 0x0, sizeof(*data));
2790   mesh_render_data_face_flag(mr, loop->f, -1, data);
2791   mesh_render_data_edge_flag(mr, loop->e, data);
2792   mesh_render_data_vert_flag(mr, loop->v, data);
2793 }
2794
2795 static void extract_edit_data_loop_mesh(const MeshRenderData *mr,
2796                                         int l,
2797                                         const MLoop *mloop,
2798                                         int p,
2799                                         const MPoly *UNUSED(mpoly),
2800                                         void *_data)
2801 {
2802   EditLoopData *data = (EditLoopData *)_data + l;
2803   memset(data, 0x0, sizeof(*data));
2804   BMFace *efa = bm_original_face_get(mr, p);
2805   BMEdge *eed = bm_original_edge_get(mr, mloop->e);
2806   BMVert *eve = bm_original_vert_get(mr, mloop->v);
2807   if (efa) {
2808     mesh_render_data_face_flag(mr, efa, -1, data);
2809   }
2810   if (eed) {
2811     mesh_render_data_edge_flag(mr, eed, data);
2812   }
2813   if (eve) {
2814     mesh_render_data_vert_flag(mr, eve, data);
2815   }
2816 }
2817
2818 static void extract_edit_data_ledge_bmesh(const MeshRenderData *mr,
2819                                           int e,
2820                                           BMEdge *eed,
2821                                           void *_data)
2822 {
2823   EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2;
2824   memset(data, 0x0, sizeof(*data) * 2);
2825   mesh_render_data_edge_flag(mr, eed, &data[0]);
2826   data[1] = data[0];
2827   mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
2828   mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
2829 }
2830
2831 static void extract_edit_data_ledge_mesh(const MeshRenderData *mr,
2832                                          int e,
2833                                          const MEdge *edge,
2834                                          void *_data)
2835 {
2836   EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2;
2837   memset(data, 0x0, sizeof(*data) * 2);
2838   int e_idx = mr->ledges[e];
2839   BMEdge *eed = bm_original_edge_get(mr, e_idx);
2840   BMVert *eve1 = bm_original_vert_get(mr, edge->v1);
2841   BMVert *eve2 = bm_original_vert_get(mr, edge->v2);
2842   if (eed) {
2843     mesh_render_data_edge_flag(mr, eed, &data[0]);
2844     data[1] = data[0];
2845   }
2846   if (eve1) {
2847     mesh_render_data_vert_flag(mr, eve1, &data[0]);
2848   }
2849   if (eve2) {
2850     mesh_render_data_vert_flag(mr, eve2, &data[1]);
2851   }
2852 }
2853
2854 static void extract_edit_data_lvert_bmesh(const MeshRenderData *mr,
2855                                           int v,
2856                                           BMVert *eve,
2857                                           void *_data)
2858 {
2859   EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v;
2860   memset(data, 0x0, sizeof(*data));
2861   mesh_render_data_vert_flag(mr, eve, data);
2862 }
2863
2864 static void extract_edit_data_lvert_mesh(const MeshRenderData *mr,
2865                                          int v,
2866                                          const MVert *UNUSED(mvert),
2867                                          void *_data)
2868 {
2869   EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v;
2870   memset(data, 0x0, sizeof(*data));
2871   int v_idx = mr->lverts[v];
2872   BMVert *eve = bm_original_vert_get(mr, v_idx);
2873   if (eve) {
2874     mesh_render_data_vert_flag(mr, eve, data);
2875   }
2876 }
2877
2878 static const MeshExtract extract_edit_data = {
2879     .init = extract_edit_data_init,
2880     .iter_loop_bm = extract_edit_data_loop_bmesh,
2881     .iter_loop_mesh = extract_edit_data_loop_mesh,
2882     .iter_ledge_bm = extract_edit_data_ledge_bmesh,
2883     .iter_ledge_mesh = extract_edit_data_ledge_mesh,
2884     .iter_lvert_bm = extract_edit_data_lvert_bmesh,
2885     .iter_lvert_mesh = extract_edit_data_lvert_mesh,
2886     .data_flag = 0,
2887     .use_threading = true,
2888 };
2889
2890 /** \} */
2891
2892 /* ---------------------------------------------------------------------- */
2893 /** \name Extract Edit UV Data / Flags
2894  * \{ */
2895
2896 typedef struct MeshExtract_EditUVData_Data {
2897   EditLoopData *vbo_data;
2898   int cd_ofs;
2899 } MeshExtract_EditUVData_Data;
2900
2901 static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf)
2902 {
2903   static GPUVertFormat format = {0};
2904   if (format.attr_len == 0) {
2905     /* WARNING: Adjust #EditLoopData struct accordingly. */
2906     GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
2907     GPU_vertformat_alias_add(&format, "flag");
2908   }
2909
2910   GPUVertBuf *vbo = buf;
2911   GPU_vertbuf_init_with_format(vbo, &format);
2912   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
2913
2914   CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
2915
2916   MeshExtract_EditUVData_Data *data = MEM_callocN(sizeof(*data), __func__);
2917   data->vbo_data = (EditLoopData *)vbo->data;
2918   data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
2919   return data;
2920 }
2921
2922 static void extract_edituv_data_loop_bmesh(const MeshRenderData *mr,
2923                                            int l,
2924                                            BMLoop *loop,
2925                                            void *_data)
2926 {
2927   MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data;
2928   EditLoopData *eldata = data->vbo_data + l;
2929   memset(eldata, 0x0, sizeof(*eldata));
2930   mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata);
2931   mesh_render_data_face_flag(mr, loop->f, data->cd_ofs, eldata);
2932   mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
2933 }
2934
2935 static void extract_edituv_data_loop_mesh(
2936     const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data)
2937 {
2938   MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data;
2939   EditLoopData *eldata = data->vbo_data + l;
2940   memset(eldata, 0x0, sizeof(*eldata));
2941   BMFace *efa = bm_original_face_get(mr, p);
2942   if (efa) {
2943     BMEdge *eed = bm_original_edge_get(mr, mloop->e);
2944     BMVert *eve = bm_original_vert_get(mr, mloop->v);
2945     if (eed && eve) {
2946       /* Loop on an edge endpoint. */
2947       BMLoop *loop = BM_face_edge_share_loop(efa, eed);
2948       mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata);
2949       mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
2950     }
2951     else {
2952       if (eed == NULL) {
2953         /* Find if the loop's vert is not part of an edit edge.
2954          * For this, we check if the previous loop was on an edge. */
2955         int loopend = mpoly->loopstart + mpoly->totloop - 1;
2956         int l_prev = (l == mpoly->loopstart) ? loopend : (l - 1);
2957         const MLoop *mloop_prev = &mr->mloop[l_prev];
2958         eed = bm_original_edge_get(mr, mloop_prev->e);
2959       }
2960       if (eed) {
2961         /* Mapped points on an edge between two edit verts. */
2962         BMLoop *loop = BM_face_edge_share_loop(efa, eed);
2963         mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata);
2964       }
2965     }
2966   }
2967 }
2968
2969 static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
2970                                        void *UNUSED(buf),
2971                                        void *data)
2972 {
2973   MEM_freeN(data);
2974 }
2975
2976 static const MeshExtract extract_edituv_data = {
2977     .init = extract_edituv_data_init,
2978     .iter_loop_bm = extract_edituv_data_loop_bmesh,
2979     .iter_loop_mesh = extract_edituv_data_loop_mesh,
2980     .finish = extract_edituv_data_finish,
2981     .data_flag = 0,
2982     .use_threading = true,
2983 };
2984
2985 /** \} */
2986
2987 /* ---------------------------------------------------------------------- */
2988 /** \name Extract Edit UV area stretch
2989  * \{ */
2990
2991 static void *extract_stretch_area_init(const MeshRenderData *mr, void *buf)
2992 {
2993   static GPUVertFormat format = {0};
2994   if (format.attr_len == 0) {
2995     GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
2996   }
2997
2998   GPUVertBuf *vbo = buf;
2999   GPU_vertbuf_init_with_format(vbo, &format);
3000   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
3001
3002   return NULL;
3003 }
3004
3005 BLI_INLINE float area_ratio_get(float area, float uvarea)
3006 {
3007   if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) {
3008     /* Tag inversion by using the sign. */
3009     return (area > uvarea) ? (uvarea / area) : -(area / uvarea);
3010   }
3011   return 0.0f;
3012 }
3013
3014 BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio)
3015 {
3016   ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio;
3017   return (ratio > 1.0f) ? (1.0f / ratio) : ratio;
3018 }
3019
3020 static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *UNUSED(data))
3021 {
3022   float tot_area = 0.0f, tot_uv_area = 0.0f;
3023   float *area_ratio = MEM_mallocN(sizeof(float) * mr->poly_len, __func__);
3024
3025   if (mr->extract_type == MR_EXTRACT_BMESH) {
3026     CustomData *cd_ldata = &mr->bm->ldata;
3027     int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
3028
3029     BMFace *efa;
3030     BMIter f_iter;
3031     int f;
3032     BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
3033       float area = BM_face_calc_area(efa);
3034       float uvarea = BM_face_calc_area_uv(efa, uv_ofs);
3035       tot_area += area;
3036       tot_uv_area += uvarea;
3037       area_ratio[f] = area_ratio_get(area, uvarea);
3038     }
3039   }
3040   else if (mr->extract_type == MR_EXTRACT_MAPPED) {
3041     const MLoopUV *uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
3042     const MPoly *mpoly = mr->mpoly;
3043     for (int p = 0; p < mr->poly_len; p++, mpoly++) {
3044       float area = BKE_mesh_calc_poly_area(mpoly, &mr->mloop[mpoly->loopstart], mr->mvert);
3045       float uvarea = BKE_mesh_calc_poly_uv_area(mpoly, uv_data);
3046       tot_area += area;
3047       tot_uv_area += uvarea;
3048       area_ratio[p] = area_ratio_get(area, uvarea);
3049     }
3050   }
3051   else {
3052     /* Should not happen. */
3053     BLI_assert(0);
3054   }
3055
3056   mr->cache->tot_area = tot_area;
3057   mr->cache->tot_uv_area = tot_uv_area;
3058
3059   /* Convert in place to avoid an extra allocation */
3060   uint16_t *poly_stretch = (uint16_t *)area_ratio;
3061   for (int p = 0; p < mr->poly_len; p++) {
3062     poly_stretch[p] = area_ratio[p] * SHRT_MAX;
3063   }
3064
3065   /* Copy face data for each loop. */
3066   GPUVertBuf *vbo = buf;
3067   uint16_t *loop_stretch = (uint16_t *)vbo->data;
3068
3069   if (mr->extract_type == MR_EXTRACT_BMESH) {
3070     BMFace *efa;
3071     BMIter f_iter;
3072     int f, l = 0;
3073     BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) {
3074       for (int i = 0; i < efa->len; i++, l++) {
3075         loop_stretch[l] = poly_stretch[f];
3076       }
3077     }
3078   }
3079   else if (mr->extract_type == MR_EXTRACT_MAPPED) {
3080     const MPoly *mpoly = mr->mpoly;
3081     for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
3082       for (int i = 0; i < mpoly->totloop; i++, l++) {
3083         loop_stretch[l] = poly_stretch[p];
3084       }
3085     }
3086   }
3087   else {
3088     /* Should not happen. */
3089     BLI_assert(0);
3090   }
3091
3092   MEM_freeN(area_ratio);
3093 }
3094
3095 static const MeshExtract extract_stretch_area = {
3096     .init = extract_stretch_area_init,
3097     .finish = mesh_stretch_area_finish,
3098     .data_flag = 0,
3099     .use_threading = false,
3100 };
3101
3102 /** \} */
3103
3104 /* ---------------------------------------------------------------------- */
3105 /** \name Extract Edit UV angle stretch
3106  * \{ */
3107
3108 typedef struct UVStretchAngle {
3109   int16_t angle;
3110   int16_t uv_angles[2];
3111 } UVStretchAngle;
3112
3113 typedef struct MeshExtract_StretchAngle_Data {
3114   UVStretchAngle *vbo_data;
3115   MLoopUV *luv;
3116   float auv[2][2], last_auv[2];
3117   float av[2][3], last_av[3];
3118   int cd_ofs;
3119 } MeshExtract_StretchAngle_Data;
3120
3121 static void compute_normalize_edge_vectors(float auv[2][2],
3122                                            float av[2][3],
3123                                            const float uv[2],
3124                                            const float uv_prev[2],
3125                                            const float co[3],
3126                                            const float co_prev[3])
3127 {
3128   /* Move previous edge. */
3129   copy_v2_v2(auv[0], auv[1]);
3130   copy_v3_v3(av[0], av[1]);
3131   /* 2d edge */
3132   sub_v2_v2v2(auv[1], uv_prev, uv);
3133   normalize_v2(auv[1]);
3134   /* 3d edge */
3135   sub_v3_v3v3(av[1], co_prev, co);
3136   normalize_v3(av[1]);
3137 }
3138
3139 static short v2_to_short_angle(float v[2])
3140 {
3141   return atan2f(v[1], v[0]) * (float)M_1_PI * SHRT_MAX;
3142 }
3143
3144 static void edituv_get_stretch_angle(float auv[2][2], float av[2][3], UVStretchAngle *r_stretch)
3145 {
3146   /* Send UV's to the shader and let it compute the aspect corrected angle. */
3147   r_stretch->uv_angles[0] = v2_to_short_angle(auv[0]);
3148   r_stretch->uv_angles[1] = v2_to_short_angle(auv[1]);
3149   /* Compute 3D angle here. */
3150   r_stretch->angle = angle_normalized_v3v3(av[0], av[1]) * (float)M_1_PI * SHRT_MAX;
3151
3152 #if 0 /* here for reference, this is done in shader now. */
3153   float uvang = angle_normalized_v2v2(auv0, auv1);
3154   float ang = angle_normalized_v3v3(av0, av1);
3155   float stretch = fabsf(uvang - ang) / (float)M_PI;
3156   return 1.0f - pow2f(1.0f - stretch);
3157 #endif
3158 }
3159
3160 static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf)
3161 {
3162   static GPUVertFormat format = {0};
3163   if (format.attr_len == 0) {
3164     /* Waning: adjust #UVStretchAngle struct accordingly. */
3165     GPU_vertformat_attr_add(&format, "angle", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
3166     GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
3167   }
3168
3169   GPUVertBuf *vbo = buf;
3170   GPU_vertbuf_init_with_format(vbo, &format);
3171   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
3172
3173   MeshExtract_StretchAngle_Data *data = MEM_callocN(sizeof(*data), __func__);
3174   data->vbo_data = (UVStretchAngle *)vbo->data;
3175
3176   /* Special iterator needed to save about half of the computing cost. */
3177   if (mr->extract_type == MR_EXTRACT_BMESH) {
3178     data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
3179   }
3180   else if (mr->extract_type == MR_EXTRACT_MAPPED) {
3181     data->luv = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
3182   }
3183   else {
3184     BLI_assert(0);
3185   }
3186   return data;
3187 }
3188
3189 static void extract_stretch_angle_loop_bmesh(const MeshRenderData *mr,
3190                                              int l,
3191                                              BMLoop *loop,
3192                                              void *_data)
3193 {
3194   MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data;
3195   float(*auv)[2] = data->auv, *last_auv = data->last_auv;
3196   float(*av)[3] = data->av, *last_av = data->last_av;
3197   const MLoopUV *luv, *luv_next;
3198   BMLoop *l_next = loop->next;
3199   BMFace *efa = loop->f;
3200   if (loop == BM_FACE_FIRST_LOOP(efa)) {
3201     /* First loop in face. */
3202     BMLoop *l_tmp = loop->prev;
3203     BMLoop *l_next_tmp = loop;
3204     luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
3205     luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
3206     compute_normalize_edge_vectors(auv,
3207                                    av,
3208                                    luv->uv,
3209                                    luv_next->uv,
3210                                    bm_vert_co_get(mr, l_tmp->v),
3211                                    bm_vert_co_get(mr, l_next_tmp->v));
3212     /* Save last edge. */
3213     copy_v2_v2(last_auv, auv[1]);
3214     copy_v3_v3(last_av, av[1]);
3215   }
3216   if (l_next == BM_FACE_FIRST_LOOP(efa)) {
3217     /* Move previous edge. */
3218     copy_v2_v2(auv[0], auv[1]);
3219     copy_v3_v3(av[0], av[1]);
3220     /* Copy already calculated last edge. */
3221     copy_v2_v2(auv[1], last_auv);
3222     copy_v3_v3(av[1], last_av);
3223   }
3224   else {
3225     luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs);
3226     luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
3227     compute_normalize_edge_vectors(auv,
3228                                    av,
3229                                    luv->uv,
3230                                    luv_next->uv,
3231                                    bm_vert_co_get(mr, loop->v),
3232                                    bm_vert_co_get(mr, l_next->v));
3233   }
3234   edituv_get_stretch_angle(auv, av, data->vbo_data + l);
3235 }
3236
3237 static void extract_stretch_angle_loop_mesh(const MeshRenderData *mr,
3238                                             int l,
3239                                             const MLoop *UNUSED(mloop),
3240                                             int UNUSED(p),
3241                                             const MPoly *mpoly,
3242                                             void *_data)
3243 {
3244   MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data;
3245   float(*auv)[2] = data->auv, *last_auv = data->last_auv;
3246   float(*av)[3] = data->av, *last_av = data->last_av;
3247   int l_next = l + 1, loopend = mpoly->loopstart + mpoly->totloop;
3248   const MVert *v, *v_next;
3249   if (l == mpoly->loopstart) {
3250     /* First loop in face. */
3251     int l_tmp = loopend - 1;
3252     int l_next_tmp = mpoly->loopstart;
3253     v = &mr->mvert[mr->mloop[l_tmp].v];
3254     v_next = &mr->mvert[mr->mloop[l_next_tmp].v];
3255     compute_normalize_edge_vectors(
3256         auv, av, data->luv[l_tmp].uv, data->luv[l_next_tmp].uv, v->co, v_next->co);
3257     /* Save last edge. */
3258     copy_v2_v2(last_auv, auv[1]);
3259     copy_v3_v3(last_av, av[1]);
3260   }
3261   if (l_next == loopend) {
3262     l_next = mpoly->loopstart;
3263     /* Move previous edge. */
3264     copy_v2_v2(auv[0], auv[1]);
3265     copy_v3_v3(av[0], av[1]);
3266     /* Copy already calculated last edge. */
3267     copy_v2_v2(auv[1], last_auv);
3268     copy_v3_v3(av[1], last_av);
3269   }
3270   else {
3271     v = &mr->mvert[mr->mloop[l].v];
3272     v_next = &mr->mvert[mr->mloop[l_next].v];
3273     compute_normalize_edge_vectors(
3274         auv, av, data->luv[l].uv, data->luv[l_next].uv, v->co, v_next->co);
3275   }
3276   edituv_get_stretch_angle(auv, av, data->vbo_data + l);
3277 }
3278
3279 static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr),
3280                                          void *UNUSED(buf),
3281                                          void *data)
3282 {
3283   MEM_freeN(data);
3284 }
3285
3286 static const MeshExtract extract_stretch_angle = {
3287     .init = extract_stretch_angle_init,
3288     .iter_loop_bm = extract_stretch_angle_loop_bmesh,
3289     .iter_loop_mesh = extract_stretch_angle_loop_mesh,
3290     .finish = extract_stretch_angle_finish,
3291     .data_flag = 0,
3292     .use_threading = false,
3293 };
3294
3295 /** \} */
3296
3297 /* ---------------------------------------------------------------------- */
3298 /** \name Extract Edit Mesh Analysis Colors
3299  * \{ */
3300
3301 static void *extract_mesh_analysis_init(const MeshRenderData *mr, void *buf)
3302 {
3303   static GPUVertFormat format = {0};
3304   if (format.attr_len == 0) {
3305     GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
3306   }
3307
3308   GPUVertBuf *vbo = buf;
3309   GPU_vertbuf_init_with_format(vbo, &format);
3310   GPU_vertbuf_data_alloc(vbo, mr->loop_len);
3311
3312   return NULL;
3313 }
3314
3315 static void axis_from_enum_v3(float v[3], const char axis)
3316 {
3317   zero_v3(v);
3318   if (axis < 3) {
3319     v[axis] = 1.0f;
3320   }
3321   else {
3322     v[axis - 3] = -1.0f;
3323   }
3324 }
3325
3326 BLI_INLINE float overhang_remap(float fac, float min, float max, float minmax_irange)
3327 {
3328   if (fac < min) {
3329     fac = 1.0f;
3330   }
3331   else if (fac > max) {
3332     fac = -1.0f;
3333   }
3334   else {
3335     fac = (fac - min) * minmax_irange;
3336     fac = 1.0f - fac;
3337     CLAMP(fac, 0.0f, 1.0f);
3338   }
3339   return fac;
3340 }
3341
3342 static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang)
3343 {
3344   const MeshStatVis *statvis = &mr->toolsettings->statvis;
3345   const float min = statvis->overhang_min / (float)M_PI;
3346   const float max = statvis->overhang_max / (float)M_PI;
3347   const char axis = statvis->overhang_axis;
3348   BMEditMesh *em = mr->edit_bmesh;
3349   BMIter iter;
3350   BMesh *bm = em->bm;
3351   BMFace *f;
3352   float dir[3];
3353   const float minmax_irange = 1.0f / (max - min);
3354
3355   BLI_assert(min <= max);
3356
3357   axis_from_enum_v3(dir, axis);
3358
3359   /* now convert into global space */
3360   mul_transposed_mat3_m4_v3(mr->obmat, dir);
3361   normalize_v3(dir);
3362
3363   if (mr->extract_type == MR_EXTRACT_BMESH) {
3364     int l = 0;
3365     BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
3366       float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI;
3367       fac = overhang_remap(fac, min, max, minmax_irange);
3368       for (int i = 0; i < f->len; i++, l++) {
3369         r_overhang[l] = fac;
3370       }
3371     }
3372   }
3373   else {
3374     const MPoly *mpoly = mr->mpoly;
3375     for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) {
3376       float fac = angle_normalized_v3v3(mr->poly_normals[p], dir) / (float)M_PI;
3377       fac = overhang_remap(fac, min, max, minmax_irange);
3378       for (int i = 0; i < mpoly->totloop; i++, l++) {
3379         r_overhang[l] = fac;
3380       }
3381     }
3382   }
3383 }
3384
3385 /**
3386  * Needed so we can use jitter values for face interpolation.
3387  */
3388 static void uv_from_jitter_v2(float uv[2])
3389 {
3390   uv[0] += 0.5f;
3391   uv[1] += 0.5f;
3392   if (uv[0] + uv[1] > 1.0f) {
3393     uv[0] = 1.0f - uv[0];
3394     uv[1] = 1.0f - uv[1];
3395   }
3396
3397   clamp_v2(uv, 0.0f, 1.0f);
3398 }
3399
3400 BLI_INLINE float thickness_remap(float fac, float min, float max, float minmax_irange)
3401 {
3402   /* important not '<=' */
3403   if (fac < max) {
3404     fac = (fac - min) * minmax_irange;
3405     fac = 1.0f - fac;
3406     CLAMP(fac, 0.0f, 1.0f);
3407   }
3408   else {
3409     fac = -1.0f;
3410   }
3411   return fac;
3412 }
3413
3414 static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness)
3415 {
3416   const float eps_offset = 0.00002f; /* values <= 0.00001 give errors */
3417   /* cheating to avoid another allocation */
3418   float *face_dists = r_thickness + (mr->loop_len - mr->poly_len);
3419   BMEditMesh *em = mr->edit_bmesh;
3420   const float scale = 1.0f / mat4_to_scale(mr->obmat);
3421   const MeshStatVis *statvis = &mr->toolsettings->statvis;
3422   const float min = statvis->thickness_min * scale;