diff options
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 8 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 32 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh.c | 3415 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 6 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_curve.c | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_gpencil.c | 21 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 98 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_metaball.c | 12 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_inline.h | 24 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 7 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_hair.c | 157 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 49 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_data.c | 37 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_select_buffer.c | 7 |
16 files changed, 2282 insertions, 1607 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 89dd6fa210c..555043ab408 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -462,6 +462,10 @@ void DRW_shgroup_uniform_texture_ex(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex, eGPUSamplerState sampler_state); +void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup, + const char *name, + GPUTexture **tex, + eGPUSamplerState sampler_state); void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex); @@ -569,7 +573,7 @@ void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float w const DRWView *DRW_view_default_get(void); void DRW_view_default_set(DRWView *view); - +void DRW_view_reset(void); void DRW_view_set_active(DRWView *view); void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len); @@ -626,6 +630,8 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, void (*callback)(void *vedata, void *user_data), void *user_data); +void DRW_cache_restart(void); + /* ViewLayers */ void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type); void **DRW_view_layer_engine_data_ensure_ex(struct ViewLayer *view_layer, diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index af5b9cd05dd..9f30cd85957 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -888,6 +888,32 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob) } } +/* Returns the vertbuf used by shaded surface batch. */ +GPUVertBuf *DRW_cache_object_pos_vertbuf_get(Object *ob) +{ + Mesh *me = BKE_object_get_evaluated_mesh(ob); + short type = (me != NULL) ? OB_MESH : ob->type; + + switch (type) { + case OB_MESH: + return DRW_mesh_batch_cache_pos_vertbuf_get((me != NULL) ? me : ob->data); + case OB_CURVE: + case OB_SURF: + case OB_FONT: + return DRW_curve_batch_cache_pos_vertbuf_get(ob->data); + case OB_MBALL: + return DRW_mball_batch_cache_pos_vertbuf_get(ob); + case OB_HAIR: + return NULL; + case OB_POINTCLOUD: + return NULL; + case OB_VOLUME: + return NULL; + default: + return NULL; + } +} + int DRW_cache_object_material_count_get(struct Object *ob) { Mesh *me = BKE_object_get_evaluated_mesh(ob); @@ -2844,6 +2870,12 @@ GPUBatch *DRW_cache_mesh_surface_vertpaint_get(Object *ob) return DRW_mesh_batch_cache_get_surface_vertpaint(ob->data); } +GPUBatch *DRW_cache_mesh_surface_sculptcolors_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + return DRW_mesh_batch_cache_get_surface_sculpt(ob->data); +} + GPUBatch *DRW_cache_mesh_surface_weights_get(Object *ob) { BLI_assert(ob->type == OB_MESH); diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 221fb89612f..2f289bf4110 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -63,6 +63,8 @@ struct GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob, struct GPUBatch *DRW_cache_object_face_wireframe_get(struct Object *ob); int DRW_cache_object_material_count_get(struct Object *ob); +struct GPUVertBuf *DRW_cache_object_pos_vertbuf_get(struct Object *ob); + /* Empties */ struct GPUBatch *DRW_cache_plain_axes_get(void); struct GPUBatch *DRW_cache_single_arrow_get(void); @@ -134,6 +136,7 @@ struct GPUBatch **DRW_cache_mesh_surface_shaded_get(struct Object *ob, struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_surface_vertpaint_get(struct Object *ob); +struct GPUBatch *DRW_cache_mesh_surface_sculptcolors_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(struct Object *ob); struct GPUBatch *DRW_cache_mesh_face_wireframe_get(struct Object *ob); diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index f203c2ff1ea..302f9a0d3a8 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -53,6 +53,7 @@ typedef struct DRW_MeshCDMask { uint32_t uv : 8; uint32_t tan : 8; uint32_t vcol : 8; + uint32_t sculpt_vcol : 8; uint32_t orco : 1; uint32_t tan_orco : 1; /** Edit uv layer is from the base edit mesh as @@ -62,7 +63,7 @@ typedef struct DRW_MeshCDMask { typedef enum eMRIterType { MR_ITER_LOOPTRI = 1 << 0, - MR_ITER_LOOP = 1 << 1, + MR_ITER_POLY = 1 << 1, MR_ITER_LEDGE = 1 << 2, MR_ITER_LVERT = 1 << 3, } eMRIterType; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index f3dc8f0fd2a..c92722fad7e 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -128,7 +128,7 @@ typedef struct MeshRenderData { BMEdge *eed_act; BMFace *efa_act; BMFace *efa_act_uv; - /* Data created on-demand (usually not for bmesh-based data). */ + /* Data created on-demand (usually not for #BMesh based data). */ MLoopTri *mlooptri; float (*loop_normals)[3]; float (*poly_normals)[3]; @@ -145,17 +145,17 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr, mr->vert_loose_len = 0; mr->edge_loose_len = 0; - BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, "lvert map"); + BLI_bitmap *lvert_map = BLI_BITMAP_NEW(mr->vert_len, __func__); mr->ledges = MEM_mallocN(mr->edge_len * sizeof(int), __func__); - const MEdge *medge = mr->medge; - for (int e = 0; e < mr->edge_len; e++, medge++) { - if (medge->flag & ME_LOOSEEDGE) { - mr->ledges[mr->edge_loose_len++] = e; + const MEdge *med = mr->medge; + for (int med_index = 0; med_index < mr->edge_len; med_index++, med++) { + if (med->flag & ME_LOOSEEDGE) { + mr->ledges[mr->edge_loose_len++] = med_index; } /* Tag verts as not loose. */ - BLI_BITMAP_ENABLE(lvert_map, medge->v1); - BLI_BITMAP_ENABLE(lvert_map, medge->v2); + BLI_BITMAP_ENABLE(lvert_map, med->v1); + BLI_BITMAP_ENABLE(lvert_map, med->v2); } if (mr->edge_loose_len < mr->edge_len) { mr->ledges = MEM_reallocN(mr->ledges, mr->edge_loose_len * sizeof(*mr->ledges)); @@ -173,11 +173,11 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr, MEM_freeN(lvert_map); - mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2; + mr->loop_loose_len = mr->vert_loose_len + (mr->edge_loose_len * 2); } } else { - /* BMesh */ + /* #BMesh */ BMesh *bm = mr->bm; if (iter_type & (MR_ITER_LEDGE | MR_ITER_LVERT)) { int elem_id; @@ -212,7 +212,9 @@ static void mesh_render_data_update_loose_geom(MeshRenderData *mr, } } -/* Part of the creation of the MeshRenderData that happens in a thread. */ +/** + * Part of the creation of the #MeshRenderData that happens in a thread. + */ static void mesh_render_data_update_looptris(MeshRenderData *mr, const eMRIterType iter_type, const eMRDataType data_flag) @@ -227,7 +229,7 @@ static void mesh_render_data_update_looptris(MeshRenderData *mr, } } else { - /* BMesh */ + /* #BMesh */ if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) { /* Edit mode ensures this is valid, no need to calculate. */ BLI_assert((mr->bm->totloop == 0) || (mr->edit_bmesh->looptris != NULL)); @@ -278,9 +280,9 @@ static void mesh_render_data_update_normals(MeshRenderData *mr, } } else { - /* BMesh */ + /* #BMesh */ if (data_flag & MR_DATA_POLY_NOR) { - /* Use bmface->no instead. */ + /* Use #BMFace.no instead. */ } if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { @@ -295,7 +297,7 @@ static void mesh_render_data_update_normals(MeshRenderData *mr, } mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__); - int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); + const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); BM_loops_calc_normal_vcos(mr->bm, vert_coords, vert_normals, @@ -419,7 +421,7 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX); } else { - /* BMesh */ + /* #BMesh */ BMesh *bm = mr->bm; mr->vert_len = bm->totvert; @@ -486,7 +488,7 @@ BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *e } else { UNUSED_VARS(mr); - return eve->co; + return eve->no; } } @@ -505,48 +507,283 @@ BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *e /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Mesh Elements Extract Iter +/** \name Mesh Elements Extract: Loop Triangles + * \{ */ + +typedef struct ExtractTriBMesh_Params { + BMLoop *(*looptris)[3]; + int tri_range[2]; +} ExtractTriBMesh_Params; +typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr, + const ExtractTriBMesh_Params *params, + void *data); + +#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elem_tri, index_tri, params) \ + CHECK_TYPE(params, const ExtractTriBMesh_Params *); \ + { \ + const int _tri_index_end = (params)->tri_range[1]; \ + BMLoop **elem_tri = (params)->looptris[(params)->tri_range[0]]; \ + for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ + index_tri += 1, elem_tri += 3) +#define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END } + +typedef struct ExtractTriMesh_Params { + const MLoopTri *mlooptri; + int tri_range[2]; +} ExtractTriMesh_Params; +typedef void(ExtractTriMeshFn)(const MeshRenderData *mr, + const ExtractTriMesh_Params *params, + void *data); + +#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(elem_tri, index_tri, params) \ + CHECK_TYPE(params, const ExtractTriMesh_Params *); \ + { \ + const int _tri_index_end = (params)->tri_range[1]; \ + const MLoopTri *elem_tri = &(params)->mlooptri[(params)->tri_range[0]]; \ + for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ + index_tri += 1, elem_tri += 1) +#define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END } + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Mesh Elements Extract: Polygons, Loops + * \{ */ + +typedef struct ExtractPolyBMesh_Params { + BMLoop *(*looptris)[3]; + int poly_range[2]; +} ExtractPolyBMesh_Params; +typedef void(ExtractPolyBMeshFn)(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data); + +#define EXTRACT_POLY_FOREACH_BM_BEGIN(elem_poly, index_poly, params, mr) \ + CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \ + { \ + BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ + BMFace **_ftable = mr->bm->ftable; \ + const int _poly_index_end = (params)->poly_range[1]; \ + for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ + index_poly += 1) { \ + BMFace *elem_poly = _ftable[index_poly]; \ + (void)elem_poly; + +#define EXTRACT_POLY_FOREACH_BM_END \ + } \ + } + +/* Iterate over polygon and loop. */ +#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(elem_loop, index_loop, params, mr) \ + CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \ + { \ + BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ + BMFace **_ftable = mr->bm->ftable; \ + const int _poly_index_end = (params)->poly_range[1]; \ + for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ + index_poly += 1) { \ + BMFace *elem_face = _ftable[index_poly]; \ + BMLoop *elem_loop, *l_first; \ + elem_loop = l_first = BM_FACE_FIRST_LOOP(elem_face); \ + do { \ + const int index_loop = BM_elem_index_get(elem_loop); \ + (void)index_loop; /* Quiet warning when unused. */ + +#define EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(elem_loop) \ + } \ + while ((elem_loop = elem_loop->next) != l_first) \ + ; \ + } \ + } + +typedef struct ExtractPolyMesh_Params { + int poly_range[2]; +} ExtractPolyMesh_Params; +typedef void(ExtractPolyMeshFn)(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data); + +#define EXTRACT_POLY_FOREACH_MESH_BEGIN(elem_poly, index_poly, params, mr) \ + CHECK_TYPE(params, const ExtractPolyMesh_Params *); \ + { \ + const MPoly *_mpoly = mr->mpoly; \ + const int _poly_index_end = (params)->poly_range[1]; \ + for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ + index_poly += 1) { \ + const MPoly *elem_poly = &_mpoly[index_poly]; \ + (void)elem_poly; + +#define EXTRACT_POLY_FOREACH_MESH_END \ + } \ + } + +/* Iterate over polygon and loop. */ +#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN( \ + elem_poly, index_poly, elem_loop, index_loop, params, mr) \ + CHECK_TYPE(params, const ExtractPolyMesh_Params *); \ + { \ + const MPoly *_mpoly = mr->mpoly; \ + const MLoop *_mloop = mr->mloop; \ + const int _poly_index_end = (params)->poly_range[1]; \ + for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ + index_poly += 1) { \ + const MPoly *elem_poly = &_mpoly[index_poly]; \ + const int _index_end = elem_poly->loopstart + elem_poly->totloop; \ + for (int index_loop = elem_poly->loopstart; index_loop < _index_end; index_loop += 1) { \ + const MLoop *elem_loop = &_mloop[index_loop]; \ + (void)elem_loop; + +#define EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END \ + } \ + } \ + } + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Mesh Elements Extract: Loose Edges + * \{ */ + +typedef struct ExtractLEdgeBMesh_Params { + const int *ledge; + int ledge_range[2]; +} ExtractLEdgeBMesh_Params; +typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *data); + +#define EXTRACT_LEDGE_FOREACH_BM_BEGIN(elem_edge, index_ledge, params) \ + CHECK_TYPE(params, const ExtractLEdgeBMesh_Params *); \ + { \ + BLI_assert((mr->bm->elem_table_dirty & BM_EDGE) == 0); \ + BMEdge **_etable = mr->bm->etable; \ + const int *_ledge = (params)->ledge; \ + const int _ledge_index_end = (params)->ledge_range[1]; \ + for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \ + index_ledge += 1) { \ + BMEdge *elem_edge = _etable[_ledge[index_ledge]]; \ + (void)elem_edge; /* Quiet warning when unused. */ \ + { +#define EXTRACT_LEDGE_FOREACH_BM_END \ + } \ + } \ + } + +typedef struct ExtractLEdgeMesh_Params { + const int *ledge; + int ledge_range[2]; +} ExtractLEdgeMesh_Params; +typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *data); + +#define EXTRACT_LEDGE_FOREACH_MESH_BEGIN(elem_edge, index_ledge, params, mr) \ + CHECK_TYPE(params, const ExtractLEdgeMesh_Params *); \ + { \ + const MEdge *_medge = mr->medge; \ + const int *_ledge = (params)->ledge; \ + const int _ledge_index_end = (params)->ledge_range[1]; \ + for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \ + index_ledge += 1) { \ + const MEdge *elem_edge = &_medge[_ledge[index_ledge]]; \ + (void)elem_edge; /* Quiet warning when unused. */ \ + { +#define EXTRACT_LEDGE_FOREACH_MESH_END \ + } \ + } \ + } + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Mesh Elements Extract: Loose Vertices + * \{ */ + +typedef struct ExtractLVertBMesh_Params { + const int *lvert; + int lvert_range[2]; +} ExtractLVertBMesh_Params; +typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr, + const ExtractLVertBMesh_Params *params, + void *data); + +#define EXTRACT_LVERT_FOREACH_BM_BEGIN(elem_vert, index_lvert, params) \ + CHECK_TYPE(params, const ExtractLVertBMesh_Params *); \ + { \ + BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ + BMVert **vtable = mr->bm->vtable; \ + const int *lverts = (params)->lvert; \ + const int _lvert_index_end = (params)->lvert_range[1]; \ + for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \ + index_lvert += 1) { \ + BMVert *elem_vert = vtable[lverts[index_lvert]]; \ + (void)elem_vert; /* Quiet warning when unused. */ \ + { +#define EXTRACT_LVERT_FOREACH_BM_END \ + } \ + } \ + } + +typedef struct ExtractLVertMesh_Params { + const int *lvert; + int lvert_range[2]; +} ExtractLVertMesh_Params; +typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr, + const ExtractLVertMesh_Params *params, + void *data); + +#define EXTRACT_LVERT_FOREACH_MESH_BEGIN(elem, index_lvert, params, mr) \ + CHECK_TYPE(params, const ExtractLVertMesh_Params *); \ + { \ + const MVert *mvert = mr->mvert; \ + const int *lverts = (params)->lvert; \ + const int _lvert_index_end = (params)->lvert_range[1]; \ + for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \ + index_lvert += 1) { \ + const MVert *elem = &mvert[lverts[index_lvert]]; \ + (void)elem; /* Quiet warning when unused. */ \ + { +#define EXTRACT_LVERT_FOREACH_MESH_END \ + } \ + } \ + } + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Mesh Elements Extract Struct * \{ */ typedef void *(ExtractInitFn)(const MeshRenderData *mr, void *buffer); -typedef void(ExtractEditTriFn)(const MeshRenderData *mr, int t, BMLoop **e, void *data); -typedef void(ExtractEditLoopFn)(const MeshRenderData *mr, int l, BMLoop *el, void *data); -typedef void(ExtractEditLedgeFn)(const MeshRenderData *mr, int e, BMEdge *ed, void *data); -typedef void(ExtractEditLvertFn)(const MeshRenderData *mr, int v, BMVert *ev, void *data); -typedef void(ExtractTriFn)(const MeshRenderData *mr, int t, const MLoopTri *mlt, void *data); -typedef void(ExtractLoopFn)( - const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data); -typedef void(ExtractLedgeFn)(const MeshRenderData *mr, int e, const MEdge *medge, void *data); -typedef void(ExtractLvertFn)(const MeshRenderData *mr, int v, const MVert *mvert, void *data); typedef void(ExtractFinishFn)(const MeshRenderData *mr, void *buffer, void *data); typedef struct MeshExtract { - /** Executed on main thread and return user data for iter functions. */ + /** Executed on main thread and return user data for iteration functions. */ ExtractInitFn *init; /** Executed on one (or more if use_threading) worker thread(s). */ - ExtractEditTriFn *iter_looptri_bm; - ExtractTriFn *iter_looptri; - ExtractEditLoopFn *iter_loop_bm; - ExtractLoopFn *iter_loop; - ExtractEditLedgeFn *iter_ledge_bm; - ExtractLedgeFn *iter_ledge; - ExtractEditLvertFn *iter_lvert_bm; - ExtractLvertFn *iter_lvert; + ExtractTriBMeshFn *iter_looptri_bm; + ExtractTriMeshFn *iter_looptri_mesh; + ExtractPolyBMeshFn *iter_poly_bm; + ExtractPolyMeshFn *iter_poly_mesh; + ExtractLEdgeBMeshFn *iter_ledge_bm; + ExtractLEdgeMeshFn *iter_ledge_mesh; + ExtractLVertBMeshFn *iter_lvert_bm; + ExtractLVertMeshFn *iter_lvert_mesh; /** Executed on one worker thread after all elements iterations. */ ExtractFinishFn *finish; /** Used to request common data. */ const eMRDataType data_flag; - /** Used to know if the element callbacks are threadsafe and can be parallelized. */ + /** Used to know if the element callbacks are thread-safe and can be parallelized. */ const bool use_threading; } MeshExtract; BLI_INLINE eMRIterType mesh_extract_iter_type(const MeshExtract *ext) { eMRIterType type = 0; - SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri), MR_ITER_LOOPTRI); - SET_FLAG_FROM_TEST(type, (ext->iter_loop_bm || ext->iter_loop), MR_ITER_LOOP); - SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge), MR_ITER_LEDGE); - SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert), MR_ITER_LVERT); + SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri_mesh), MR_ITER_LOOPTRI); + SET_FLAG_FROM_TEST(type, (ext->iter_poly_bm || ext->iter_poly_mesh), MR_ITER_POLY); + SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge_mesh), MR_ITER_LEDGE); + SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert_mesh), MR_ITER_LVERT); return type; } @@ -583,15 +820,15 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo)) } } else { - const MPoly *mpoly = mr->mpoly; - for (int p = 0; p < mr->poly_len; p++, mpoly++) { - if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) { - int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1); - mat_tri_len[mat] += mpoly->totloop - 2; + const MPoly *mp = mr->mpoly; + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + int mat = min_ii(mp->mat_nr, mr->mat_len - 1); + mat_tri_len[mat] += mp->totloop - 2; } } } - /* Accumulate tri len per mat to have correct offsets. */ + /* Accumulate triangle lengths per material to have correct offsets. */ int ofs = mat_tri_len[0]; mat_tri_len[0] = 0; for (int i = 1; i < mr->mat_len; i++) { @@ -608,51 +845,59 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo)) return data; } -static void extract_tris_looptri_bmesh(const MeshRenderData *mr, - int UNUSED(t), - BMLoop **elt, - void *_data) +static void extract_tris_iter_looptri_bm(const MeshRenderData *mr, + const struct ExtractTriBMesh_Params *params, + void *_data) { - if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { - MeshExtract_Tri_Data *data = _data; - int *mat_tri_ofs = data->tri_mat_end; - int mat = min_ii(elt[0]->f->mat_nr, mr->mat_len - 1); - GPU_indexbuf_set_tri_verts(&data->elb, - mat_tri_ofs[mat]++, - BM_elem_index_get(elt[0]), - BM_elem_index_get(elt[1]), - BM_elem_index_get(elt[2])); + MeshExtract_Tri_Data *data = _data; + const int mat_last = mr->mat_len - 1; + EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params) + { + if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { + int *mat_tri_ofs = data->tri_mat_end; + const int mat = min_ii(elt[0]->f->mat_nr, mat_last); + GPU_indexbuf_set_tri_verts(&data->elb, + mat_tri_ofs[mat]++, + BM_elem_index_get(elt[0]), + BM_elem_index_get(elt[1]), + BM_elem_index_get(elt[2])); + } } + EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; } -static void extract_tris_looptri_mesh(const MeshRenderData *mr, - int UNUSED(t), - const MLoopTri *mlt, - void *_data) +static void extract_tris_iter_looptri_mesh(const MeshRenderData *mr, + const struct ExtractTriMesh_Params *params, + void *_data) { - const MPoly *mpoly = &mr->mpoly[mlt->poly]; - if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) { - MeshExtract_Tri_Data *data = _data; - int *mat_tri_ofs = data->tri_mat_end; - int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1); - GPU_indexbuf_set_tri_verts( - &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]); + MeshExtract_Tri_Data *data = _data; + const int mat_last = mr->mat_len - 1; + EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params) + { + const MPoly *mp = &mr->mpoly[mlt->poly]; + if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + int *mat_tri_ofs = data->tri_mat_end; + const int mat = min_ii(mp->mat_nr, mat_last); + GPU_indexbuf_set_tri_verts( + &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]); + } } + EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; } static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data) { MeshExtract_Tri_Data *data = _data; GPU_indexbuf_build_in_place(&data->elb, ibo); - /* HACK Create ibo subranges and assign them to each GPUBatch. */ + /* HACK: Create ibo sub-ranges and assign them to each #GPUBatch. */ if (mr->use_final_mesh && mr->cache->surface_per_mat && mr->cache->surface_per_mat[0]) { BLI_assert(mr->cache->surface_per_mat[0]->elem == ibo); for (int i = 0; i < mr->mat_len; i++) { /* Multiply by 3 because these are triangle indices. */ - int start = data->tri_mat_start[i] * 3; - int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3; + const int start = data->tri_mat_start[i] * 3; + const int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3; GPUIndexBuf *sub_ibo = GPU_indexbuf_create_subrange(ibo, start, len); - /* WARNING: We modify the GPUBatch here! */ + /* WARNING: We modify the #GPUBatch here! */ GPU_batch_elembuf_set(mr->cache->surface_per_mat[i], sub_ibo, true); } } @@ -662,18 +907,12 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data } static const MeshExtract extract_tris = { - extract_tris_init, - extract_tris_looptri_bmesh, - extract_tris_looptri_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_tris_finish, - 0, - false, + .init = extract_tris_init, + .iter_looptri_bm = extract_tris_iter_looptri_bm, + .iter_looptri_mesh = extract_tris_iter_looptri_mesh, + .finish = extract_tris_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -691,71 +930,113 @@ static void *extract_lines_init(const MeshRenderData *mr, void *UNUSED(buf)) return elb; } -static void extract_lines_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *elb) -{ - if (!BM_elem_flag_test(loop->e, BM_ELEM_HIDDEN)) { - GPU_indexbuf_set_line_verts(elb, BM_elem_index_get(loop->e), l, BM_elem_index_get(loop->next)); - } - else { - GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(loop->e)); - } -} - -static void extract_lines_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *mpoly, - void *elb) -{ - const MEdge *medge = &mr->medge[mloop->e]; - if (!((mr->use_hide && (medge->flag & ME_HIDE)) || - ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && - (mr->e_origindex[mloop->e] == ORIGINDEX_NONE)))) { - int loopend = mpoly->totloop + mpoly->loopstart - 1; - int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1); - GPU_indexbuf_set_line_verts(elb, mloop->e, l, other_loop); +static void extract_lines_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *elb) +{ + /* Using poly & loop iterator would complicate accessing the adjacent loop. */ + EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) + { + BMLoop *l_iter, *l_first; + /* Use #BMLoop.prev to match mesh order (to avoid minor differences in data extraction). */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f)->prev; + do { + if (!BM_elem_flag_test(l_iter->e, BM_ELEM_HIDDEN)) { + GPU_indexbuf_set_line_verts(elb, + BM_elem_index_get(l_iter->e), + BM_elem_index_get(l_iter), + BM_elem_index_get(l_iter->next)); + } + else { + GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(l_iter->e)); + } + } while ((l_iter = l_iter->next) != l_first); + } + EXTRACT_POLY_FOREACH_BM_END; +} + +static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *elb) +{ + /* Using poly & loop iterator would complicate accessing the adjacent loop. */ + const MLoop *mloop = mr->mloop; + const MEdge *medge = mr->medge; + if (mr->use_hide || (mr->extract_type == MR_EXTRACT_MAPPED) || (mr->e_origindex != NULL)) { + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + const int ml_index_last = mp->loopstart + (mp->totloop - 1); + int ml_index = ml_index_last, ml_index_next = mp->loopstart; + do { + const MLoop *ml = &mloop[ml_index]; + const MEdge *med = &medge[ml->e]; + if (!((mr->use_hide && (med->flag & ME_HIDE)) || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && + (mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) { + GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); + } + else { + GPU_indexbuf_set_line_restart(elb, ml->e); + } + } while ((ml_index = ml_index_next++) != ml_index_last); + } + EXTRACT_POLY_FOREACH_MESH_END; } else { - GPU_indexbuf_set_line_restart(elb, mloop->e); + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + const int ml_index_last = mp->loopstart + (mp->totloop - 1); + int ml_index = ml_index_last, ml_index_next = mp->loopstart; + do { + const MLoop *ml = &mloop[ml_index]; + GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); + } while ((ml_index = ml_index_next++) != ml_index_last); + } + EXTRACT_POLY_FOREACH_MESH_END; } } -static void extract_lines_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb) +static void extract_lines_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *elb) { - int ledge_idx = mr->edge_len + e; - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - int l = mr->loop_len + e * 2; - GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1); - } - else { - GPU_indexbuf_set_line_restart(elb, ledge_idx); + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + const int l_index_offset = mr->edge_len + ledge_index; + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + const int l_index = mr->loop_len + ledge_index * 2; + GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1); + } + else { + GPU_indexbuf_set_line_restart(elb, l_index_offset); + } + /* Don't render the edge twice. */ + GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed)); } - /* Don't render the edge twice. */ - GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed)); + EXTRACT_LEDGE_FOREACH_BM_END; } -static void extract_lines_ledge_mesh(const MeshRenderData *mr, - int e, - const MEdge *medge, - void *elb) +static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *elb) { - int ledge_idx = mr->edge_len + e; - int edge_idx = mr->ledges[e]; - if (!((mr->use_hide && (medge->flag & ME_HIDE)) || - ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && - (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) { - int l = mr->loop_len + e * 2; - GPU_indexbuf_set_line_verts(elb, ledge_idx, l, l + 1); - } - else { - GPU_indexbuf_set_line_restart(elb, ledge_idx); + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + const int l_index_offset = mr->edge_len + ledge_index; + const int e_index = mr->ledges[ledge_index]; + if (!((mr->use_hide && (med->flag & ME_HIDE)) || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && + (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { + const int l_index = mr->loop_len + ledge_index * 2; + GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1); + } + else { + GPU_indexbuf_set_line_restart(elb, l_index_offset); + } + /* Don't render the edge twice. */ + GPU_indexbuf_set_line_restart(elb, e_index); } - /* Don't render the edge twice. */ - GPU_indexbuf_set_line_restart(elb, edge_idx); + EXTRACT_LEDGE_FOREACH_MESH_END; } static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb) @@ -765,18 +1046,14 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo } static const MeshExtract extract_lines = { - extract_lines_init, - NULL, - NULL, - extract_lines_loop_bmesh, - extract_lines_loop_mesh, - extract_lines_ledge_bmesh, - extract_lines_ledge_mesh, - NULL, - NULL, - extract_lines_finish, - 0, - false, + .init = extract_lines_init, + .iter_poly_bm = extract_lines_iter_poly_bm, + .iter_poly_mesh = extract_lines_iter_poly_mesh, + .iter_ledge_bm = extract_lines_iter_ledge_bm, + .iter_ledge_mesh = extract_lines_iter_ledge_mesh, + .finish = extract_lines_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -803,18 +1080,14 @@ static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void } static const MeshExtract extract_lines_with_lines_loose = { - extract_lines_init, - NULL, - NULL, - extract_lines_loop_bmesh, - extract_lines_loop_mesh, - extract_lines_ledge_bmesh, - extract_lines_ledge_mesh, - NULL, - NULL, - extract_lines_with_lines_loose_finish, - 0, - false, + .init = extract_lines_init, + .iter_poly_bm = extract_lines_iter_poly_bm, + .iter_poly_mesh = extract_lines_iter_poly_mesh, + .iter_ledge_bm = extract_lines_iter_ledge_bm, + .iter_ledge_mesh = extract_lines_iter_ledge_mesh, + .finish = extract_lines_with_lines_loose_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -830,77 +1103,101 @@ static void *extract_points_init(const MeshRenderData *mr, void *UNUSED(buf)) return elb; } -BLI_INLINE void vert_set_bmesh(GPUIndexBufBuilder *elb, BMVert *eve, int loop) +BLI_INLINE void vert_set_bm(GPUIndexBufBuilder *elb, BMVert *eve, int l_index) { - int vert_idx = BM_elem_index_get(eve); + const int v_index = BM_elem_index_get(eve); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - GPU_indexbuf_set_point_vert(elb, vert_idx, loop); + GPU_indexbuf_set_point_vert(elb, v_index, l_index); } else { - GPU_indexbuf_set_point_restart(elb, vert_idx); + GPU_indexbuf_set_point_restart(elb, v_index); } } BLI_INLINE void vert_set_mesh(GPUIndexBufBuilder *elb, const MeshRenderData *mr, - int vert_idx, - int loop) + const int v_index, + const int l_index) { - const MVert *mvert = &mr->mvert[vert_idx]; - if (!((mr->use_hide && (mvert->flag & ME_HIDE)) || + const MVert *mv = &mr->mvert[v_index]; + if (!((mr->use_hide && (mv->flag & ME_HIDE)) || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && - (mr->v_origindex[vert_idx] == ORIGINDEX_NONE)))) { - GPU_indexbuf_set_point_vert(elb, vert_idx, loop); + (mr->v_origindex[v_index] == ORIGINDEX_NONE)))) { + GPU_indexbuf_set_point_vert(elb, v_index, l_index); } else { - GPU_indexbuf_set_point_restart(elb, vert_idx); + GPU_indexbuf_set_point_restart(elb, v_index); } } -static void extract_points_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *elb) +static void extract_points_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *elb) { - vert_set_bmesh(elb, loop->v, l); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + vert_set_bm(elb, l->v, l_index); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_points_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *UNUSED(mpoly), - void *elb) +static void extract_points_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *elb) { - vert_set_mesh(elb, mr, mloop->v, l); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + vert_set_mesh(elb, mr, ml->v, ml_index); + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } -static void extract_points_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *elb) +static void extract_points_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *elb) { - vert_set_bmesh(elb, eed->v1, mr->loop_len + e * 2); - vert_set_bmesh(elb, eed->v2, mr->loop_len + e * 2 + 1); + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + vert_set_bm(elb, eed->v1, mr->loop_len + (ledge_index * 2)); + vert_set_bm(elb, eed->v2, mr->loop_len + (ledge_index * 2) + 1); + } + EXTRACT_LEDGE_FOREACH_BM_END; } -static void extract_points_ledge_mesh(const MeshRenderData *mr, - int e, - const MEdge *medge, - void *elb) +static void extract_points_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *elb) { - vert_set_mesh(elb, mr, medge->v1, mr->loop_len + e * 2); - vert_set_mesh(elb, mr, medge->v2, mr->loop_len + e * 2 + 1); + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + vert_set_mesh(elb, mr, med->v1, mr->loop_len + (ledge_index * 2)); + vert_set_mesh(elb, mr, med->v2, mr->loop_len + (ledge_index * 2) + 1); + } + EXTRACT_LEDGE_FOREACH_MESH_END; } -static void extract_points_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *elb) +static void extract_points_iter_lvert_bm(const MeshRenderData *mr, + const ExtractLVertBMesh_Params *params, + void *elb) { - vert_set_bmesh(elb, eve, mr->loop_len + mr->edge_loose_len * 2 + v); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params) + { + vert_set_bm(elb, eve, offset + lvert_index); + } + EXTRACT_LVERT_FOREACH_BM_END; } -static void extract_points_lvert_mesh(const MeshRenderData *mr, - int v, - const MVert *UNUSED(mvert), - void *elb) +static void extract_points_iter_lvert_mesh(const MeshRenderData *mr, + const ExtractLVertMesh_Params *params, + void *elb) { - vert_set_mesh(elb, mr, mr->lverts[v], mr->loop_len + mr->edge_loose_len * 2 + v); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr) + { + vert_set_mesh(elb, mr, mr->lverts[lvert_index], offset + lvert_index); + } + EXTRACT_LVERT_FOREACH_MESH_END; } static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb) @@ -910,18 +1207,16 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, v } static const MeshExtract extract_points = { - extract_points_init, - NULL, - NULL, - extract_points_loop_bmesh, - extract_points_loop_mesh, - extract_points_ledge_bmesh, - extract_points_ledge_mesh, - extract_points_lvert_bmesh, - extract_points_lvert_mesh, - extract_points_finish, - 0, - false, + .init = extract_points_init, + .iter_poly_bm = extract_points_iter_poly_bm, + .iter_poly_mesh = extract_points_iter_poly_mesh, + .iter_ledge_bm = extract_points_iter_ledge_bm, + .iter_ledge_mesh = extract_points_iter_ledge_mesh, + .iter_lvert_bm = extract_points_iter_lvert_bm, + .iter_lvert_mesh = extract_points_iter_lvert_mesh, + .finish = extract_points_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -937,34 +1232,51 @@ static void *extract_fdots_init(const MeshRenderData *mr, void *UNUSED(buf)) return elb; } -static void extract_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr), - int UNUSED(l), - BMLoop *loop, - void *elb) +static void extract_fdots_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *elb) { - int face_idx = BM_elem_index_get(loop->f); - if (!BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN)) { - GPU_indexbuf_set_point_vert(elb, face_idx, face_idx); - } - else { - GPU_indexbuf_set_point_restart(elb, face_idx); + EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) + { + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + GPU_indexbuf_set_point_vert(elb, f_index, f_index); + } + else { + GPU_indexbuf_set_point_restart(elb, f_index); + } } + EXTRACT_POLY_FOREACH_BM_END; } -static void extract_fdots_loop_mesh(const MeshRenderData *mr, - int UNUSED(l), - const MLoop *mloop, - int p, - const MPoly *mpoly, - void *elb) +static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *elb) { - const MVert *mvert = &mr->mvert[mloop->v]; - if ((!mr->use_subsurf_fdots || (mvert->flag & ME_VERT_FACEDOT)) && - !(mr->use_hide && (mpoly->flag & ME_HIDE))) { - GPU_indexbuf_set_point_vert(elb, p, p); + if (mr->use_subsurf_fdots) { + /* Check #ME_VERT_FACEDOT. */ + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const MVert *mv = &mr->mvert[ml->v]; + if ((mv->flag & ME_VERT_FACEDOT) && !(mr->use_hide && (mp->flag & ME_HIDE))) { + GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); + } + else { + GPU_indexbuf_set_point_restart(elb, mp_index); + } + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } else { - GPU_indexbuf_set_point_restart(elb, p); + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); + } + else { + GPU_indexbuf_set_point_restart(elb, mp_index); + } + } + EXTRACT_POLY_FOREACH_MESH_END; } } @@ -975,18 +1287,12 @@ static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo } static const MeshExtract extract_fdots = { - extract_fdots_init, - NULL, - NULL, - extract_fdots_loop_bmesh, - extract_fdots_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_fdots_finish, - 0, - false, + .init = extract_fdots_init, + .iter_poly_bm = extract_fdots_iter_poly_bm, + .iter_poly_mesh = extract_fdots_iter_poly_mesh, + .finish = extract_fdots_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1009,66 +1315,60 @@ static void *extract_lines_paint_mask_init(const MeshRenderData *mr, void *UNUSE return data; } -static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *mpoly, - void *_data) -{ - MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data; - const int edge_idx = mloop->e; - const MEdge *medge = &mr->medge[edge_idx]; - if (!((mr->use_hide && (medge->flag & ME_HIDE)) || - ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && - (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) { - - int loopend = mpoly->totloop + mpoly->loopstart - 1; - int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1); - if (mpoly->flag & ME_FACE_SEL) { - if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, edge_idx)) { - /* Hide edge as it has more than 2 selected loop. */ - GPU_indexbuf_set_line_restart(&data->elb, edge_idx); +static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) +{ + MeshExtract_LinePaintMask_Data *data = _data; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const int e_index = ml->e; + const MEdge *me = &mr->medge[e_index]; + if (!((mr->use_hide && (me->flag & ME_HIDE)) || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && + (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { + + const int ml_index_last = mp->totloop + mp->loopstart - 1; + const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); + if (mp->flag & ME_FACE_SEL) { + if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, e_index)) { + /* Hide edge as it has more than 2 selected loop. */ + GPU_indexbuf_set_line_restart(&data->elb, e_index); + } + else { + /* First selected loop. Set edge visible, overwriting any unselected loop. */ + GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other); + } } else { - /* First selected loop. Set edge visible, overwritting any unsel loop. */ - GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop); + /* Set theses unselected loop only if this edge has no other selected loop. */ + if (!BLI_BITMAP_TEST(data->select_map, e_index)) { + GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other); + } } } else { - /* Set theses unselected loop only if this edge has no other selected loop. */ - if (!BLI_BITMAP_TEST(data->select_map, edge_idx)) { - GPU_indexbuf_set_line_verts(&data->elb, edge_idx, l, other_loop); - } + GPU_indexbuf_set_line_restart(&data->elb, e_index); } } - else { - GPU_indexbuf_set_line_restart(&data->elb, edge_idx); - } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *_data) { - MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data; + MeshExtract_LinePaintMask_Data *data = _data; GPU_indexbuf_build_in_place(&data->elb, ibo); MEM_freeN(data); } static const MeshExtract extract_lines_paint_mask = { - extract_lines_paint_mask_init, - NULL, - NULL, - NULL, - extract_lines_paint_mask_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_lines_paint_mask_finish, - 0, - false, + .init = extract_lines_paint_mask_init, + .iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh, + .finish = extract_lines_paint_mask_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1090,7 +1390,7 @@ typedef struct MeshExtract_LineAdjacency_Data { static void *extract_lines_adjacency_init(const MeshRenderData *mr, void *UNUSED(buf)) { /* Similar to poly_to_tri_count(). - * There is always loop + tri - 1 edges inside a polygon. + * There is always (loop + triangle - 1) edges inside a polygon. * Accumulate for all polys and you get : */ uint tess_edge_len = mr->loop_len + mr->tri_len - mr->poly_len; @@ -1107,7 +1407,7 @@ BLI_INLINE void lines_adjacency_triangle( uint v1, uint v2, uint v3, uint l1, uint l2, uint l3, MeshExtract_LineAdjacency_Data *data) { GPUIndexBufBuilder *elb = &data->elb; - /* Iter around the triangle's edges. */ + /* Iterate around the triangle's edges. */ for (int e = 0; e < 3; e++) { SHIFT3(uint, v3, v2, v1); SHIFT3(uint, l3, l2, l1); @@ -1118,7 +1418,7 @@ BLI_INLINE void lines_adjacency_triangle( int v_data = POINTER_AS_INT(*pval); if (!value_is_init || v_data == NO_EDGE) { /* Save the winding order inside the sign bit. Because the - * edgehash sort the keys and we need to compare winding later. */ + * Edge-hash sort the keys and we need to compare winding later. */ int value = (int)l1 + 1; /* 0 cannot be signed so add one. */ *pval = POINTER_FROM_INT((inv_indices) ? -value : value); /* Store loop indices for remaining non-manifold edges. */ @@ -1130,7 +1430,7 @@ BLI_INLINE void lines_adjacency_triangle( *pval = POINTER_FROM_INT(NO_EDGE); bool inv_opposite = (v_data < 0); uint l_opposite = (uint)abs(v_data) - 1; - /* TODO Make this part threadsafe. */ + /* TODO Make this part thread-safe. */ if (inv_opposite == inv_indices) { /* Don't share edge if triangles have non matching winding. */ GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l1); @@ -1144,42 +1444,48 @@ BLI_INLINE void lines_adjacency_triangle( } } -static void extract_lines_adjacency_looptri_bmesh(const MeshRenderData *UNUSED(mr), - int UNUSED(t), - BMLoop **elt, - void *data) +static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData *UNUSED(mr), + const struct ExtractTriBMesh_Params *params, + void *data) { - if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { - lines_adjacency_triangle(BM_elem_index_get(elt[0]->v), - BM_elem_index_get(elt[1]->v), - BM_elem_index_get(elt[2]->v), - BM_elem_index_get(elt[0]), - BM_elem_index_get(elt[1]), - BM_elem_index_get(elt[2]), - data); + EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params) + { + if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { + lines_adjacency_triangle(BM_elem_index_get(elt[0]->v), + BM_elem_index_get(elt[1]->v), + BM_elem_index_get(elt[2]->v), + BM_elem_index_get(elt[0]), + BM_elem_index_get(elt[1]), + BM_elem_index_get(elt[2]), + data); + } } + EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; } -static void extract_lines_adjacency_looptri_mesh(const MeshRenderData *mr, - int UNUSED(t), - const MLoopTri *mlt, - void *data) +static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr, + const struct ExtractTriMesh_Params *params, + void *data) { - const MPoly *mpoly = &mr->mpoly[mlt->poly]; - if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) { - lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v, - mr->mloop[mlt->tri[1]].v, - mr->mloop[mlt->tri[2]].v, - mlt->tri[0], - mlt->tri[1], - mlt->tri[2], - data); + EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params) + { + const MPoly *mp = &mr->mpoly[mlt->poly]; + if (!(mr->use_hide && (mp->flag & ME_HIDE))) { + lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v, + mr->mloop[mlt->tri[1]].v, + mr->mloop[mlt->tri[2]].v, + mlt->tri[0], + mlt->tri[1], + mlt->tri[2], + data); + } } + EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; } static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo, void *_data) { - MeshExtract_LineAdjacency_Data *data = (MeshExtract_LineAdjacency_Data *)_data; + MeshExtract_LineAdjacency_Data *data = _data; /* Create edges for remaining non manifold edges. */ EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh); for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { @@ -1209,18 +1515,12 @@ static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo, #undef NO_EDGE static const MeshExtract extract_lines_adjacency = { - extract_lines_adjacency_init, - extract_lines_adjacency_looptri_bmesh, - extract_lines_adjacency_looptri_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_lines_adjacency_finish, - 0, - false, + .init = extract_lines_adjacency_init, + .iter_looptri_bm = extract_lines_adjacency_iter_looptri_bm, + .iter_looptri_mesh = extract_lines_adjacency_iter_looptri_mesh, + .finish = extract_lines_adjacency_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1250,53 +1550,53 @@ BLI_INLINE void edituv_tri_add( } } -static void extract_edituv_tris_looptri_bmesh(const MeshRenderData *UNUSED(mr), - int UNUSED(t), - BMLoop **elt, - void *data) +static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData *UNUSED(mr), + const struct ExtractTriBMesh_Params *params, + void *data) { - edituv_tri_add(data, - BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN), - BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT), - BM_elem_index_get(elt[0]), - BM_elem_index_get(elt[1]), - BM_elem_index_get(elt[2])); + EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params) + { + edituv_tri_add(data, + BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN), + BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT), + BM_elem_index_get(elt[0]), + BM_elem_index_get(elt[1]), + BM_elem_index_get(elt[2])); + } + EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; } -static void extract_edituv_tris_looptri_mesh(const MeshRenderData *mr, - int UNUSED(t), - const MLoopTri *mlt, - void *data) +static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr, + const struct ExtractTriMesh_Params *params, + void *data) { - const MPoly *mpoly = &mr->mpoly[mlt->poly]; - edituv_tri_add(data, - (mpoly->flag & ME_HIDE) != 0, - (mpoly->flag & ME_FACE_SEL) != 0, - mlt->tri[0], - mlt->tri[1], - mlt->tri[2]); + EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params) + { + const MPoly *mp = &mr->mpoly[mlt->poly]; + edituv_tri_add(data, + (mp->flag & ME_HIDE) != 0, + (mp->flag & ME_FACE_SEL) != 0, + mlt->tri[0], + mlt->tri[1], + mlt->tri[2]); + } + EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; } static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data) { - MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data; + MeshExtract_EditUvElem_Data *extract_data = data; GPU_indexbuf_build_in_place(&extract_data->elb, ibo); MEM_freeN(extract_data); } static const MeshExtract extract_edituv_tris = { - extract_edituv_tris_init, - extract_edituv_tris_looptri_bmesh, - extract_edituv_tris_looptri_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_edituv_tris_finish, - 0, - false, + .init = extract_edituv_tris_init, + .iter_looptri_bm = extract_edituv_tris_iter_looptri_bm, + .iter_looptri_mesh = extract_edituv_tris_iter_looptri_mesh, + .finish = extract_edituv_tris_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1322,55 +1622,53 @@ BLI_INLINE void edituv_edge_add( } } -static void extract_edituv_lines_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *data) +static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - edituv_edge_add(data, - BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN), - BM_elem_flag_test(loop->f, BM_ELEM_SELECT), - l, - BM_elem_index_get(loop->next)); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr) + { + edituv_edge_add(data, + BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN), + BM_elem_flag_test(loop->f, BM_ELEM_SELECT), + l_index, + BM_elem_index_get(loop->next)); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop); } -static void extract_edituv_lines_loop_mesh(const MeshRenderData *mr, - int loop_idx, - const MLoop *mloop, - int UNUSED(p), - const MPoly *mpoly, - void *data) +static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - int loopend = mpoly->totloop + mpoly->loopstart - 1; - int loop_next_idx = (loop_idx == loopend) ? mpoly->loopstart : (loop_idx + 1); - const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[mloop->e] != ORIGINDEX_NONE); - edituv_edge_add(data, - (mpoly->flag & ME_HIDE) != 0 || !real_edge, - (mpoly->flag & ME_FACE_SEL) != 0, - loop_idx, - loop_next_idx); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const int ml_index_last = mp->totloop + mp->loopstart - 1; + const int ml_index_next = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); + const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[ml->e] != ORIGINDEX_NONE); + edituv_edge_add(data, + (mp->flag & ME_HIDE) != 0 || !real_edge, + (mp->flag & ME_FACE_SEL) != 0, + ml_index, + ml_index_next); + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data) { - MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data; + MeshExtract_EditUvElem_Data *extract_data = data; GPU_indexbuf_build_in_place(&extract_data->elb, ibo); MEM_freeN(extract_data); } static const MeshExtract extract_edituv_lines = { - extract_edituv_lines_init, - NULL, - NULL, - extract_edituv_lines_loop_bmesh, - extract_edituv_lines_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_lines_finish, - 0, - false, + .init = extract_edituv_lines_init, + .iter_poly_bm = extract_edituv_lines_iter_poly_bm, + .iter_poly_mesh = extract_edituv_lines_iter_poly_mesh, + .finish = extract_edituv_lines_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1398,50 +1696,48 @@ BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data, } } -static void extract_edituv_points_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *data) +static void extract_edituv_points_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - edituv_point_add(data, - BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN), - BM_elem_flag_test(loop->f, BM_ELEM_SELECT), - l); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + edituv_point_add(data, + BM_elem_flag_test(l->f, BM_ELEM_HIDDEN), + BM_elem_flag_test(l->f, BM_ELEM_SELECT), + l_index); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_edituv_points_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *mpoly, - void *data) +static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && - mr->v_origindex[mloop->v] != ORIGINDEX_NONE); - edituv_point_add( - data, ((mpoly->flag & ME_HIDE) != 0) || !real_vert, (mpoly->flag & ME_FACE_SEL) != 0, l); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && + mr->v_origindex[ml->v] != ORIGINDEX_NONE); + edituv_point_add( + data, ((mp->flag & ME_HIDE) != 0) || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index); + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *data) { - MeshExtract_EditUvElem_Data *extract_data = (MeshExtract_EditUvElem_Data *)data; + MeshExtract_EditUvElem_Data *extract_data = data; GPU_indexbuf_build_in_place(&extract_data->elb, ibo); MEM_freeN(extract_data); } static const MeshExtract extract_edituv_points = { - extract_edituv_points_init, - NULL, - NULL, - extract_edituv_points_loop_bmesh, - extract_edituv_points_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_points_finish, - 0, - false, + .init = extract_edituv_points_init, + .iter_poly_bm = extract_edituv_points_iter_poly_bm, + .iter_poly_mesh = extract_edituv_points_iter_poly_mesh, + .finish = extract_edituv_points_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1462,64 +1758,75 @@ static void *extract_edituv_fdots_init(const MeshRenderData *mr, void *UNUSED(ib BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, - int face_idx) + int face_index) { if (!hidden && (data->sync_selection || selected)) { - GPU_indexbuf_set_point_vert(&data->elb, face_idx, face_idx); + GPU_indexbuf_set_point_vert(&data->elb, face_index, face_index); } else { - GPU_indexbuf_set_point_restart(&data->elb, face_idx); + GPU_indexbuf_set_point_restart(&data->elb, face_index); } } -static void extract_edituv_fdots_loop_bmesh(const MeshRenderData *UNUSED(mr), - int UNUSED(l), - BMLoop *loop, - void *data) +static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - edituv_facedot_add(data, - BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN), - BM_elem_flag_test(loop->f, BM_ELEM_SELECT), - BM_elem_index_get(loop->f)); + EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) + { + edituv_facedot_add( + data, BM_elem_flag_test(f, BM_ELEM_HIDDEN), BM_elem_flag_test(f, BM_ELEM_SELECT), f_index); + } + EXTRACT_POLY_FOREACH_BM_END; } -static void extract_edituv_fdots_loop_mesh(const MeshRenderData *mr, - int UNUSED(l), - const MLoop *mloop, - int p, - const MPoly *mpoly, - void *data) +static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && - mr->p_origindex[p] != ORIGINDEX_NONE); - const bool subd_fdot = (!mr->use_subsurf_fdots || - (mr->mvert[mloop->v].flag & ME_VERT_FACEDOT) != 0); - edituv_facedot_add(data, - ((mpoly->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot, - (mpoly->flag & ME_FACE_SEL) != 0, - p); + if (mr->use_subsurf_fdots) { + /* Check #ME_VERT_FACEDOT. */ + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && + mr->p_origindex[mp_index] != ORIGINDEX_NONE); + const bool subd_fdot = (!mr->use_subsurf_fdots || + (mr->mvert[ml->v].flag & ME_VERT_FACEDOT) != 0); + edituv_facedot_add(data, + ((mp->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot, + (mp->flag & ME_FACE_SEL) != 0, + mp_index); + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; + } + else { + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && + mr->p_origindex[mp_index] != ORIGINDEX_NONE); + edituv_facedot_add(data, + ((mp->flag & ME_HIDE) != 0) || !real_fdot, + (mp->flag & ME_FACE_SEL) != 0, + mp_index); + } + EXTRACT_POLY_FOREACH_MESH_END; + } } static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *_data) { - MeshExtract_EditUvElem_Data *data = (MeshExtract_EditUvElem_Data *)_data; + MeshExtract_EditUvElem_Data *data = _data; GPU_indexbuf_build_in_place(&data->elb, ibo); MEM_freeN(data); } static const MeshExtract extract_edituv_fdots = { - extract_edituv_fdots_init, - NULL, - NULL, - extract_edituv_fdots_loop_bmesh, - extract_edituv_fdots_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_fdots_finish, - 0, - false, + .init = extract_edituv_fdots_init, + .iter_poly_bm = extract_edituv_fdots_iter_poly_bm, + .iter_poly_mesh = extract_edituv_fdots_iter_poly_mesh, + .finish = extract_edituv_fdots_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1542,7 +1849,7 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { - /* WARNING Adjust PosNorLoop struct accordingly. */ + /* WARNING Adjust #PosNorLoop struct accordingly. */ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); GPU_vertformat_alias_add(&format, "vnor"); @@ -1566,95 +1873,122 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf) } } else { - const MVert *mvert = mr->mvert; - for (int v = 0; v < mr->vert_len; v++, mvert++) { - data->packed_nor[v] = GPU_normal_convert_i10_s3(mvert->no); + const MVert *mv = mr->mvert; + for (int v = 0; v < mr->vert_len; v++, mv++) { + data->packed_nor[v] = GPU_normal_convert_i10_s3(mv->no); } } return data; } -static void extract_pos_nor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data) +static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { MeshExtract_PosNor_Data *data = _data; - PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert->pos, bm_vert_co_get(mr, loop->v)); - vert->nor = data->packed_nor[BM_elem_index_get(loop->v)]; - BMFace *efa = loop->f; - vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + PosNorLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v)); + vert->nor = data->packed_nor[BM_elem_index_get(l->v)]; + BMFace *efa = l->f; + vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_pos_nor_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *mpoly, - void *_data) +static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) { MeshExtract_PosNor_Data *data = _data; - PosNorLoop *vert = data->vbo_data + l; - const MVert *mvert = &mr->mvert[mloop->v]; - copy_v3_v3(vert->pos, mvert->co); - vert->nor = data->packed_nor[mloop->v]; - /* Flag for paint mode overlay. */ - if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE || - ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && - (mr->v_origindex[mloop->v] == ORIGINDEX_NONE))) { - vert->nor.w = -1; - } - else if (mvert->flag & SELECT) { - vert->nor.w = 1; - } - else { - vert->nor.w = 0; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + PosNorLoop *vert = &data->vbo_data[ml_index]; + const MVert *mv = &mr->mvert[ml->v]; + copy_v3_v3(vert->pos, mv->co); + vert->nor = data->packed_nor[ml->v]; + /* Flag for paint mode overlay. */ + if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && + (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { + vert->nor.w = -1; + } + else if (mv->flag & SELECT) { + vert->nor.w = 1; + } + else { + vert->nor.w = 0; + } } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } -static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *_data) +static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *_data) { - int l = mr->loop_len + e * 2; MeshExtract_PosNor_Data *data = _data; - PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); - copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); - vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)]; - vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)]; + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + int l_index = mr->loop_len + ledge_index * 2; + PosNorLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); + copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); + vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)]; + vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)]; + } + EXTRACT_LEDGE_FOREACH_BM_END; } -static void extract_pos_nor_ledge_mesh(const MeshRenderData *mr, - int e, - const MEdge *medge, - void *_data) +static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *_data) { - int l = mr->loop_len + e * 2; MeshExtract_PosNor_Data *data = _data; - PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert[0].pos, mr->mvert[medge->v1].co); - copy_v3_v3(vert[1].pos, mr->mvert[medge->v2].co); - vert[0].nor = data->packed_nor[medge->v1]; - vert[1].nor = data->packed_nor[medge->v2]; + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + const int ml_index = mr->loop_len + ledge_index * 2; + PosNorLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); + copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); + vert[0].nor = data->packed_nor[med->v1]; + vert[1].nor = data->packed_nor[med->v2]; + } + EXTRACT_LEDGE_FOREACH_MESH_END; } -static void extract_pos_nor_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *_data) +static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr, + const ExtractLVertBMesh_Params *params, + void *_data) { - int l = mr->loop_len + mr->edge_loose_len * 2 + v; MeshExtract_PosNor_Data *data = _data; - PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); - vert->nor = data->packed_nor[BM_elem_index_get(eve)]; + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params) + { + const int l_index = offset + lvert_index; + PosNorLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); + vert->nor = data->packed_nor[BM_elem_index_get(eve)]; + } + EXTRACT_LVERT_FOREACH_BM_END; } -static void extract_pos_nor_lvert_mesh(const MeshRenderData *mr, - int v, - const MVert *mvert, - void *_data) +static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, + const ExtractLVertMesh_Params *params, + void *_data) { - int l = mr->loop_len + mr->edge_loose_len * 2 + v; - int v_idx = mr->lverts[v]; MeshExtract_PosNor_Data *data = _data; - PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert->pos, mvert->co); - vert->nor = data->packed_nor[v_idx]; + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr) + { + const int ml_index = offset + lvert_index; + const int v_index = mr->lverts[lvert_index]; + PosNorLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert->pos, mv->co); + vert->nor = data->packed_nor[v_index]; + } + EXTRACT_LVERT_FOREACH_MESH_END; } static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(vbo), void *data) @@ -1663,18 +1997,16 @@ static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSE } static const MeshExtract extract_pos_nor = { - extract_pos_nor_init, - NULL, - NULL, - extract_pos_nor_loop_bmesh, - extract_pos_nor_loop_mesh, - extract_pos_nor_ledge_bmesh, - extract_pos_nor_ledge_mesh, - extract_pos_nor_lvert_bmesh, - extract_pos_nor_lvert_mesh, - extract_pos_nor_finish, - 0, - true, + .init = extract_pos_nor_init, + .iter_poly_bm = extract_pos_nor_iter_poly_bm, + .iter_poly_mesh = extract_pos_nor_iter_poly_mesh, + .iter_ledge_bm = extract_pos_nor_iter_ledge_bm, + .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh, + .iter_lvert_bm = extract_pos_nor_iter_lvert_bm, + .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh, + .finish = extract_pos_nor_finish, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -1700,62 +2032,71 @@ static void *extract_lnor_hq_init(const MeshRenderData *mr, void *buf) return vbo->data; } -static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data) +static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { if (mr->loop_normals) { - normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]); - } - else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) { - normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_vert_no_get(mr, loop->v)); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(_l, l_index, params, mr) + { + normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, mr->loop_normals[l_index]); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(_l); } else { - normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_face_no_get(mr, loop->f)); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH)) { + normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_vert_no_get(mr, l->v)); + } + else { + normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, l->f)); + } + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } } -static void extract_lnor_hq_loop_mesh( - const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data) +static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - gpuHQNor *lnor_data = &((gpuHQNor *)data)[l]; - if (mr->loop_normals) { - normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[l]); - } - else if (mpoly->flag & ME_SMOOTH) { - copy_v3_v3_short(&lnor_data->x, mr->mvert[mloop->v].no); - } - else { - normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[p]); - } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + gpuHQNor *lnor_data = &((gpuHQNor *)data)[ml_index]; + if (mr->loop_normals) { + normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); + } + else if (mp->flag & ME_SMOOTH) { + copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no); + } + else { + normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]); + } - /* Flag for paint mode overlay. - * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In - * paint mode it will use the unmapped data to draw the wireframe. */ - if (mpoly->flag & ME_HIDE || - (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && - mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) { - lnor_data->w = -1; - } - else if (mpoly->flag & ME_FACE_SEL) { - lnor_data->w = 1; - } - else { - lnor_data->w = 0; + /* Flag for paint mode overlay. + * Only use #MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. + * In paint mode it will use the un-mapped data to draw the wire-frame. */ + if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && + (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + lnor_data->w = -1; + } + else if (mp->flag & ME_FACE_SEL) { + lnor_data->w = 1; + } + else { + lnor_data->w = 0; + } } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static const MeshExtract extract_lnor_hq = { - extract_lnor_hq_init, - NULL, - NULL, - extract_lnor_hq_loop_bmesh, - extract_lnor_hq_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - MR_DATA_LOOP_NOR, - true, + .init = extract_lnor_hq_init, + .iter_poly_bm = extract_lnor_hq_iter_poly_bm, + .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh, + .data_flag = MR_DATA_LOOP_NOR, + .use_threading = true, }; /** \} */ @@ -1777,64 +2118,75 @@ static void *extract_lnor_init(const MeshRenderData *mr, void *buf) return vbo->data; } -static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data) +static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { if (mr->loop_normals) { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]); - } - else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v)); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); + BMFace *efa = l->f; + ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } else { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, loop->f)); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH)) { + ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, l->v)); + } + else { + ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, l->f)); + } + BMFace *efa = l->f; + ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } - BMFace *efa = loop->f; - ((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; } -static void extract_lnor_loop_mesh( - const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data) +static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[l]; - if (mr->loop_normals) { - *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[l]); - } - else if (mpoly->flag & ME_SMOOTH) { - *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no); - } - else { - *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[p]); - } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[ml_index]; + if (mr->loop_normals) { + *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); + } + else if (mp->flag & ME_SMOOTH) { + *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no); + } + else { + *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]); + } - /* Flag for paint mode overlay. - * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In - * paint mode it will use the unmapped data to draw the wireframe. */ - if (mpoly->flag & ME_HIDE || - (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && - mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) { - lnor_data->w = -1; - } - else if (mpoly->flag & ME_FACE_SEL) { - lnor_data->w = 1; - } - else { - lnor_data->w = 0; + /* Flag for paint mode overlay. + * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. + * In paint mode it will use the un-mapped data to draw the wire-frame. */ + if (mp->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && + (mr->v_origindex) && mr->v_origindex[ml->v] == ORIGINDEX_NONE)) { + lnor_data->w = -1; + } + else if (mp->flag & ME_FACE_SEL) { + lnor_data->w = 1; + } + else { + lnor_data->w = 0; + } } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static const MeshExtract extract_lnor = { - extract_lnor_init, - NULL, - NULL, - extract_lnor_loop_bmesh, - extract_lnor_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - MR_DATA_LOOP_NOR, - true, + .init = extract_lnor_init, + .iter_poly_bm = extract_lnor_iter_poly_bm, + .iter_poly_mesh = extract_lnor_iter_poly_mesh, + .data_flag = MR_DATA_LOOP_NOR, + .use_threading = true, }; /** \} */ @@ -1878,7 +2230,7 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf) /* Active display layer name. */ if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) { GPU_vertformat_alias_add(&format, "au"); - /* Alias to pos for edit uvs. */ + /* Alias to `pos` for edit uvs. */ GPU_vertformat_alias_add(&format, "pos"); } /* Stencil mask uv layer name. */ @@ -1904,20 +2256,21 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf) if (uv_layers & (1 << i)) { if (mr->extract_type == MR_EXTRACT_BMESH) { int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i); - BMIter f_iter, l_iter; + BMIter f_iter; BMFace *efa; - BMLoop *loop; BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs); memcpy(uv_data, luv->uv, sizeof(*uv_data)); uv_data++; - } + } while ((l_iter = l_iter->next) != l_first); } } else { MLoopUV *layer_data = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i); - for (int l = 0; l < mr->loop_len; l++, uv_data++, layer_data++) { + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) { memcpy(uv_data, layer_data->uv, sizeof(*uv_data)); } } @@ -1928,18 +2281,9 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf) } static const MeshExtract extract_uv = { - extract_uv_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - false, + .init = extract_uv_init, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -1987,7 +2331,7 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool } } if (use_orco_tan && orco == NULL) { - /* If orco is not available compute it ourselves */ + /* If `orco` is not available compute it ourselves */ orco_allocated = true; orco = MEM_mallocN(sizeof(*orco) * mr->vert_len, __func__); @@ -2001,17 +2345,18 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool } } else { - const MVert *mvert = mr->mvert; - for (int v = 0; v < mr->vert_len; v++, mvert++) { - copy_v3_v3(orco[v], mvert->co); + const MVert *mv = mr->mvert; + for (int v = 0; v < mr->vert_len; v++, mv++) { + copy_v3_v3(orco[v], mv->co); } } BKE_mesh_orco_verts_transform(mr->me, orco, mr->vert_len, 0); } /* Start Fresh */ - CustomData_free_layers(cd_ldata, CD_TANGENT, mr->loop_len); - + CustomData loop_data; + CustomData_reset(&loop_data); + CustomData *ldata = cd_ldata; if (tan_len != 0 || use_orco_tan) { short tangent_mask = 0; bool calc_active_tangent = false; @@ -2041,9 +2386,10 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool mr->poly_normals, mr->loop_normals, orco, - cd_ldata, + &loop_data, mr->loop_len, &tangent_mask); + ldata = &loop_data; } } @@ -2075,18 +2421,18 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool short(*tan_data)[4] = (short(*)[4])vbo->data; for (int i = 0; i < tan_len; i++) { const char *name = tangent_names[i]; - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(cd_ldata, CD_TANGENT, name); - for (int l = 0; l < mr->loop_len; l++) { - normal_float_to_short_v3(*tan_data, layer_data[l]); - (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + normal_float_to_short_v3(*tan_data, layer_data[ml_index]); + (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; tan_data++; } } if (use_orco_tan) { - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(cd_ldata, CD_TANGENT, 0); - for (int l = 0; l < mr->loop_len; l++) { - normal_float_to_short_v3(*tan_data, layer_data[l]); - (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + normal_float_to_short_v3(*tan_data, layer_data[ml_index]); + (*tan_data)[3] = (layer_data[ml_index][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; tan_data++; } } @@ -2095,24 +2441,25 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool GPUPackedNormal *tan_data = (GPUPackedNormal *)vbo->data; for (int i = 0; i < tan_len; i++) { const char *name = tangent_names[i]; - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(cd_ldata, CD_TANGENT, name); - for (int l = 0; l < mr->loop_len; l++) { - *tan_data = GPU_normal_convert_i10_v3(layer_data[l]); - tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(ldata, CD_TANGENT, name); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]); + tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2; tan_data++; } } if (use_orco_tan) { - float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(cd_ldata, CD_TANGENT, 0); - for (int l = 0; l < mr->loop_len; l++) { - *tan_data = GPU_normal_convert_i10_v3(layer_data[l]); - tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(ldata, CD_TANGENT, 0); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++) { + *tan_data = GPU_normal_convert_i10_v3(layer_data[ml_index]); + tan_data->w = (layer_data[ml_index][3] > 0.0f) ? 1 : -2; tan_data++; } } } - CustomData_free_layers(cd_ldata, CD_TANGENT, mr->loop_len); + CustomData_free_layers(ldata, CD_TANGENT, mr->loop_len); + CustomData_free(&loop_data, mr->loop_len); } static void *extract_tan_init(const MeshRenderData *mr, void *buf) @@ -2122,18 +2469,9 @@ static void *extract_tan_init(const MeshRenderData *mr, void *buf) } static const MeshExtract extract_tan = { - extract_tan_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, - false, + .init = extract_tan_init, + .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + .use_threading = false, }; /** \} */ @@ -2149,18 +2487,9 @@ static void *extract_tan_hq_init(const MeshRenderData *mr, void *buf) } static const MeshExtract extract_tan_hq = { - extract_tan_hq_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, - false, + .init = extract_tan_hq_init, + .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + .use_threading = false, }; /** \} */ @@ -2175,7 +2504,9 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) GPU_vertformat_deinterleave(&format); CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; + CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; uint32_t vcol_layers = mr->cache->cd_used.vcol; + uint32_t svcol_layers = mr->cache->cd_used.sculpt_vcol; for (int i = 0; i < MAX_MCOL; i++) { if (vcol_layers & (1 << i)) { @@ -2192,14 +2523,42 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) { GPU_vertformat_alias_add(&format, "ac"); } + /* Gather number of auto layers. */ - /* We only do vcols that are not overridden by uvs */ + /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 && + CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) { + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); + GPU_vertformat_alias_add(&format, attr_name); + } + } + } + + /* Sculpt Vertex Colors */ + for (int i = 0; i < 8; i++) { + if (svcol_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + + BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "c"); + } + if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "ac"); + } + /* Gather number of auto layers. */ + /* We only do `vcols` that are not overridden by `uvs`. */ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); GPU_vertformat_alias_add(&format, attr_name); } } } + GPUVertBuf *vbo = buf; GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->loop_len); @@ -2209,27 +2568,30 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) } gpuMeshVcol; gpuMeshVcol *vcol_data = (gpuMeshVcol *)vbo->data; + MLoop *loops = CustomData_get_layer(cd_ldata, CD_MLOOP); + for (int i = 0; i < MAX_MCOL; i++) { if (vcol_layers & (1 << i)) { if (mr->extract_type == MR_EXTRACT_BMESH) { int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i); - BMIter f_iter, l_iter; + BMIter f_iter; BMFace *efa; - BMLoop *loop; BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) { - const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs); vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); vcol_data++; - } + } while ((l_iter = l_iter->next) != l_first); } } else { const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i); - for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) { + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, mloopcol++, vcol_data++) { vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); @@ -2237,22 +2599,45 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) } } } + + if (svcol_layers & (1 << i)) { + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i); + BMIter f_iter; + BMFace *efa; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const MPropCol *prop_col = BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs); + vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]); + vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]); + vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]); + vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]); + vcol_data++; + } while ((l_iter = l_iter->next) != l_first); + } + } + else { + MPropCol *vcol = CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i); + for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) { + vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]); + vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]); + vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]); + vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]); + } + } + + vcol_data += mr->loop_len; + } } return NULL; } static const MeshExtract extract_vcol = { - extract_vcol_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - false, + .init = extract_vcol_init, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -2271,7 +2656,7 @@ static void *extract_orco_init(const MeshRenderData *mr, void *buf) static GPUVertFormat format = {0}; if (format.attr_len == 0) { /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex - * attributes. This is a substantial waste of Vram and should be done another way. + * attributes. This is a substantial waste of video-ram and should be done another way. * Unfortunately, at the time of writing, I did not found any other "non disruptive" * alternative. */ GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); @@ -2286,33 +2671,37 @@ static void *extract_orco_init(const MeshRenderData *mr, void *buf) MeshExtract_Orco_Data *data = MEM_mallocN(sizeof(*data), __func__); data->vbo_data = (float(*)[4])vbo->data; data->orco = CustomData_get_layer(cd_vdata, CD_ORCO); - /* Make sure orco layer was requested only if needed! */ + /* Make sure `orco` layer was requested only if needed! */ BLI_assert(data->orco); return data; } -static void extract_orco_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *data) +static void extract_orco_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; - float *loop_orco = orco_data->vbo_data[l]; - copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]); - loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr) + { + float *loop_orco = orco_data->vbo_data[l_index]; + copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]); + loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop); } -static void extract_orco_loop_mesh(const MeshRenderData *UNUSED(mr), - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *UNUSED(mpoly), - void *data) +static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; - float *loop_orco = orco_data->vbo_data[l]; - copy_v3_v3(loop_orco, orco_data->orco[mloop->v]); - loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; + float *loop_orco = orco_data->vbo_data[ml_index]; + copy_v3_v3(loop_orco, orco_data->orco[ml->v]); + loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data) @@ -2321,18 +2710,12 @@ static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(b } static const MeshExtract extract_orco = { - extract_orco_init, - NULL, - NULL, - extract_orco_loop_bmesh, - extract_orco_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_orco_finish, - 0, - true, + .init = extract_orco_init, + .iter_poly_bm = extract_orco_iter_poly_bm, + .iter_poly_mesh = extract_orco_iter_poly_mesh, + .finish = extract_orco_finish, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -2359,7 +2742,7 @@ static float loop_edge_factor_get(const float f_no[3], cross_v3_v3v3(enor, v_no, evec); normalize_v3(enor); float d = fabsf(dot_v3v3(enor, f_no)); - /* Rescale to the slider range. */ + /* Re-scale to the slider range. */ d *= (1.0f / 0.065f); CLAMP(d, 0.0f, 1.0f); return d; @@ -2383,9 +2766,9 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf) /* HACK(fclem) Detecting the need for edge render. * We could have a flag in the mesh instead or check the modifier stack. */ - const MEdge *medge = mr->medge; - for (int e = 0; e < mr->edge_len; e++, medge++) { - if ((medge->flag & ME_EDGERENDER) == 0) { + const MEdge *med = mr->medge; + for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) { + if ((med->flag & ME_EDGERENDER) == 0) { data->use_edge_render = true; break; } @@ -2401,81 +2784,103 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_edge_fac_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data) +static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { - MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; - if (BM_edge_is_manifold(loop->e)) { - float ratio = loop_edge_factor_get(bm_face_no_get(mr, loop->f), - bm_vert_co_get(mr, loop->v), - bm_vert_no_get(mr, loop->v), - bm_vert_co_get(mr, loop->next->v)); - data->vbo_data[l] = ratio * 253 + 1; - } - else { - data->vbo_data[l] = 255; + MeshExtract_EdgeFac_Data *data = _data; + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + if (BM_edge_is_manifold(l->e)) { + float ratio = loop_edge_factor_get(bm_face_no_get(mr, l->f), + bm_vert_co_get(mr, l->v), + bm_vert_no_get(mr, l->v), + bm_vert_co_get(mr, l->next->v)); + data->vbo_data[l_index] = ratio * 253 + 1; + } + else { + data->vbo_data[l_index] = 255; + } } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_edge_fac_loop_mesh( - const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data) +static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) { MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; + if (data->use_edge_render) { - const MEdge *medge = &mr->medge[mloop->e]; - data->vbo_data[l] = (medge->flag & ME_EDGERENDER) ? 255 : 0; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const MEdge *med = &mr->medge[ml->e]; + data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0; + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } else { - /* Count loop per edge to detect non-manifold. */ - if (data->edge_loop_count[mloop->e] < 3) { - data->edge_loop_count[mloop->e]++; - } - if (data->edge_loop_count[mloop->e] == 2) { - /* Manifold */ - int loopend = mpoly->totloop + mpoly->loopstart - 1; - int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1); - const MLoop *mloop_next = &mr->mloop[other_loop]; - const MVert *v1 = &mr->mvert[mloop->v]; - const MVert *v2 = &mr->mvert[mloop_next->v]; - float vnor_f[3]; - normal_short_to_float_v3(vnor_f, v1->no); - float ratio = loop_edge_factor_get(mr->poly_normals[p], v1->co, vnor_f, v2->co); - data->vbo_data[l] = ratio * 253 + 1; - } - else { - /* Non-manifold */ - data->vbo_data[l] = 255; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + /* Count loop per edge to detect non-manifold. */ + if (data->edge_loop_count[ml->e] < 3) { + data->edge_loop_count[ml->e]++; + } + if (data->edge_loop_count[ml->e] == 2) { + /* Manifold */ + const int ml_index_last = mp->totloop + mp->loopstart - 1; + const int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); + const MLoop *ml_next = &mr->mloop[ml_index_other]; + const MVert *v1 = &mr->mvert[ml->v]; + const MVert *v2 = &mr->mvert[ml_next->v]; + float vnor_f[3]; + normal_short_to_float_v3(vnor_f, v1->no); + float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co); + data->vbo_data[ml_index] = ratio * 253 + 1; + } + else { + /* Non-manifold */ + data->vbo_data[ml_index] = 255; + } } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } } -static void extract_edge_fac_ledge_bmesh(const MeshRenderData *mr, - int e, - BMEdge *UNUSED(eed), - void *_data) +static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *_data) { - MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; - data->vbo_data[mr->loop_len + e * 2 + 0] = 255; - data->vbo_data[mr->loop_len + e * 2 + 1] = 255; + MeshExtract_EdgeFac_Data *data = _data; + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + data->vbo_data[mr->loop_len + (ledge_index * 2) + 0] = 255; + data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255; + } + EXTRACT_LEDGE_FOREACH_BM_END; } -static void extract_edge_fac_ledge_mesh(const MeshRenderData *mr, - int e, - const MEdge *UNUSED(edge), - void *_data) +static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *_data) { - MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; - data->vbo_data[mr->loop_len + e * 2 + 0] = 255; - data->vbo_data[mr->loop_len + e * 2 + 1] = 255; + MeshExtract_EdgeFac_Data *data = _data; + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + data->vbo_data[mr->loop_len + ledge_index * 2 + 0] = 255; + data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 255; + } + EXTRACT_LEDGE_FOREACH_MESH_END; } static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_data) { - MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; + MeshExtract_EdgeFac_Data *data = _data; if (GPU_crappy_amd_driver()) { GPUVertBuf *vbo = (GPUVertBuf *)buf; - /* Some AMD drivers strangely crash with VBOs with a one byte format. - * To workaround we reinit the vbo with another format and convert + /* Some AMD drivers strangely crash with VBO's with a one byte format. + * To workaround we reinitialize the VBO with another format and convert * all bytes to floats. */ static GPUVertFormat format = {0}; if (format.attr_len == 0) { @@ -2490,8 +2895,8 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_ GPU_vertbuf_data_alloc(vbo, buf_len); float *fdata = (float *)vbo->data; - for (int l = 0; l < buf_len; l++, fdata++) { - *fdata = data->vbo_data[l] / 255.0f; + for (int ml_index = 0; ml_index < buf_len; ml_index++, fdata++) { + *fdata = data->vbo_data[ml_index] / 255.0f; } /* Free old byte data. */ MEM_freeN(data->vbo_data); @@ -2500,18 +2905,14 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_ } static const MeshExtract extract_edge_fac = { - extract_edge_fac_init, - NULL, - NULL, - extract_edge_fac_loop_bmesh, - extract_edge_fac_loop_mesh, - extract_edge_fac_ledge_bmesh, - extract_edge_fac_ledge_mesh, - NULL, - NULL, - extract_edge_fac_finish, - MR_DATA_POLY_NOR, - false, + .init = extract_edge_fac_init, + .iter_poly_bm = extract_edge_fac_iter_poly_bm, + .iter_poly_mesh = extract_edge_fac_iter_poly_mesh, + .iter_ledge_bm = extract_edge_fac_iter_ledge_bm, + .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh, + .finish = extract_edge_fac_finish, + .data_flag = MR_DATA_POLY_NOR, + .use_threading = false, }; /** \} */ @@ -2522,8 +2923,8 @@ static const MeshExtract extract_edge_fac = { typedef struct MeshExtract_Weight_Data { float *vbo_data; const DRW_MeshWeightState *wstate; - const MDeformVert *dvert; /* For Mesh. */ - int cd_ofs; /* For BMesh. */ + const MDeformVert *dvert; /* For #Mesh. */ + int cd_ofs; /* For #BMesh. */ } MeshExtract_Weight_Data; static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate) @@ -2609,27 +3010,49 @@ static void *extract_weights_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_weights_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *_data) +static void extract_weights_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { - MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data; - const MDeformVert *dvert = (data->cd_ofs != -1) ? BM_ELEM_CD_GET_VOID_P(loop->v, data->cd_ofs) : - NULL; - data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate); + MeshExtract_Weight_Data *data = _data; + if (data->cd_ofs != -1) { + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(l->v, data->cd_ofs); + data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); + } + else { + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); + } } -static void extract_weights_loop_mesh(const MeshRenderData *UNUSED(mr), - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *UNUSED(mpoly), - void *_data) +static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) { - MeshExtract_Weight_Data *data = (MeshExtract_Weight_Data *)_data; - const MDeformVert *dvert = data->dvert ? &data->dvert[mloop->v] : NULL; - data->vbo_data[l] = evaluate_vertex_weight(dvert, data->wstate); + MeshExtract_Weight_Data *data = _data; + if (data->dvert != NULL) { + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const MDeformVert *dvert = &data->dvert[ml->v]; + data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; + } + else { + const MDeformVert *dvert = NULL; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; + } } static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(buf), void *data) @@ -2638,18 +3061,12 @@ static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSE } static const MeshExtract extract_weights = { - extract_weights_init, - NULL, - NULL, - extract_weights_loop_bmesh, - extract_weights_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_weights_finish, - 0, - true, + .init = extract_weights_init, + .iter_poly_bm = extract_weights_iter_poly_bm, + .iter_poly_mesh = extract_weights_iter_poly_mesh, + .finish = extract_weights_finish, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -2756,31 +3173,31 @@ static void mesh_render_data_edge_flag(const MeshRenderData *mr, BMEdge *eed, Ed } static void mesh_render_data_loop_flag(const MeshRenderData *mr, - BMLoop *loop, + BMLoop *l, const int cd_ofs, EditLoopData *eattr) { if (cd_ofs == -1) { return; } - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_ofs); if (luv != NULL && (luv->flag & MLOOPUV_PINNED)) { eattr->v_flag |= VFLAG_VERT_UV_PINNED; } - if (uvedit_uv_select_test_ex(mr->toolsettings, loop, cd_ofs)) { + if (uvedit_uv_select_test_ex(mr->toolsettings, l, cd_ofs)) { eattr->v_flag |= VFLAG_VERT_UV_SELECT; } } static void mesh_render_data_loop_edge_flag(const MeshRenderData *mr, - BMLoop *loop, + BMLoop *l, const int cd_ofs, EditLoopData *eattr) { if (cd_ofs == -1) { return; } - if (uvedit_edge_select_test_ex(mr->toolsettings, loop, cd_ofs)) { + if (uvedit_edge_select_test_ex(mr->toolsettings, l, cd_ofs)) { eattr->v_flag |= VFLAG_EDGE_UV_SELECT; eattr->v_flag |= VFLAG_VERT_UV_SELECT; } @@ -2800,7 +3217,7 @@ static void *extract_edit_data_init(const MeshRenderData *mr, void *buf) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { - /* WARNING Adjust EditLoopData struct accordingly. */ + /* WARNING: Adjust #EditLoopData struct accordingly. */ GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); GPU_vertformat_alias_add(&format, "flag"); } @@ -2810,114 +3227,130 @@ static void *extract_edit_data_init(const MeshRenderData *mr, void *buf) return vbo->data; } -static void extract_edit_data_loop_bmesh(const MeshRenderData *mr, - int l, - BMLoop *loop, - void *_data) +static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { - EditLoopData *data = (EditLoopData *)_data + l; - memset(data, 0x0, sizeof(*data)); - mesh_render_data_face_flag(mr, loop->f, -1, data); - mesh_render_data_edge_flag(mr, loop->e, data); - mesh_render_data_vert_flag(mr, loop->v, data); -} -static void extract_edit_data_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int p, - const MPoly *UNUSED(mpoly), - void *_data) -{ - EditLoopData *data = (EditLoopData *)_data + l; - memset(data, 0x0, sizeof(*data)); - BMFace *efa = bm_original_face_get(mr, p); - BMEdge *eed = bm_original_edge_get(mr, mloop->e); - BMVert *eve = bm_original_vert_get(mr, mloop->v); - if (efa) { - mesh_render_data_face_flag(mr, efa, -1, data); - } - if (eed) { - mesh_render_data_edge_flag(mr, eed, data); - } - if (eve) { - mesh_render_data_vert_flag(mr, eve, data); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + EditLoopData *data = (EditLoopData *)_data + l_index; + memset(data, 0x0, sizeof(*data)); + mesh_render_data_face_flag(mr, l->f, -1, data); + mesh_render_data_edge_flag(mr, l->e, data); + mesh_render_data_vert_flag(mr, l->v, data); } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_edit_data_ledge_bmesh(const MeshRenderData *mr, - int e, - BMEdge *eed, - void *_data) +static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) { - EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2; - memset(data, 0x0, sizeof(*data) * 2); - mesh_render_data_edge_flag(mr, eed, &data[0]); - data[1] = data[0]; - mesh_render_data_vert_flag(mr, eed->v1, &data[0]); - mesh_render_data_vert_flag(mr, eed->v2, &data[1]); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + EditLoopData *data = (EditLoopData *)_data + ml_index; + memset(data, 0x0, sizeof(*data)); + BMFace *efa = bm_original_face_get(mr, mp_index); + BMEdge *eed = bm_original_edge_get(mr, ml->e); + BMVert *eve = bm_original_vert_get(mr, ml->v); + if (efa) { + mesh_render_data_face_flag(mr, efa, -1, data); + } + if (eed) { + mesh_render_data_edge_flag(mr, eed, data); + } + if (eve) { + mesh_render_data_vert_flag(mr, eve, data); + } + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } -static void extract_edit_data_ledge_mesh(const MeshRenderData *mr, - int e, - const MEdge *edge, - void *_data) +static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *_data) { - EditLoopData *data = (EditLoopData *)_data + mr->loop_len + e * 2; - memset(data, 0x0, sizeof(*data) * 2); - int e_idx = mr->ledges[e]; - BMEdge *eed = bm_original_edge_get(mr, e_idx); - BMVert *eve1 = bm_original_vert_get(mr, edge->v1); - BMVert *eve2 = bm_original_vert_get(mr, edge->v2); - if (eed) { + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + EditLoopData *data = (EditLoopData *)_data + mr->loop_len + (ledge_index * 2); + memset(data, 0x0, sizeof(*data) * 2); mesh_render_data_edge_flag(mr, eed, &data[0]); data[1] = data[0]; + mesh_render_data_vert_flag(mr, eed->v1, &data[0]); + mesh_render_data_vert_flag(mr, eed->v2, &data[1]); + } + EXTRACT_LEDGE_FOREACH_BM_END; +} + +static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *_data) +{ + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + EditLoopData *data = (EditLoopData *)_data + mr->loop_len + ledge_index * 2; + memset(data, 0x0, sizeof(*data) * 2); + const int e_index = mr->ledges[ledge_index]; + BMEdge *eed = bm_original_edge_get(mr, e_index); + BMVert *eve1 = bm_original_vert_get(mr, med->v1); + BMVert *eve2 = bm_original_vert_get(mr, med->v2); + if (eed) { + mesh_render_data_edge_flag(mr, eed, &data[0]); + data[1] = data[0]; + } + if (eve1) { + mesh_render_data_vert_flag(mr, eve1, &data[0]); + } + if (eve2) { + mesh_render_data_vert_flag(mr, eve2, &data[1]); + } } - if (eve1) { - mesh_render_data_vert_flag(mr, eve1, &data[0]); - } - if (eve2) { - mesh_render_data_vert_flag(mr, eve2, &data[1]); - } + EXTRACT_LEDGE_FOREACH_MESH_END; } -static void extract_edit_data_lvert_bmesh(const MeshRenderData *mr, - int v, - BMVert *eve, - void *_data) +static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr, + const ExtractLVertBMesh_Params *params, + void *_data) { - EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v; - memset(data, 0x0, sizeof(*data)); - mesh_render_data_vert_flag(mr, eve, data); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params) + { + EditLoopData *data = (EditLoopData *)_data + offset + lvert_index; + memset(data, 0x0, sizeof(*data)); + mesh_render_data_vert_flag(mr, eve, data); + } + EXTRACT_LVERT_FOREACH_BM_END; } -static void extract_edit_data_lvert_mesh(const MeshRenderData *mr, - int v, - const MVert *UNUSED(mvert), - void *_data) +static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, + const ExtractLVertMesh_Params *params, + void *_data) { - EditLoopData *data = (EditLoopData *)_data + mr->loop_len + mr->edge_loose_len * 2 + v; - memset(data, 0x0, sizeof(*data)); - int v_idx = mr->lverts[v]; - BMVert *eve = bm_original_vert_get(mr, v_idx); - if (eve) { - mesh_render_data_vert_flag(mr, eve, data); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr) + { + EditLoopData *data = (EditLoopData *)_data + offset + lvert_index; + memset(data, 0x0, sizeof(*data)); + const int v_index = mr->lverts[lvert_index]; + BMVert *eve = bm_original_vert_get(mr, v_index); + if (eve) { + mesh_render_data_vert_flag(mr, eve, data); + } } + EXTRACT_LVERT_FOREACH_MESH_END; } static const MeshExtract extract_edit_data = { - extract_edit_data_init, - NULL, - NULL, - extract_edit_data_loop_bmesh, - extract_edit_data_loop_mesh, - extract_edit_data_ledge_bmesh, - extract_edit_data_ledge_mesh, - extract_edit_data_lvert_bmesh, - extract_edit_data_lvert_mesh, - NULL, - 0, - true, + .init = extract_edit_data_init, + .iter_poly_bm = extract_edit_data_iter_poly_bm, + .iter_poly_mesh = extract_edit_data_iter_poly_mesh, + .iter_ledge_bm = extract_edit_data_iter_ledge_bm, + .iter_ledge_mesh = extract_edit_data_iter_ledge_mesh, + .iter_lvert_bm = extract_edit_data_iter_lvert_bm, + .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -2935,7 +3368,7 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { - /* WARNING Adjust EditLoopData struct accordingly. */ + /* WARNING: Adjust #EditLoopData struct accordingly. */ GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); GPU_vertformat_alias_add(&format, "flag"); } @@ -2952,51 +3385,59 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_edituv_data_loop_bmesh(const MeshRenderData *mr, - int l, - BMLoop *loop, - void *_data) +static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { - MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data; - EditLoopData *eldata = data->vbo_data + l; - memset(eldata, 0x0, sizeof(*eldata)); - mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata); - mesh_render_data_face_flag(mr, loop->f, data->cd_ofs, eldata); - mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata); -} - -static void extract_edituv_data_loop_mesh( - const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data) -{ - MeshExtract_EditUVData_Data *data = (MeshExtract_EditUVData_Data *)_data; - EditLoopData *eldata = data->vbo_data + l; - memset(eldata, 0x0, sizeof(*eldata)); - BMFace *efa = bm_original_face_get(mr, p); - if (efa) { - BMEdge *eed = bm_original_edge_get(mr, mloop->e); - BMVert *eve = bm_original_vert_get(mr, mloop->v); - if (eed && eve) { - /* Loop on an edge endpoint. */ - BMLoop *loop = BM_face_edge_share_loop(efa, eed); - mesh_render_data_loop_flag(mr, loop, data->cd_ofs, eldata); - mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata); - } - else { - if (eed == NULL) { - /* Find if the loop's vert is not part of an edit edge. - * For this, we check if the previous loop was on an edge. */ - int loopend = mpoly->loopstart + mpoly->totloop - 1; - int l_prev = (l == mpoly->loopstart) ? loopend : (l - 1); - const MLoop *mloop_prev = &mr->mloop[l_prev]; - eed = bm_original_edge_get(mr, mloop_prev->e); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + MeshExtract_EditUVData_Data *data = _data; + EditLoopData *eldata = &data->vbo_data[l_index]; + memset(eldata, 0x0, sizeof(*eldata)); + mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata); + mesh_render_data_face_flag(mr, l->f, data->cd_ofs, eldata); + mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); +} + +static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) +{ + MeshExtract_EditUVData_Data *data = _data; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + EditLoopData *eldata = &data->vbo_data[ml_index]; + memset(eldata, 0x0, sizeof(*eldata)); + BMFace *efa = bm_original_face_get(mr, mp_index); + if (efa) { + BMEdge *eed = bm_original_edge_get(mr, ml->e); + BMVert *eve = bm_original_vert_get(mr, ml->v); + if (eed && eve) { + /* Loop on an edge endpoint. */ + BMLoop *l = BM_face_edge_share_loop(efa, eed); + mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata); + mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); } - if (eed) { - /* Mapped points on an edge between two edit verts. */ - BMLoop *loop = BM_face_edge_share_loop(efa, eed); - mesh_render_data_loop_edge_flag(mr, loop, data->cd_ofs, eldata); + else { + if (eed == NULL) { + /* Find if the loop's vert is not part of an edit edge. + * For this, we check if the previous loop was on an edge. */ + const int ml_index_last = mp->loopstart + mp->totloop - 1; + const int l_prev = (ml_index == mp->loopstart) ? ml_index_last : (ml_index - 1); + const MLoop *ml_prev = &mr->mloop[l_prev]; + eed = bm_original_edge_get(mr, ml_prev->e); + } + if (eed) { + /* Mapped points on an edge between two edit verts. */ + BMLoop *l = BM_face_edge_share_loop(efa, eed); + mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); + } } } } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr), @@ -3007,18 +3448,12 @@ static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr), } static const MeshExtract extract_edituv_data = { - extract_edituv_data_init, - NULL, - NULL, - extract_edituv_data_loop_bmesh, - extract_edituv_data_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_edituv_data_finish, - 0, - true, + .init = extract_edituv_data_init, + .iter_poly_bm = extract_edituv_data_iter_poly_bm, + .iter_poly_mesh = extract_edituv_data_iter_poly_mesh, + .finish = extract_edituv_data_finish, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -3078,13 +3513,13 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * } else if (mr->extract_type == MR_EXTRACT_MAPPED) { const MLoopUV *uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); - const MPoly *mpoly = mr->mpoly; - for (int p = 0; p < mr->poly_len; p++, mpoly++) { - float area = BKE_mesh_calc_poly_area(mpoly, &mr->mloop[mpoly->loopstart], mr->mvert); - float uvarea = BKE_mesh_calc_poly_uv_area(mpoly, uv_data); + const MPoly *mp = mr->mpoly; + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + float area = BKE_mesh_calc_poly_area(mp, &mr->mloop[mp->loopstart], mr->mvert); + float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data); tot_area += area; tot_uv_area += uvarea; - area_ratio[p] = area_ratio_get(area, uvarea); + area_ratio[mp_index] = area_ratio_get(area, uvarea); } } else { @@ -3097,8 +3532,8 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * /* Convert in place to avoid an extra allocation */ uint16_t *poly_stretch = (uint16_t *)area_ratio; - for (int p = 0; p < mr->poly_len; p++) { - poly_stretch[p] = area_ratio[p] * SHRT_MAX; + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { + poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX; } /* Copy face data for each loop. */ @@ -3108,18 +3543,18 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * if (mr->extract_type == MR_EXTRACT_BMESH) { BMFace *efa; BMIter f_iter; - int f, l = 0; + int f, l_index = 0; BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { - for (int i = 0; i < efa->len; i++, l++) { - loop_stretch[l] = poly_stretch[f]; + for (int i = 0; i < efa->len; i++, l_index++) { + loop_stretch[l_index] = poly_stretch[f]; } } } else if (mr->extract_type == MR_EXTRACT_MAPPED) { - const MPoly *mpoly = mr->mpoly; - for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) { - for (int i = 0; i < mpoly->totloop; i++, l++) { - loop_stretch[l] = poly_stretch[p]; + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + for (int i = 0; i < mp->totloop; i++, l_index++) { + loop_stretch[l_index] = poly_stretch[mp_index]; } } } @@ -3132,18 +3567,10 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void * } static const MeshExtract extract_stretch_area = { - extract_stretch_area_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - mesh_stretch_area_finish, - 0, - false, + .init = extract_stretch_area_init, + .finish = mesh_stretch_area_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -3190,7 +3617,7 @@ static short v2_to_short_angle(float v[2]) static void edituv_get_stretch_angle(float auv[2][2], float av[2][3], UVStretchAngle *r_stretch) { - /* Send uvs to the shader and let it compute the aspect corrected angle. */ + /* Send UV's to the shader and let it compute the aspect corrected angle. */ r_stretch->uv_angles[0] = v2_to_short_angle(auv[0]); r_stretch->uv_angles[1] = v2_to_short_angle(auv[1]); /* Compute 3D angle here. */ @@ -3208,7 +3635,7 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf) { static GPUVertFormat format = {0}; if (format.attr_len == 0) { - /* WARNING Adjust UVStretchAngle struct accordingly. */ + /* Waning: adjust #UVStretchAngle struct accordingly. */ GPU_vertformat_attr_add(&format, "angle", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); } @@ -3220,7 +3647,7 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf) MeshExtract_StretchAngle_Data *data = MEM_callocN(sizeof(*data), __func__); data->vbo_data = (UVStretchAngle *)vbo->data; - /* Special iter nneded to save about half of the computing cost. */ + /* Special iterator needed to save about half of the computing cost. */ if (mr->extract_type == MR_EXTRACT_BMESH) { data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); } @@ -3233,94 +3660,95 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_stretch_angle_loop_bmesh(const MeshRenderData *mr, - int l, - BMLoop *loop, - void *_data) +static void extract_stretch_angle_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { - MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data; + MeshExtract_StretchAngle_Data *data = _data; float(*auv)[2] = data->auv, *last_auv = data->last_auv; float(*av)[3] = data->av, *last_av = data->last_av; - const MLoopUV *luv, *luv_next; - BMLoop *l_next = loop->next; - BMFace *efa = loop->f; - if (loop == efa->l_first) { - /* First loop in face. */ - BMLoop *l_tmp = loop->prev; - BMLoop *l_next_tmp = loop; - luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs); - luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs); - compute_normalize_edge_vectors(auv, - av, - luv->uv, - luv_next->uv, - bm_vert_co_get(mr, l_tmp->v), - bm_vert_co_get(mr, l_next_tmp->v)); - /* Save last edge. */ - copy_v2_v2(last_auv, auv[1]); - copy_v3_v3(last_av, av[1]); - } - if (l_next == efa->l_first) { - /* Move previous edge. */ - copy_v2_v2(auv[0], auv[1]); - copy_v3_v3(av[0], av[1]); - /* Copy already calculated last edge. */ - copy_v2_v2(auv[1], last_auv); - copy_v3_v3(av[1], last_av); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + const MLoopUV *luv, *luv_next; + BMLoop *l_next = l->next; + BMFace *efa = l->f; + if (l == BM_FACE_FIRST_LOOP(efa)) { + /* First loop in face. */ + BMLoop *l_tmp = l->prev; + BMLoop *l_next_tmp = l; + luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs); + luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs); + compute_normalize_edge_vectors(auv, + av, + luv->uv, + luv_next->uv, + bm_vert_co_get(mr, l_tmp->v), + bm_vert_co_get(mr, l_next_tmp->v)); + /* Save last edge. */ + copy_v2_v2(last_auv, auv[1]); + copy_v3_v3(last_av, av[1]); + } + if (l_next == BM_FACE_FIRST_LOOP(efa)) { + /* Move previous edge. */ + copy_v2_v2(auv[0], auv[1]); + copy_v3_v3(av[0], av[1]); + /* Copy already calculated last edge. */ + copy_v2_v2(auv[1], last_auv); + copy_v3_v3(av[1], last_av); + } + else { + luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs); + luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs); + compute_normalize_edge_vectors( + auv, av, luv->uv, luv_next->uv, bm_vert_co_get(mr, l->v), bm_vert_co_get(mr, l_next->v)); + } + edituv_get_stretch_angle(auv, av, &data->vbo_data[l_index]); } - else { - luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs); - luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs); - compute_normalize_edge_vectors(auv, - av, - luv->uv, - luv_next->uv, - bm_vert_co_get(mr, loop->v), - bm_vert_co_get(mr, l_next->v)); - } - edituv_get_stretch_angle(auv, av, data->vbo_data + l); -} - -static void extract_stretch_angle_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *UNUSED(mloop), - int UNUSED(p), - const MPoly *mpoly, - void *_data) + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); +} + +static void extract_stretch_angle_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) { - MeshExtract_StretchAngle_Data *data = (MeshExtract_StretchAngle_Data *)_data; - float(*auv)[2] = data->auv, *last_auv = data->last_auv; - float(*av)[3] = data->av, *last_av = data->last_av; - int l_next = l + 1, loopend = mpoly->loopstart + mpoly->totloop; - const MVert *v, *v_next; - if (l == mpoly->loopstart) { - /* First loop in face. */ - int l_tmp = loopend - 1; - int l_next_tmp = mpoly->loopstart; - v = &mr->mvert[mr->mloop[l_tmp].v]; - v_next = &mr->mvert[mr->mloop[l_next_tmp].v]; - compute_normalize_edge_vectors( - auv, av, data->luv[l_tmp].uv, data->luv[l_next_tmp].uv, v->co, v_next->co); - /* Save last edge. */ - copy_v2_v2(last_auv, auv[1]); - copy_v3_v3(last_av, av[1]); - } - if (l_next == loopend) { - l_next = mpoly->loopstart; - /* Move previous edge. */ - copy_v2_v2(auv[0], auv[1]); - copy_v3_v3(av[0], av[1]); - /* Copy already calculated last edge. */ - copy_v2_v2(auv[1], last_auv); - copy_v3_v3(av[1], last_av); - } - else { - v = &mr->mvert[mr->mloop[l].v]; - v_next = &mr->mvert[mr->mloop[l_next].v]; - compute_normalize_edge_vectors( - auv, av, data->luv[l].uv, data->luv[l_next].uv, v->co, v_next->co); + MeshExtract_StretchAngle_Data *data = _data; + + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + float(*auv)[2] = data->auv, *last_auv = data->last_auv; + float(*av)[3] = data->av, *last_av = data->last_av; + int l_next = ml_index + 1, ml_index_end = mp->loopstart + mp->totloop; + const MVert *v, *v_next; + if (ml_index == mp->loopstart) { + /* First loop in face. */ + const int ml_index_last = ml_index_end - 1; + const int l_next_tmp = mp->loopstart; + v = &mr->mvert[mr->mloop[ml_index_last].v]; + v_next = &mr->mvert[mr->mloop[l_next_tmp].v]; + compute_normalize_edge_vectors( + auv, av, data->luv[ml_index_last].uv, data->luv[l_next_tmp].uv, v->co, v_next->co); + /* Save last edge. */ + copy_v2_v2(last_auv, auv[1]); + copy_v3_v3(last_av, av[1]); + } + if (l_next == ml_index_end) { + l_next = mp->loopstart; + /* Move previous edge. */ + copy_v2_v2(auv[0], auv[1]); + copy_v3_v3(av[0], av[1]); + /* Copy already calculated last edge. */ + copy_v2_v2(auv[1], last_auv); + copy_v3_v3(av[1], last_av); + } + else { + v = &mr->mvert[mr->mloop[ml_index].v]; + v_next = &mr->mvert[mr->mloop[l_next].v]; + compute_normalize_edge_vectors( + auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co); + } + edituv_get_stretch_angle(auv, av, &data->vbo_data[ml_index]); } - edituv_get_stretch_angle(auv, av, data->vbo_data + l); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr), @@ -3331,18 +3759,12 @@ static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr), } static const MeshExtract extract_stretch_angle = { - extract_stretch_angle_init, - NULL, - NULL, - extract_stretch_angle_loop_bmesh, - extract_stretch_angle_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_stretch_angle_finish, - 0, - false, + .init = extract_stretch_angle_init, + .iter_poly_bm = extract_stretch_angle_iter_poly_bm, + .iter_poly_mesh = extract_stretch_angle_iter_poly_mesh, + .finish = extract_stretch_angle_finish, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -3414,28 +3836,30 @@ static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang) normalize_v3(dir); if (mr->extract_type == MR_EXTRACT_BMESH) { - int l = 0; + int l_index = 0; BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI; fac = overhang_remap(fac, min, max, minmax_irange); - for (int i = 0; i < f->len; i++, l++) { - r_overhang[l] = fac; + for (int i = 0; i < f->len; i++, l_index++) { + r_overhang[l_index] = fac; } } } else { - const MPoly *mpoly = mr->mpoly; - for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) { - float fac = angle_normalized_v3v3(mr->poly_normals[p], dir) / (float)M_PI; + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + float fac = angle_normalized_v3v3(mr->poly_normals[mp_index], dir) / (float)M_PI; fac = overhang_remap(fac, min, max, minmax_irange); - for (int i = 0; i < mpoly->totloop; i++, l++) { - r_overhang[l] = fac; + for (int i = 0; i < mp->totloop; i++, l_index++) { + r_overhang[l_index] = fac; } } } } -/* so we can use jitter values for face interpolation */ +/** + * Needed so we can use jitter values for face interpolation. + */ static void uv_from_jitter_v2(float uv[2]) { uv[0] += 0.5f; @@ -3527,12 +3951,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) BMIter iter; BMFace *f; - int l = 0; + int l_index = 0; BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { float fac = face_dists[BM_elem_index_get(f)]; fac = thickness_remap(fac, min, max, minmax_irange); - for (int i = 0; i < f->len; i++, l++) { - r_thickness[l] = fac; + for (int i = 0; i < f->len; i++, l_index++) { + r_thickness[l_index] = fac; } } } @@ -3573,12 +3997,12 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) } } - const MPoly *mpoly = mr->mpoly; - for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) { - float fac = face_dists[p]; + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + float fac = face_dists[mp_index]; fac = thickness_remap(fac, min, max, minmax_irange); - for (int i = 0; i < mpoly->totloop; i++, l++) { - r_thickness[l] = fac; + for (int i = 0; i < mp->totloop; i++, l_index++) { + r_thickness[l_index] = fac; } } } @@ -3629,8 +4053,8 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) { BMEditMesh *em = mr->edit_bmesh; - for (int l = 0; l < mr->loop_len; l++) { - r_intersect[l] = -1.0f; + for (int l_index = 0; l_index < mr->loop_len; l_index++) { + r_intersect[l_index] = -1.0f; } if (mr->extract_type == MR_EXTRACT_BMESH) { @@ -3651,9 +4075,9 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) for (int j = 0; j < 2; j++) { BMFace *f_hit = f_hit_pair[j]; BMLoop *l_first = BM_FACE_FIRST_LOOP(f_hit); - int l = BM_elem_index_get(l_first); - for (int k = 0; k < f_hit->len; k++, l++) { - r_intersect[l] = 1.0f; + int l_index = BM_elem_index_get(l_first); + for (int k = 0; k < f_hit->len; k++, l_index++) { + r_intersect[l_index] = 1.0f; } } } @@ -3680,9 +4104,9 @@ static void statvis_calc_intersect(const MeshRenderData *mr, float *r_intersect) }; for (int j = 0; j < 2; j++) { const MPoly *f_hit = f_hit_pair[j]; - int l = f_hit->loopstart; - for (int k = 0; k < f_hit->totloop; k++, l++) { - r_intersect[l] = 1.0f; + int l_index = f_hit->loopstart; + for (int k = 0; k < f_hit->totloop; k++, l_index++) { + r_intersect[l_index] = 1.0f; } } } @@ -3725,9 +4149,9 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) BM_mesh_elem_index_ensure(em->bm, BM_VERT); } - int l = 0; - int p = 0; - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, p) { + int l_index = 0; + int f_index = 0; + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, f_index) { float fac = -1.0f; if (f->len > 3) { @@ -3739,7 +4163,7 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) const float *no_face; float no_corner[3]; if (mr->bm_vert_coords != NULL) { - no_face = mr->bm_poly_normals[p]; + no_face = mr->bm_poly_normals[f_index]; BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner); } else { @@ -3758,24 +4182,24 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) } fac = distort_remap(fac, min, max, minmax_irange); - for (int i = 0; i < f->len; i++, l++) { - r_distort[l] = fac; + for (int i = 0; i < f->len; i++, l_index++) { + r_distort[l_index] = fac; } } } else { - const MPoly *mpoly = mr->mpoly; - for (int p = 0, l = 0; p < mr->poly_len; p++, mpoly++) { + const MPoly *mp = mr->mpoly; + for (int mp_index = 0, l_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { float fac = -1.0f; - if (mpoly->totloop > 3) { - float *f_no = mr->poly_normals[p]; + if (mp->totloop > 3) { + float *f_no = mr->poly_normals[mp_index]; fac = 0.0f; - for (int i = 1; i <= mpoly->totloop; i++) { - const MLoop *l_prev = &mr->mloop[mpoly->loopstart + (i - 1) % mpoly->totloop]; - const MLoop *l_curr = &mr->mloop[mpoly->loopstart + (i + 0) % mpoly->totloop]; - const MLoop *l_next = &mr->mloop[mpoly->loopstart + (i + 1) % mpoly->totloop]; + for (int i = 1; i <= mp->totloop; i++) { + const MLoop *l_prev = &mr->mloop[mp->loopstart + (i - 1) % mp->totloop]; + const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop]; + const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop]; float no_corner[3]; normal_tri_v3(no_corner, mr->mvert[l_prev->v].co, @@ -3791,8 +4215,8 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) } fac = distort_remap(fac, min, max, minmax_irange); - for (int i = 0; i < mpoly->totloop; i++, l++) { - r_distort[l] = fac; + for (int i = 0; i < mp->totloop; i++, l_index++) { + r_distort[l_index] = fac; } } } @@ -3825,11 +4249,10 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) copy_vn_fl(vert_angles, mr->vert_len, -M_PI); if (mr->extract_type == MR_EXTRACT_BMESH) { - BMIter iter, l_iter; + BMIter iter; BMesh *bm = em->bm; BMFace *efa; BMEdge *e; - BMLoop *loop; /* first assign float values to verts */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { float angle = BM_edge_calc_face_angle_signed(e); @@ -3840,35 +4263,37 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) } /* Copy vert value to loops. */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) { - int l = BM_elem_index_get(loop); - int v = BM_elem_index_get(loop->v); - r_sharp[l] = sharp_remap(vert_angles[v], min, max, minmax_irange); - } + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + int l_index = BM_elem_index_get(l_iter); + int v_index = BM_elem_index_get(l_iter->v); + r_sharp[l_index] = sharp_remap(vert_angles[v_index], min, max, minmax_irange); + } while ((l_iter = l_iter->next) != l_first); } } else { /* first assign float values to verts */ - const MPoly *mpoly = mr->mpoly; + const MPoly *mp = mr->mpoly; EdgeHash *eh = BLI_edgehash_new_ex(__func__, mr->edge_len); - for (int p = 0; p < mr->poly_len; p++, mpoly++) { - for (int i = 0; i < mpoly->totloop; i++) { - const MLoop *l_curr = &mr->mloop[mpoly->loopstart + (i + 0) % mpoly->totloop]; - const MLoop *l_next = &mr->mloop[mpoly->loopstart + (i + 1) % mpoly->totloop]; + for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) { + for (int i = 0; i < mp->totloop; i++) { + const MLoop *l_curr = &mr->mloop[mp->loopstart + (i + 0) % mp->totloop]; + const MLoop *l_next = &mr->mloop[mp->loopstart + (i + 1) % mp->totloop]; const MVert *v_curr = &mr->mvert[l_curr->v]; const MVert *v_next = &mr->mvert[l_next->v]; float angle; void **pval; bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval); if (!value_is_init) { - *pval = mr->poly_normals[p]; + *pval = mr->poly_normals[mp_index]; /* non-manifold edge, yet... */ continue; } else if (*pval != NULL) { - const float *f1_no = mr->poly_normals[p]; + const float *f1_no = mr->poly_normals[mp_index]; const float *f2_no = *pval; angle = angle_normalized_v3v3(f1_no, f2_no); angle = is_edge_convex_v3(v_curr->co, v_next->co, f1_no, f2_no) ? angle : -angle; @@ -3901,9 +4326,9 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) BLI_edgehashIterator_free(ehi); BLI_edgehash_free(eh, NULL); - const MLoop *mloop = mr->mloop; - for (int l = 0; l < mr->loop_len; l++, mloop++) { - r_sharp[l] = sharp_remap(vert_angles[mloop->v], min, max, minmax_irange); + const MLoop *ml = mr->mloop; + for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) { + r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange); } } @@ -3937,20 +4362,12 @@ static void extract_mesh_analysis_finish(const MeshRenderData *mr, void *buf, vo } static const MeshExtract extract_mesh_analysis = { - extract_mesh_analysis_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_mesh_analysis_finish, - /* This is not needed for all vis type. - * Maybe split into different extract. */ - MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, - false, + .init = extract_mesh_analysis_init, + .finish = extract_mesh_analysis_finish, + /* This is not needed for all visualization types. + * * Maybe split into different extract. */ + .data_flag = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, + .use_threading = false, }; /** \} */ @@ -3975,49 +4392,46 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, void *buf) return vbo->data; } -static void extract_fdots_pos_loop_bmesh(const MeshRenderData *mr, - int UNUSED(l), - BMLoop *loop, - void *data) +static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - float(*center)[3] = (float(*)[3])data; - float w = 1.0f / (float)loop->f->len; - madd_v3_v3fl(center[BM_elem_index_get(loop->f)], bm_vert_co_get(mr, loop->v), w); + float(*center)[3] = data; + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + float w = 1.0f / (float)l->f->len; + madd_v3_v3fl(center[BM_elem_index_get(l->f)], bm_vert_co_get(mr, l->v), w); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr, - int UNUSED(l), - const MLoop *mloop, - int p, - const MPoly *mpoly, - void *data) +static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { float(*center)[3] = (float(*)[3])data; - const MVert *mvert = &mr->mvert[mloop->v]; - if (mr->use_subsurf_fdots) { - if (mvert->flag & ME_VERT_FACEDOT) { - copy_v3_v3(center[p], mvert->co); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const MVert *mv = &mr->mvert[ml->v]; + if (mr->use_subsurf_fdots) { + if (mv->flag & ME_VERT_FACEDOT) { + copy_v3_v3(center[mp_index], mv->co); + } + } + else { + float w = 1.0f / (float)mp->totloop; + madd_v3_v3fl(center[mp_index], mv->co, w); } } - else { - float w = 1.0f / (float)mpoly->totloop; - madd_v3_v3fl(center[p], mvert->co, w); - } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static const MeshExtract extract_fdots_pos = { - extract_fdots_pos_init, - NULL, - NULL, - extract_fdots_pos_loop_bmesh, - extract_fdots_pos_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - true, + .init = extract_fdots_pos_init, + .iter_poly_bm = extract_fdots_pos_iter_poly_bm, + .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -4090,18 +4504,10 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void * } static const MeshExtract extract_fdots_nor = { - extract_fdots_nor_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - extract_fdots_nor_finish, - MR_DATA_POLY_NOR, - false, + .init = extract_fdots_nor_init, + .finish = extract_fdots_nor_finish, + .data_flag = MR_DATA_POLY_NOR, + .use_threading = false, }; /** \} */ @@ -4145,30 +4551,42 @@ static void *extract_fdots_uv_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_fdots_uv_loop_bmesh(const MeshRenderData *UNUSED(mr), - int UNUSED(l), - BMLoop *loop, - void *_data) +static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { - MeshExtract_FdotUV_Data *data = (MeshExtract_FdotUV_Data *)_data; - float w = 1.0f / (float)loop->f->len; - const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs); - madd_v2_v2fl(data->vbo_data[BM_elem_index_get(loop->f)], luv->uv, w); + MeshExtract_FdotUV_Data *data = _data; + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + float w = 1.0f / (float)l->f->len; + const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs); + madd_v2_v2fl(data->vbo_data[BM_elem_index_get(l->f)], luv->uv, w); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_fdots_uv_loop_mesh( - const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *_data) +static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) { - MeshExtract_FdotUV_Data *data = (MeshExtract_FdotUV_Data *)_data; + MeshExtract_FdotUV_Data *data = _data; if (mr->use_subsurf_fdots) { - const MVert *mvert = &mr->mvert[mloop->v]; - if (mvert->flag & ME_VERT_FACEDOT) { - copy_v2_v2(data->vbo_data[p], data->uv_data[l].uv); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const MVert *mv = &mr->mvert[ml->v]; + if (mv->flag & ME_VERT_FACEDOT) { + copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv); + } } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } else { - float w = 1.0f / (float)mpoly->totloop; - madd_v2_v2fl(data->vbo_data[p], data->uv_data[l].uv, w); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + float w = 1.0f / (float)mp->totloop; + madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w); + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } } @@ -4180,18 +4598,12 @@ static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr), } static const MeshExtract extract_fdots_uv = { - extract_fdots_uv_init, - NULL, - NULL, - extract_fdots_uv_loop_bmesh, - extract_fdots_uv_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_fdots_uv_finish, - 0, - true, + .init = extract_fdots_uv_init, + .iter_poly_bm = extract_fdots_uv_iter_poly_bm, + .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh, + .finish = extract_fdots_uv_finish, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -4220,31 +4632,35 @@ static void *extract_fdots_edituv_data_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_fdots_edituv_data_loop_bmesh(const MeshRenderData *mr, - int UNUSED(l), - BMLoop *loop, - void *_data) +static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) { - MeshExtract_EditUVFdotData_Data *data = (MeshExtract_EditUVFdotData_Data *)_data; - EditLoopData *eldata = data->vbo_data + BM_elem_index_get(loop->f); - memset(eldata, 0x0, sizeof(*eldata)); - mesh_render_data_face_flag(mr, loop->f, data->cd_ofs, eldata); + MeshExtract_EditUVFdotData_Data *data = _data; + EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) + { + EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)]; + memset(eldata, 0x0, sizeof(*eldata)); + mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); + } + EXTRACT_POLY_FOREACH_BM_END; } -static void extract_fdots_edituv_data_loop_mesh(const MeshRenderData *mr, - int UNUSED(l), - const MLoop *UNUSED(mloop), - int p, - const MPoly *UNUSED(mpoly), - void *_data) +static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) { - MeshExtract_EditUVFdotData_Data *data = (MeshExtract_EditUVFdotData_Data *)_data; - EditLoopData *eldata = data->vbo_data + p; - memset(eldata, 0x0, sizeof(*eldata)); - BMFace *efa = bm_original_face_get(mr, p); - if (efa) { - mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata); + MeshExtract_EditUVFdotData_Data *data = _data; + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + EditLoopData *eldata = &data->vbo_data[mp_index]; + memset(eldata, 0x0, sizeof(*eldata)); + BMFace *efa = bm_original_face_get(mr, mp_index); + if (efa) { + mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata); + } } + EXTRACT_POLY_FOREACH_MESH_END; } static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr), @@ -4255,18 +4671,12 @@ static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr), } static const MeshExtract extract_fdots_edituv_data = { - extract_fdots_edituv_data_init, - NULL, - NULL, - extract_fdots_edituv_data_loop_bmesh, - extract_fdots_edituv_data_loop_mesh, - NULL, - NULL, - NULL, - NULL, - extract_fdots_edituv_data_finish, - 0, - true, + .init = extract_fdots_edituv_data_init, + .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm, + .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh, + .finish = extract_fdots_edituv_data_finish, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -4317,18 +4727,9 @@ static void *extract_skin_roots_init(const MeshRenderData *mr, void *buf) } static const MeshExtract extract_skin_roots = { - extract_skin_roots_init, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - false, + .init = extract_skin_roots_init, + .data_flag = 0, + .use_threading = false, }; /** \} */ @@ -4350,157 +4751,183 @@ static void *extract_select_idx_init(const MeshRenderData *mr, void *buf) return vbo->data; } -/* TODO Use glVertexID to get loop index and use the data structure on the CPU to retrieve the +/* TODO Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the * select element associated with this loop ID. This would remove the need for this separate - * index VBOs. We could upload the p/e/v_origindex as a buffer texture and sample it inside the + * index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the * shader to output original index. */ -static void extract_poly_idx_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *data) +static void extract_poly_idx_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - ((uint32_t *)data)[l] = BM_elem_index_get(loop->f); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + ((uint32_t *)data)[l_index] = BM_elem_index_get(l->f); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_edge_idx_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *data) +static void extract_edge_idx_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - ((uint32_t *)data)[l] = BM_elem_index_get(loop->e); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + ((uint32_t *)data)[l_index] = BM_elem_index_get(l->e); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_vert_idx_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *data) +static void extract_vert_idx_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - ((uint32_t *)data)[l] = BM_elem_index_get(loop->v); + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + ((uint32_t *)data)[l_index] = BM_elem_index_get(l->v); + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); } -static void extract_edge_idx_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *data) +static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *data) { - ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = BM_elem_index_get(eed); - ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = BM_elem_index_get(eed); + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed); + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed); + } + EXTRACT_LEDGE_FOREACH_BM_END; } -static void extract_vert_idx_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *data) +static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *data) { - ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = BM_elem_index_get(eed->v1); - ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = BM_elem_index_get(eed->v2); + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = BM_elem_index_get(eed->v1); + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2); + } + EXTRACT_LEDGE_FOREACH_BM_END; } -static void extract_vert_idx_lvert_bmesh(const MeshRenderData *mr, int v, BMVert *eve, void *data) +static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr, + const ExtractLVertBMesh_Params *params, + void *data) { - ((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = BM_elem_index_get(eve); + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params) + { + ((uint32_t *)data)[offset + lvert_index] = BM_elem_index_get(eve); + } + EXTRACT_LVERT_FOREACH_BM_END; } -static void extract_poly_idx_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *UNUSED(mloop), - int p, - const MPoly *UNUSED(mpoly), - void *data) +static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - ((uint32_t *)data)[l] = (mr->p_origindex) ? mr->p_origindex[p] : p; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + ((uint32_t *)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index; + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } -static void extract_edge_idx_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *UNUSED(mpoly), - void *data) +static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - ((uint32_t *)data)[l] = (mr->e_origindex) ? mr->e_origindex[mloop->e] : mloop->e; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + ((uint32_t *)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e; + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } -static void extract_vert_idx_loop_mesh(const MeshRenderData *mr, - int l, - const MLoop *mloop, - int UNUSED(p), - const MPoly *UNUSED(mpoly), - void *data) +static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - ((uint32_t *)data)[l] = (mr->v_origindex) ? mr->v_origindex[mloop->v] : mloop->v; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + ((uint32_t *)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v; + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } -static void extract_edge_idx_ledge_mesh(const MeshRenderData *mr, - int e, - const MEdge *UNUSED(medge), - void *data) +static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *data) { - int e_idx = mr->ledges[e]; - int e_orig = (mr->e_origindex) ? mr->e_origindex[e_idx] : e_idx; - ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = e_orig; - ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = e_orig; + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + const int e_index = mr->ledges[ledge_index]; + const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_index; + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = e_orig; + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig; + } + EXTRACT_LEDGE_FOREACH_MESH_END; } -static void extract_vert_idx_ledge_mesh(const MeshRenderData *mr, - int e, - const MEdge *medge, - void *data) +static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *data) { - int v1_orig = (mr->v_origindex) ? mr->v_origindex[medge->v1] : medge->v1; - int v2_orig = (mr->v_origindex) ? mr->v_origindex[medge->v2] : medge->v2; - ((uint32_t *)data)[mr->loop_len + e * 2 + 0] = v1_orig; - ((uint32_t *)data)[mr->loop_len + e * 2 + 1] = v2_orig; + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1; + int v2_orig = (mr->v_origindex) ? mr->v_origindex[med->v2] : med->v2; + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 0] = v1_orig; + ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig; + } + EXTRACT_LEDGE_FOREACH_MESH_END; } -static void extract_vert_idx_lvert_mesh(const MeshRenderData *mr, - int v, - const MVert *UNUSED(mvert), - void *data) +static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr, + const ExtractLVertMesh_Params *params, + void *data) { - int v_idx = mr->lverts[v]; - int v_orig = (mr->v_origindex) ? mr->v_origindex[v_idx] : v_idx; - ((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = v_orig; + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_MESH_BEGIN(med, lvert_index, params, mr) + { + const int v_index = mr->lverts[lvert_index]; + const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index; + ((uint32_t *)data)[offset + lvert_index] = v_orig; + } + EXTRACT_LVERT_FOREACH_MESH_END; } static const MeshExtract extract_poly_idx = { - extract_select_idx_init, - NULL, - NULL, - extract_poly_idx_loop_bmesh, - extract_poly_idx_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - true, + .init = extract_select_idx_init, + .iter_poly_bm = extract_poly_idx_iter_poly_bm, + .iter_poly_mesh = extract_poly_idx_iter_poly_mesh, + .data_flag = 0, + .use_threading = true, }; static const MeshExtract extract_edge_idx = { - extract_select_idx_init, - NULL, - NULL, - extract_edge_idx_loop_bmesh, - extract_edge_idx_loop_mesh, - extract_edge_idx_ledge_bmesh, - extract_edge_idx_ledge_mesh, - NULL, - NULL, - NULL, - 0, - true, + .init = extract_select_idx_init, + .iter_poly_bm = extract_edge_idx_iter_poly_bm, + .iter_poly_mesh = extract_edge_idx_iter_poly_mesh, + .iter_ledge_bm = extract_edge_idx_iter_ledge_bm, + .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh, + .data_flag = 0, + .use_threading = true, }; static const MeshExtract extract_vert_idx = { - extract_select_idx_init, - NULL, - NULL, - extract_vert_idx_loop_bmesh, - extract_vert_idx_loop_mesh, - extract_vert_idx_ledge_bmesh, - extract_vert_idx_ledge_mesh, - extract_vert_idx_lvert_bmesh, - extract_vert_idx_lvert_mesh, - NULL, - 0, - true, + .init = extract_select_idx_init, + .iter_poly_bm = extract_vert_idx_iter_poly_bm, + .iter_poly_mesh = extract_vert_idx_iter_poly_mesh, + .iter_ledge_bm = extract_vert_idx_iter_ledge_bm, + .iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh, + .iter_lvert_bm = extract_vert_idx_iter_lvert_bm, + .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh, + .data_flag = 0, + .use_threading = true, }; static void *extract_select_fdot_idx_init(const MeshRenderData *mr, void *buf) @@ -4516,37 +4943,43 @@ static void *extract_select_fdot_idx_init(const MeshRenderData *mr, void *buf) return vbo->data; } -static void extract_fdot_idx_loop_bmesh(const MeshRenderData *UNUSED(mr), - int UNUSED(l), - BMLoop *loop, - void *data) +static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *data) { - ((uint32_t *)data)[BM_elem_index_get(loop->f)] = BM_elem_index_get(loop->f); + EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) + { + ((uint32_t *)data)[f_index] = f_index; + } + EXTRACT_POLY_FOREACH_BM_END; } -static void extract_fdot_idx_loop_mesh(const MeshRenderData *mr, - int UNUSED(l), - const MLoop *UNUSED(mloop), - int p, - const MPoly *UNUSED(mpoly), - void *data) +static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *data) { - ((uint32_t *)data)[p] = (mr->p_origindex) ? mr->p_origindex[p] : p; + if (mr->p_origindex != NULL) { + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + ((uint32_t *)data)[mp_index] = mr->p_origindex[mp_index]; + } + EXTRACT_POLY_FOREACH_MESH_END; + } + else { + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + ((uint32_t *)data)[mp_index] = mp_index; + } + EXTRACT_POLY_FOREACH_MESH_END; + } } static const MeshExtract extract_fdot_idx = { - extract_select_fdot_idx_init, - NULL, - NULL, - extract_fdot_idx_loop_bmesh, - extract_fdot_idx_loop_mesh, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - true, + .init = extract_select_fdot_idx_init, + .iter_poly_bm = extract_fdot_idx_iter_poly_bm, + .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh, + .data_flag = 0, + .use_threading = true, }; /** \} */ @@ -4589,9 +5022,9 @@ static ExtractTaskData *extract_task_data_create_mesh_extract(const MeshRenderDa taskdata->extract = extract; taskdata->buf = buf; - /* ExtractUserData is shared between the iterations as it holds counters to detect if the - * extraction is finished. To make sure the duplication of the userdata does not create a new - * instance of the counters we allocate the userdata in its own container. + /* #ExtractUserData is shared between the iterations as it holds counters to detect if the + * extraction is finished. To make sure the duplication of the user_data does not create a new + * instance of the counters we allocate the user_data in its own container. * * This structure makes sure that when extract_init is called, that the user data of all * iterations are updated. */ @@ -4628,67 +5061,69 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, switch (mr->extract_type) { case MR_EXTRACT_BMESH: if (iter_type & MR_ITER_LOOPTRI) { - int t_end = min_ii(mr->tri_len, end); - for (int t = start; t < t_end; t++) { - BMLoop **elt = &mr->edit_bmesh->looptris[t][0]; - extract->iter_looptri_bm(mr, t, elt, user_data); - } + extract->iter_looptri_bm(mr, + &(const ExtractTriBMesh_Params){ + .looptris = mr->edit_bmesh->looptris, + .tri_range = {start, min_ii(mr->tri_len, end)}, + }, + user_data); } - if (iter_type & MR_ITER_LOOP) { - int l_end = min_ii(mr->poly_len, end); - for (int f = start; f < l_end; f++) { - BMFace *efa = BM_face_at_index(mr->bm, f); - BMLoop *loop; - BMIter l_iter; - BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) { - extract->iter_loop_bm(mr, BM_elem_index_get(loop), loop, user_data); - } - } + if (iter_type & MR_ITER_POLY) { + extract->iter_poly_bm(mr, + &(const ExtractPolyBMesh_Params){ + .poly_range = {start, min_ii(mr->poly_len, end)}, + }, + user_data); } if (iter_type & MR_ITER_LEDGE) { - int le_end = min_ii(mr->edge_loose_len, end); - for (int e = start; e < le_end; e++) { - BMEdge *eed = BM_edge_at_index(mr->bm, mr->ledges[e]); - extract->iter_ledge_bm(mr, e, eed, user_data); - } + extract->iter_ledge_bm(mr, + &(const ExtractLEdgeBMesh_Params){ + .ledge = mr->ledges, + .ledge_range = {start, min_ii(mr->edge_loose_len, end)}, + }, + user_data); } if (iter_type & MR_ITER_LVERT) { - int lv_end = min_ii(mr->vert_loose_len, end); - for (int v = start; v < lv_end; v++) { - BMVert *eve = BM_vert_at_index(mr->bm, mr->lverts[v]); - extract->iter_lvert_bm(mr, v, eve, user_data); - } + extract->iter_lvert_bm(mr, + &(const ExtractLVertBMesh_Params){ + .lvert = mr->lverts, + .lvert_range = {start, min_ii(mr->vert_loose_len, end)}, + }, + user_data); } break; case MR_EXTRACT_MAPPED: case MR_EXTRACT_MESH: if (iter_type & MR_ITER_LOOPTRI) { - int t_end = min_ii(mr->tri_len, end); - for (int t = start; t < t_end; t++) { - extract->iter_looptri(mr, t, &mr->mlooptri[t], user_data); - } + extract->iter_looptri_mesh(mr, + &(const ExtractTriMesh_Params){ + .mlooptri = mr->mlooptri, + .tri_range = {start, min_ii(mr->tri_len, end)}, + }, + user_data); } - if (iter_type & MR_ITER_LOOP) { - int l_end = min_ii(mr->poly_len, end); - for (int p = start; p < l_end; p++) { - const MPoly *mpoly = &mr->mpoly[p]; - int l = mpoly->loopstart; - for (int i = 0; i < mpoly->totloop; i++, l++) { - extract->iter_loop(mr, l, &mr->mloop[l], p, mpoly, user_data); - } - } + if (iter_type & MR_ITER_POLY) { + extract->iter_poly_mesh(mr, + &(const ExtractPolyMesh_Params){ + .poly_range = {start, min_ii(mr->poly_len, end)}, + }, + user_data); } if (iter_type & MR_ITER_LEDGE) { - int le_end = min_ii(mr->edge_loose_len, end); - for (int e = start; e < le_end; e++) { - extract->iter_ledge(mr, e, &mr->medge[mr->ledges[e]], user_data); - } + extract->iter_ledge_mesh(mr, + &(const ExtractLEdgeMesh_Params){ + .ledge = mr->ledges, + .ledge_range = {start, min_ii(mr->edge_loose_len, end)}, + }, + user_data); } if (iter_type & MR_ITER_LVERT) { - int lv_end = min_ii(mr->vert_loose_len, end); - for (int v = start; v < lv_end; v++) { - extract->iter_lvert(mr, v, &mr->mvert[mr->lverts[v]], user_data); - } + extract->iter_lvert_mesh(mr, + &(const ExtractLVertMesh_Params){ + .lvert = mr->lverts, + .lvert_range = {start, min_ii(mr->vert_loose_len, end)}, + }, + user_data); } break; } @@ -4915,10 +5350,10 @@ static void extract_task_create(struct TaskGraph *task_graph, task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size); } } - if (taskdata->iter_type & MR_ITER_LOOP) { + if (taskdata->iter_type & MR_ITER_POLY) { for (int i = 0; i < mr->poly_len; i += chunk_size) { extract_range_task_create( - task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOP, i, chunk_size); + task_graph, task_node_user_data_init, taskdata, MR_ITER_POLY, i, chunk_size); } } if (taskdata->iter_type & MR_ITER_LEDGE) { @@ -4973,9 +5408,9 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, * `extract_single_threaded_task_node`. * * Other extractions will create a node for each loop exceeding 8192 items. these nodes are - * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the userdata - * needed for the extraction based on the data extracted from the mesh. counters are used to - * check if the finalize of a task has to be called. + * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the + * user_data needed for the extraction based on the data extracted from the mesh. + * counters are used to check if the finalize of a task has to be called. * * Mesh extraction sub graph * diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 191d75342d0..5cf1c24af0b 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -170,6 +170,7 @@ struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(struct Mesh *me, struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_surface_weights(struct Mesh *me); /* edit-mesh drawing */ struct GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(struct Mesh *me); @@ -199,6 +200,11 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_uv_edges(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(struct Mesh *me); +/* For direct data access. */ +struct GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(struct Mesh *me); +struct GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu); +struct GPUVertBuf *DRW_mball_batch_cache_pos_vertbuf_get(struct Object *ob); + int DRW_mesh_material_count_get(struct Mesh *me); /* See 'common_globals_lib.glsl' for duplicate defines. */ diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c index 8798549a416..73e0ff7ef83 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -903,6 +903,16 @@ GPUBatch **DRW_curve_batch_cache_get_surface_shaded(struct Curve *cu, return cache->surf_per_mat; } +GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */ + DRW_batch_request(&cache->batch.surfaces); + + DRW_vbo_request(NULL, &cache->ordered.loop_pos_nor); + return cache->ordered.loop_pos_nor; +} + GPUBatch *DRW_curve_batch_cache_get_wireframes_face(Curve *cu) { CurveBatchCache *cache = curve_batch_cache_get(cu); diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index b4974330043..53e04fb61ee 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -349,10 +349,10 @@ static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl), } } -static void gp_object_verts_count_cb(bGPDlayer *UNUSED(gpl), - bGPDframe *UNUSED(gpf), - bGPDstroke *gps, - void *thunk) +static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl), + bGPDframe *UNUSED(gpf), + bGPDstroke *gps, + void *thunk) { gpIterData *iter = (gpIterData *)thunk; @@ -387,7 +387,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr .tri_len = 0, }; BKE_gpencil_visible_stroke_iter( - NULL, ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra); + NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra); /* Create VBOs. */ GPUVertFormat *format = gpencil_stroke_format(); @@ -441,10 +441,10 @@ GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra) return cache->fill_batch; } -static void gp_lines_indices_cb(bGPDlayer *UNUSED(gpl), - bGPDframe *UNUSED(gpf), - bGPDstroke *gps, - void *thunk) +static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl), + bGPDframe *UNUSED(gpf), + bGPDstroke *gps, + void *thunk) { gpIterData *iter = (gpIterData *)thunk; int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps); @@ -477,7 +477,8 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob) /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ bool do_onion = true; - BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra); + BKE_gpencil_visible_stroke_iter( + NULL, ob, NULL, gpencil_lines_indices_cb, &iter, do_onion, cfra); GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 99e285a18f1..ea1717f0684 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -112,6 +112,21 @@ BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me) return &me->ldata; } +BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_MDATA: + return &me->vdata; + break; + case ME_WRAPPER_TYPE_BMESH: + return &me->edit_mesh->bm->vdata; + break; + } + + BLI_assert(0); + return &me->vdata; +} + static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; @@ -135,7 +150,19 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; - const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); + const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); + + int layer = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR); + if (layer != -1) { + cd_used->sculpt_vcol |= (1 << layer); + } +} + +static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used) +{ + const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; + const CustomData *cd_ldata = &me_final->ldata; + int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL); if (layer != -1) { cd_used->vcol |= (1 << layer); @@ -148,6 +175,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, { const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); + const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); /* See: DM_vertex_attributes_from_gpu for similar logic */ DRW_MeshCDMask cd_used; @@ -175,6 +203,11 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name); type = CD_MCOL; } + + if (layer == -1) { + layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name); + type = CD_PROP_COLOR; + } #if 0 /* Tangents are always from UV's - this will never happen. */ if (layer == -1) { layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name); @@ -222,7 +255,20 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, } break; } + case CD_PROP_COLOR: { + /* Sculpt Vertex Colors */ + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name) : + CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR); + } + if (layer != -1) { + cd_used.sculpt_vcol |= (1 << layer); + } + break; + } case CD_MCOL: { + /* Vertex Color Data */ if (layer == -1) { layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) : CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL); @@ -230,6 +276,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, if (layer != -1) { cd_used.vcol |= (1 << layer); } + break; } case CD_ORCO: { @@ -679,10 +726,22 @@ static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me) { DRW_MeshCDMask cd_needed; mesh_cd_layers_type_clear(&cd_needed); - mesh_cd_calc_active_vcol_layer(me, &cd_needed); + mesh_cd_calc_active_mloopcol_layer(me, &cd_needed); BLI_assert(cd_needed.vcol != 0 && - "No vcol layer available in vertpaint, but batches requested anyway!"); + "No MLOOPCOL layer available in vertpaint, but batches requested anyway!"); + + mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); +} + +static void sculpt_request_active_vcol(MeshBatchCache *cache, Mesh *me) +{ + DRW_MeshCDMask cd_needed; + mesh_cd_layers_type_clear(&cd_needed); + mesh_cd_calc_active_vcol_layer(me, &cd_needed); + + BLI_assert(cd_needed.sculpt_vcol != 0 && + "No MPropCol layer available in Sculpt, but batches requested anyway!"); mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); } @@ -799,6 +858,14 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me) return DRW_batch_request(&cache->batch.surface); } +GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + sculpt_request_active_vcol(cache, me); + mesh_batch_cache_add_request(cache, MBC_SURFACE); + return DRW_batch_request(&cache->batch.surface); +} + int DRW_mesh_material_count_get(Mesh *me) { return mesh_render_mat_len_get(me); @@ -810,6 +877,23 @@ int DRW_mesh_material_count_get(Mesh *me) /** \name Edit Mode API * \{ */ +GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */ + mesh_batch_cache_add_request(cache, MBC_SURFACE); + DRW_batch_request(&cache->batch.surface); + + DRW_vbo_request(NULL, &cache->final.vbo.pos_nor); + return cache->final.vbo.pos_nor; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Edit Mode API + * \{ */ + GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); @@ -1120,7 +1204,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if (cache->cd_used.orco != cache->cd_needed.orco) { GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.orco); } - if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) { + if (((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) || + ((cache->cd_used.sculpt_vcol & cache->cd_needed.sculpt_vcol) != + cache->cd_needed.sculpt_vcol)) { GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.vcol); } } @@ -1201,7 +1287,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if (cache->cd_used.uv != 0) { DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.uv); } - if (cache->cd_used.vcol != 0) { + if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) { DRW_vbo_request(cache->batch.surface, &mbufcache->vbo.vcol); } } @@ -1269,7 +1355,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if ((cache->cd_used.tan != 0) || (cache->cd_used.tan_orco != 0)) { DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.tan); } - if (cache->cd_used.vcol != 0) { + if (cache->cd_used.vcol != 0 || cache->cd_used.sculpt_vcol != 0) { DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.vcol); } if (cache->cd_used.orco != 0) { diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c index c14e66c2b47..076d32ffe1f 100644 --- a/source/blender/draw/intern/draw_cache_impl_metaball.c +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -274,6 +274,18 @@ struct GPUBatch *DRW_metaball_batch_cache_get_edge_detection(struct Object *ob, return cache->edge_detection; } +struct GPUVertBuf *DRW_mball_batch_cache_pos_vertbuf_get(Object *ob) +{ + if (!BKE_mball_is_basis(ob)) { + return NULL; + } + + MetaBall *mb = ob->data; + MetaBallBatchCache *cache = metaball_batch_cache_get(mb); + + return mball_batch_cache_get_pos_and_normals(ob, cache); +} + int DRW_metaball_material_count_get(MetaBall *mb) { return max_ii(1, mb->totcol); diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h index a067434f3bb..67f44b5fb0c 100644 --- a/source/blender/draw/intern/draw_cache_inline.h +++ b/source/blender/draw/intern/draw_cache_inline.h @@ -90,17 +90,19 @@ BLI_INLINE void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo) if (*vbo == NULL) { *vbo = MEM_callocN(sizeof(GPUVertBuf), "GPUVertBuf"); } - /* HACK set first vbo if not init. */ - if (batch->verts[0] == NULL) { - GPU_batch_vao_cache_clear(batch); - batch->verts[0] = *vbo; - } - else { - /* HACK: bypass assert */ - int vbo_vert_len = (*vbo)->vertex_len; - (*vbo)->vertex_len = batch->verts[0]->vertex_len; - GPU_batch_vertbuf_add(batch, *vbo); - (*vbo)->vertex_len = vbo_vert_len; + if (batch != NULL) { + /* HACK set first vbo if not init. */ + if (batch->verts[0] == NULL) { + GPU_batch_vao_cache_clear(batch); + batch->verts[0] = *vbo; + } + else { + /* HACK: bypass assert */ + int vbo_vert_len = (*vbo)->vertex_len; + (*vbo)->vertex_len = batch->verts[0]->vertex_len; + GPU_batch_vertbuf_add(batch, *vbo); + (*vbo)->vertex_len = vbo_vert_len; + } } } diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 656d72b2808..81c0e97a1a8 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -176,6 +176,13 @@ struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md, struct DRWShadingGroup *shgrp); +struct GPUVertBuf *DRW_hair_pos_buffer_get(struct Object *object, + struct ParticleSystem *psys, + struct ModifierData *md); +void DRW_hair_duplimat_get(struct Object *object, + struct ParticleSystem *psys, + struct ModifierData *md, + float (*dupli_mat)[4]); void DRW_hair_init(void); void DRW_hair_update(void); diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 2fdaf0d5345..6cfba0e2a78 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -124,32 +124,109 @@ void DRW_hair_init(void) } } -DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, - ParticleSystem *psys, - ModifierData *md, - DRWShadingGroup *shgrp_parent) +static ParticleHairCache *drw_hair_particle_cache_get( + Object *object, ParticleSystem *psys, ModifierData *md, int subdiv, int thickness_res) +{ + bool update; + ParticleHairCache *cache; + if (psys) { + /* Old particle hair. */ + update = particles_ensure_procedural_data(object, psys, md, &cache, subdiv, thickness_res); + } + else { + /* New hair object. */ + update = hair_ensure_procedural_data(object, &cache, subdiv, thickness_res); + } + + if (update) { + int final_points_len = cache->final[subdiv].strands_res * cache->strands_len; + if (final_points_len > 0) { + GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); + +#ifdef USE_TRANSFORM_FEEDBACK + DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create( + tf_shader, g_tf_pass, cache->final[subdiv].proc_buf); +#else + DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); + + ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); + pr_call->next = g_tf_calls; + pr_call->vbo = cache->final[subdiv].proc_buf; + pr_call->shgrp = tf_shgrp; + pr_call->vert_len = final_points_len; + g_tf_calls = pr_call; + DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); + DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); + DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); +#endif + + DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", cache->point_tex); + DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", cache->strand_tex); + DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", cache->strand_seg_tex); + DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1); + DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len); + } + } + return cache; +} + +/* Note: Only valid after DRW_hair_update(). */ +GPUVertBuf *DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, ModifierData *md) { - /* TODO(fclem): Pass the scene as parameter */ const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - float dupli_mat[4][4]; - Object *dupli_parent = DRW_object_get_dupli_parent(object); - DupliObject *dupli_object = DRW_object_get_dupli(object); int subdiv = scene->r.hair_subdiv; int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2; - ParticleHairCache *hair_cache; - bool need_ft_update; + ParticleHairCache *cache = drw_hair_particle_cache_get(object, psys, md, subdiv, thickness_res); + + return cache->final[subdiv].proc_buf; +} + +void DRW_hair_duplimat_get(Object *object, + ParticleSystem *psys, + ModifierData *UNUSED(md), + float (*dupli_mat)[4]) +{ + Object *dupli_parent = DRW_object_get_dupli_parent(object); + DupliObject *dupli_object = DRW_object_get_dupli(object); + if (psys) { - /* Old particle hair. */ - need_ft_update = particles_ensure_procedural_data( - object, psys, md, &hair_cache, subdiv, thickness_res); + if ((dupli_parent != NULL) && (dupli_object != NULL)) { + if (dupli_object->type & OB_DUPLICOLLECTION) { + copy_m4_m4(dupli_mat, dupli_parent->obmat); + } + else { + copy_m4_m4(dupli_mat, dupli_object->ob->obmat); + invert_m4(dupli_mat); + mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat); + } + } + else { + unit_m4(dupli_mat); + } } else { /* New hair object. */ - need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res); + copy_m4_m4(dupli_mat, object->obmat); } +} + +DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, + ParticleSystem *psys, + ModifierData *md, + DRWShadingGroup *shgrp_parent) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + float dupli_mat[4][4]; + + int subdiv = scene->r.hair_subdiv; + int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2; + + ParticleHairCache *hair_cache = drw_hair_particle_cache_get( + object, psys, md, subdiv, thickness_res); DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent); @@ -177,25 +254,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture); } - if (psys) { - if ((dupli_parent != NULL) && (dupli_object != NULL)) { - if (dupli_object->type & OB_DUPLICOLLECTION) { - copy_m4_m4(dupli_mat, dupli_parent->obmat); - } - else { - copy_m4_m4(dupli_mat, dupli_object->ob->obmat); - invert_m4(dupli_mat); - mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat); - } - } - else { - unit_m4(dupli_mat); - } - } - else { - /* New hair object. */ - copy_m4_m4(dupli_mat, object->obmat); - } + DRW_hair_duplimat_get(object, psys, md, dupli_mat); /* Get hair shape parameters. */ float hair_rad_shape, hair_rad_root, hair_rad_tip; @@ -229,38 +288,6 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1]; DRW_shgroup_call_no_cull(shgrp, geom, object); - /* Transform Feedback subdiv. */ - if (need_ft_update) { - int final_points_len = hair_cache->final[subdiv].strands_res * hair_cache->strands_len; - if (final_points_len) { - GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); - -#ifdef USE_TRANSFORM_FEEDBACK - DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create( - tf_shader, g_tf_pass, hair_cache->final[subdiv].proc_buf); -#else - DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); - - ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); - pr_call->next = g_tf_calls; - pr_call->vbo = hair_cache->final[subdiv].proc_buf; - pr_call->shgrp = tf_shgrp; - pr_call->vert_len = final_points_len; - g_tf_calls = pr_call; - DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); - DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); - DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); -#endif - - DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex); - DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex); - DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex); - DRW_shgroup_uniform_int( - tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); - DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len); - } - } - return shgrp; } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 10ef8d9c4c8..3e42c4cdb23 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -373,6 +373,8 @@ void DRW_render_viewport_size_set(int size[2]) { DST.size[0] = size[0]; DST.size[1] = size[1]; + DST.inv_size[0] = 1.0f / size[0]; + DST.inv_size[1] = 1.0f / size[1]; } const float *DRW_viewport_size_get(void) @@ -1635,13 +1637,6 @@ bool DRW_render_check_grease_pencil(Depsgraph *depsgraph) return false; } -static void drw_view_reset(void) -{ - DST.view_default = NULL; - DST.view_active = NULL; - DST.view_previous = NULL; -} - static void DRW_render_gpencil_to_image(RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect) @@ -1719,7 +1714,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph for (RenderView *render_view = render_result->views.first; render_view != NULL; render_view = render_view->next) { RE_SetActiveRenderView(render, render_view->name); - drw_view_reset(); + DRW_view_reset(); DST.buffer_finish_called = false; DRW_render_gpencil_to_image(engine, render_layer, &render_rect); } @@ -1827,7 +1822,7 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) for (RenderView *render_view = render_result->views.first; render_view != NULL; render_view = render_view->next) { RE_SetActiveRenderView(render, render_view->name); - drw_view_reset(); + DRW_view_reset(); engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect); DST.buffer_finish_called = false; } @@ -1949,6 +1944,28 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, #endif } +/* Used when the render engine want to redo another cache populate inside the same render frame. */ +void DRW_cache_restart(void) +{ + /* Save viewport size. */ + float size[2], inv_size[2]; + copy_v2_v2(size, DST.size); + copy_v2_v2(inv_size, DST.inv_size); + + /* Force cache to reset. */ + drw_viewport_cache_resize(); + + drw_viewport_var_init(); + + DST.buffer_finish_called = false; + + DRW_hair_init(); + + /* Restore. */ + copy_v2_v2(DST.size, size); + copy_v2_v2(DST.inv_size, inv_size); +} + static struct DRWSelectBuffer { struct GPUFrameBuffer *framebuffer_depth_only; struct GPUTexture *texture_depth; @@ -2374,6 +2391,17 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, const rcti *rect) { + SELECTID_Context *sel_ctx = DRW_select_engine_context_get(); + GPUViewport *viewport = WM_draw_region_get_viewport(region); + if (!viewport) { + /* Selection engine requires a viewport. + * TODO (germano): This should be done internally in the engine. */ + sel_ctx->is_dirty = true; + sel_ctx->objects_drawn_len = 0; + sel_ctx->index_drawn_len = 1; + return; + } + Scene *scene = DEG_get_evaluated_scene(depsgraph); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); @@ -2394,14 +2422,13 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_context_state_init(); /* Setup viewport */ - DST.viewport = WM_draw_region_get_viewport(region); + DST.viewport = viewport; drw_viewport_var_init(); /* Update ubos */ DRW_globals_update(); /* Init Select Engine */ - struct SELECTID_Context *sel_ctx = DRW_select_engine_context_get(); sel_ctx->last_rect = *rect; use_drw_engine(&draw_engine_select_type); diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 07fb97236fb..3d83b918757 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -76,7 +76,7 @@ static void draw_call_sort(DRWCommand *array, DRWCommand *array_tmp, int array_l for (int i = 1; i < ARRAY_SIZE(idx); i++) { idx[i] += idx[i - 1]; } - /* Traverse in reverse to not change the order of the resource ids. */ + /* Traverse in reverse to not change the order of the resource ID's. */ for (int src = array_len - 1; src >= 0; src--) { array_tmp[--idx[KEY(array[src])]] = array[src]; } @@ -116,7 +116,7 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool) vmempool->ubo_len = ubo_len; } - /* Remove unecessary buffers */ + /* Remove unnecessary buffers */ for (int i = ubo_len; i < vmempool->ubo_len; i++) { GPU_uniformbuffer_free(vmempool->matrices_ubo[i]); GPU_uniformbuffer_free(vmempool->obinfos_ubo[i]); @@ -151,7 +151,7 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool) BLI_memblock_iternew(vmempool->commands, &iter); while ((chunk = BLI_memblock_iterstep(&iter))) { bool sortable = true; - /* We can only sort chunks that contain DRWCommandDraw only. */ + /* We can only sort chunks that contain #DRWCommandDraw only. */ for (int i = 0; i < ARRAY_SIZE(chunk->command_type) && sortable; i++) { if (chunk->command_type[i] != 0) { sortable = false; @@ -179,7 +179,7 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, int arraysize) { if (loc == -1) { - /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */ + /* Nice to enable eventually, for now EEVEE uses uniforms that might not exist. */ // BLI_assert(0); return; } @@ -262,11 +262,19 @@ void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, con DRW_shgroup_uniform_texture_ex(shgroup, name, tex, GPU_SAMPLER_MAX); } -void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex) +void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup, + const char *name, + GPUTexture **tex, + eGPUSamplerState sampler_state) { BLI_assert(tex != NULL); int loc = GPU_shader_get_texture_binding(shgroup->shader, name); - drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, GPU_SAMPLER_MAX, 0, 1); + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, sampler_state, 0, 1); +} + +void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex) +{ + DRW_shgroup_uniform_texture_ref_ex(shgroup, name, tex, GPU_SAMPLER_MAX); } void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, @@ -424,7 +432,7 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, int location = GPU_shader_get_uniform(shgroup->shader, name); if (location == -1) { - /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */ + /* Nice to enable eventually, for now EEVEE uses uniforms that might not exist. */ // BLI_assert(0); return; } @@ -530,6 +538,11 @@ static void drw_call_culling_init(DRWCullingState *cull, Object *ob) mul_v3_m4v3(corner, ob->obmat, bbox->vec[0]); mul_m4_v3(ob->obmat, cull->bsphere.center); cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner); + + /* Bypass test for very large objects (see T67319). */ + if (UNLIKELY(cull->bsphere.radius > 1e12)) { + cull->bsphere.radius = -1.0f; + } } else { /* Bypass test. */ @@ -569,7 +582,7 @@ uint32_t DRW_object_resource_id_get(Object *UNUSED(ob)) /* Handle not yet allocated. Return next handle. */ handle = DST.resource_handle; } - return handle; + return handle & ~(1 << 31); } static DRWResourceHandle drw_resource_handle(DRWShadingGroup *shgroup, @@ -1786,6 +1799,14 @@ const DRWView *DRW_view_default_get(void) return DST.view_default; } +/* WARNING: Only use in render AND only if you are going to set view_default again. */ +void DRW_view_reset(void) +{ + DST.view_default = NULL; + DST.view_active = NULL; + DST.view_previous = NULL; +} + /* MUST only be called once per render and only in render mode. Sets default view. */ void DRW_view_default_set(DRWView *view) { diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c index 81c9f400f6e..558d5441136 100644 --- a/source/blender/draw/intern/draw_select_buffer.c +++ b/source/blender/draw/intern/draw_select_buffer.c @@ -122,7 +122,6 @@ uint *DRW_select_buffer_read(struct Depsgraph *depsgraph, /** * \param rect: The rectangle to sample indices from (min/max inclusive). - * \param mask: Specifies the rect pixels (optional). * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. */ uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph, @@ -165,10 +164,10 @@ uint *DRW_select_buffer_bitmap_from_rect(struct Depsgraph *depsgraph, } /** - * \param bitmap_len: Number of indices in the selection id buffer. * \param center: Circle center. * \param radius: Circle radius. - * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. + * \param r_bitmap_len: Number of indices in the selection id buffer. + * \returns a #BLI_bitmap the length of \a r_bitmap_len or NULL on failure. */ uint *DRW_select_buffer_bitmap_from_circle(struct Depsgraph *depsgraph, struct ARegion *region, @@ -338,7 +337,7 @@ uint DRW_select_buffer_sample_point(struct Depsgraph *depsgraph, /** * Find the selection id closest to \a center. - * \param dist[in,out]: Use to initialize the distance, + * \param dist: Use to initialize the distance, * when found, this value is set to the distance of the selection that's returned. */ uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, |