Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/intern/draw_cache_extract_mesh.c
| Show First 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
| #include "draw_cache_extract.h" | #include "draw_cache_extract.h" | ||||
| // #define DEBUG_TIME | // #define DEBUG_TIME | ||||
| #ifdef DEBUG_TIME | #ifdef DEBUG_TIME | ||||
| # include "PIL_time_utildefines.h" | # include "PIL_time_utildefines.h" | ||||
| #endif | #endif | ||||
| #define CHUNK_SIZE 8192 | |||||
| /* | |||||
| * Max number of extractions types. | |||||
| */ | |||||
| #define M_EXTRACT_LEN 38 | |||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Mesh/BMesh Interface (indirect, partially cached access to complex data). | /** \name Mesh/BMesh Interface (indirect, partially cached access to complex data). | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshRenderData { | typedef struct MeshRenderData { | ||||
| eMRExtractType extract_type; | eMRExtractType extract_type; | ||||
| int poly_len, edge_len, vert_len, loop_len; | int poly_len, edge_len, vert_len, loop_len; | ||||
| ▲ Show 20 Lines • Show All 434 Lines • ▼ Show 20 Lines | |||||
| /** \name Mesh Elements Extract: Loop Triangles | /** \name Mesh Elements Extract: Loop Triangles | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct ExtractTriBMesh_Params { | typedef struct ExtractTriBMesh_Params { | ||||
| BMLoop *(*looptris)[3]; | BMLoop *(*looptris)[3]; | ||||
| int tri_range[2]; | int tri_range[2]; | ||||
| } ExtractTriBMesh_Params; | } ExtractTriBMesh_Params; | ||||
| typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr, | typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractTriBMesh_Params *params, | BMLoop **elt, | ||||
| const int elt_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elem_tri, index_tri, params) \ | #define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elem_tri, index_tri, params) \ | ||||
| CHECK_TYPE(params, const ExtractTriBMesh_Params *); \ | CHECK_TYPE(params, const ExtractTriBMesh_Params *); \ | ||||
| { \ | { \ | ||||
| const int _tri_index_end = (params)->tri_range[1]; \ | const int _tri_index_end = (params)->tri_range[1]; \ | ||||
| BMLoop **elem_tri = (params)->looptris[(params)->tri_range[0]]; \ | BMLoop **elem_tri = (params)->looptris[(params)->tri_range[0]]; \ | ||||
| for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ | for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ | ||||
| index_tri += 1, elem_tri += 3) | index_tri += 1, elem_tri += 3) | ||||
| #define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END } | #define EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END } | ||||
| typedef struct ExtractTriMesh_Params { | typedef struct ExtractTriMesh_Params { | ||||
| const MLoopTri *mlooptri; | const MLoopTri *mlooptri; | ||||
| int tri_range[2]; | int tri_range[2]; | ||||
| } ExtractTriMesh_Params; | } ExtractTriMesh_Params; | ||||
| typedef void(ExtractTriMeshFn)(const MeshRenderData *mr, | typedef void(ExtractTriMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractTriMesh_Params *params, | const MLoopTri *mlt, | ||||
| const int elt_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(elem_tri, index_tri, params) \ | #define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(elem_tri, index_tri, params) \ | ||||
| CHECK_TYPE(params, const ExtractTriMesh_Params *); \ | CHECK_TYPE(params, const ExtractTriMesh_Params *); \ | ||||
| { \ | { \ | ||||
| const int _tri_index_end = (params)->tri_range[1]; \ | const int _tri_index_end = (params)->tri_range[1]; \ | ||||
| const MLoopTri *elem_tri = &(params)->mlooptri[(params)->tri_range[0]]; \ | const MLoopTri *elem_tri = &(params)->mlooptri[(params)->tri_range[0]]; \ | ||||
| for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ | for (int index_tri = (params)->tri_range[0]; index_tri < _tri_index_end; \ | ||||
| index_tri += 1, elem_tri += 1) | index_tri += 1, elem_tri += 1) | ||||
| #define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END } | #define EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END } | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Mesh Elements Extract: Polygons, Loops | /** \name Mesh Elements Extract: Polygons, Loops | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct ExtractPolyBMesh_Params { | typedef struct ExtractPolyBMesh_Params { | ||||
| BMLoop *(*looptris)[3]; | BMLoop *(*looptris)[3]; | ||||
| int poly_range[2]; | int poly_range[2]; | ||||
| } ExtractPolyBMesh_Params; | } ExtractPolyBMesh_Params; | ||||
| typedef void(ExtractPolyBMeshFn)(const MeshRenderData *mr, | typedef void(ExtractPolyBMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int f_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_POLY_FOREACH_BM_BEGIN(elem_poly, index_poly, params, mr) \ | #define EXTRACT_POLY_FOREACH_BM_BEGIN(elem_poly, index_poly, params, mr) \ | ||||
| CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \ | CHECK_TYPE(params, const ExtractPolyBMesh_Params *); \ | ||||
| { \ | { \ | ||||
| BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ | BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ | ||||
| BMFace **_ftable = mr->bm->ftable; \ | BMFace **_ftable = mr->bm->ftable; \ | ||||
| const int _poly_index_end = (params)->poly_range[1]; \ | const int _poly_index_end = (params)->poly_range[1]; \ | ||||
| Show All 28 Lines | while ((elem_loop = elem_loop->next) != l_first) \ | ||||
| ; \ | ; \ | ||||
| } \ | } \ | ||||
| } | } | ||||
| typedef struct ExtractPolyMesh_Params { | typedef struct ExtractPolyMesh_Params { | ||||
| int poly_range[2]; | int poly_range[2]; | ||||
| } ExtractPolyMesh_Params; | } ExtractPolyMesh_Params; | ||||
| typedef void(ExtractPolyMeshFn)(const MeshRenderData *mr, | typedef void(ExtractPolyMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_POLY_FOREACH_MESH_BEGIN(elem_poly, index_poly, params, mr) \ | #define EXTRACT_POLY_FOREACH_MESH_BEGIN(elem_poly, index_poly, params, mr) \ | ||||
| CHECK_TYPE(params, const ExtractPolyMesh_Params *); \ | CHECK_TYPE(params, const ExtractPolyMesh_Params *); \ | ||||
| { \ | { \ | ||||
| const MPoly *_mpoly = mr->mpoly; \ | const MPoly *_mpoly = mr->mpoly; \ | ||||
| const int _poly_index_end = (params)->poly_range[1]; \ | const int _poly_index_end = (params)->poly_range[1]; \ | ||||
| for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ | for (int index_poly = (params)->poly_range[0]; index_poly < _poly_index_end; \ | ||||
| Show All 32 Lines | |||||
| /** \name Mesh Elements Extract: Loose Edges | /** \name Mesh Elements Extract: Loose Edges | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct ExtractLEdgeBMesh_Params { | typedef struct ExtractLEdgeBMesh_Params { | ||||
| const int *ledge; | const int *ledge; | ||||
| int ledge_range[2]; | int ledge_range[2]; | ||||
| } ExtractLEdgeBMesh_Params; | } ExtractLEdgeBMesh_Params; | ||||
| typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr, | typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_LEDGE_FOREACH_BM_BEGIN(elem_edge, index_ledge, params) \ | #define EXTRACT_LEDGE_FOREACH_BM_BEGIN(elem_edge, index_ledge, params) \ | ||||
| CHECK_TYPE(params, const ExtractLEdgeBMesh_Params *); \ | CHECK_TYPE(params, const ExtractLEdgeBMesh_Params *); \ | ||||
| { \ | { \ | ||||
| BLI_assert((mr->bm->elem_table_dirty & BM_EDGE) == 0); \ | BLI_assert((mr->bm->elem_table_dirty & BM_EDGE) == 0); \ | ||||
| BMEdge **_etable = mr->bm->etable; \ | BMEdge **_etable = mr->bm->etable; \ | ||||
| const int *_ledge = (params)->ledge; \ | const int *_ledge = (params)->ledge; \ | ||||
| const int _ledge_index_end = (params)->ledge_range[1]; \ | const int _ledge_index_end = (params)->ledge_range[1]; \ | ||||
| for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \ | for (int index_ledge = (params)->ledge_range[0]; index_ledge < _ledge_index_end; \ | ||||
| index_ledge += 1) { \ | index_ledge += 1) { \ | ||||
| BMEdge *elem_edge = _etable[_ledge[index_ledge]]; \ | BMEdge *elem_edge = _etable[_ledge[index_ledge]]; \ | ||||
| (void)elem_edge; /* Quiet warning when unused. */ \ | (void)elem_edge; /* Quiet warning when unused. */ \ | ||||
| { | { | ||||
| #define EXTRACT_LEDGE_FOREACH_BM_END \ | #define EXTRACT_LEDGE_FOREACH_BM_END \ | ||||
| } \ | } \ | ||||
| } \ | } \ | ||||
| } | } | ||||
| typedef struct ExtractLEdgeMesh_Params { | typedef struct ExtractLEdgeMesh_Params { | ||||
| const int *ledge; | const int *ledge; | ||||
| int ledge_range[2]; | int ledge_range[2]; | ||||
| } ExtractLEdgeMesh_Params; | } ExtractLEdgeMesh_Params; | ||||
| typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr, | typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *med, | ||||
| const uint ledge_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_LEDGE_FOREACH_MESH_BEGIN(elem_edge, index_ledge, params, mr) \ | #define EXTRACT_LEDGE_FOREACH_MESH_BEGIN(elem_edge, index_ledge, params, mr) \ | ||||
| CHECK_TYPE(params, const ExtractLEdgeMesh_Params *); \ | CHECK_TYPE(params, const ExtractLEdgeMesh_Params *); \ | ||||
| { \ | { \ | ||||
| const MEdge *_medge = mr->medge; \ | const MEdge *_medge = mr->medge; \ | ||||
| const int *_ledge = (params)->ledge; \ | const int *_ledge = (params)->ledge; \ | ||||
| const int _ledge_index_end = (params)->ledge_range[1]; \ | const int _ledge_index_end = (params)->ledge_range[1]; \ | ||||
| Show All 13 Lines | |||||
| /** \name Mesh Elements Extract: Loose Vertices | /** \name Mesh Elements Extract: Loose Vertices | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct ExtractLVertBMesh_Params { | typedef struct ExtractLVertBMesh_Params { | ||||
| const int *lvert; | const int *lvert; | ||||
| int lvert_range[2]; | int lvert_range[2]; | ||||
| } ExtractLVertBMesh_Params; | } ExtractLVertBMesh_Params; | ||||
| typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr, | typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractLVertBMesh_Params *params, | BMVert *eve, | ||||
| const int lvert_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_LVERT_FOREACH_BM_BEGIN(elem_vert, index_lvert, params) \ | #define EXTRACT_LVERT_FOREACH_BM_BEGIN(elem_vert, index_lvert, params) \ | ||||
| CHECK_TYPE(params, const ExtractLVertBMesh_Params *); \ | CHECK_TYPE(params, const ExtractLVertBMesh_Params *); \ | ||||
| { \ | { \ | ||||
| BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ | BLI_assert((mr->bm->elem_table_dirty & BM_FACE) == 0); \ | ||||
| BMVert **vtable = mr->bm->vtable; \ | BMVert **vtable = mr->bm->vtable; \ | ||||
| const int *lverts = (params)->lvert; \ | const int *lverts = (params)->lvert; \ | ||||
| const int _lvert_index_end = (params)->lvert_range[1]; \ | const int _lvert_index_end = (params)->lvert_range[1]; \ | ||||
| for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \ | for (int index_lvert = (params)->lvert_range[0]; index_lvert < _lvert_index_end; \ | ||||
| index_lvert += 1) { \ | index_lvert += 1) { \ | ||||
| BMVert *elem_vert = vtable[lverts[index_lvert]]; \ | BMVert *elem_vert = vtable[lverts[index_lvert]]; \ | ||||
| (void)elem_vert; /* Quiet warning when unused. */ \ | (void)elem_vert; /* Quiet warning when unused. */ \ | ||||
| { | { | ||||
| #define EXTRACT_LVERT_FOREACH_BM_END \ | #define EXTRACT_LVERT_FOREACH_BM_END \ | ||||
| } \ | } \ | ||||
| } \ | } \ | ||||
| } | } | ||||
| typedef struct ExtractLVertMesh_Params { | typedef struct ExtractLVertMesh_Params { | ||||
| const int *lvert; | const int *lvert; | ||||
| int lvert_range[2]; | int lvert_range[2]; | ||||
| } ExtractLVertMesh_Params; | } ExtractLVertMesh_Params; | ||||
| typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr, | typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr, | ||||
| const ExtractLVertMesh_Params *params, | const MVert *mv, | ||||
| const int lvert_index, | |||||
| void *data); | void *data); | ||||
| #define EXTRACT_LVERT_FOREACH_MESH_BEGIN(elem, index_lvert, params, mr) \ | #define EXTRACT_LVERT_FOREACH_MESH_BEGIN(elem, index_lvert, params, mr) \ | ||||
| CHECK_TYPE(params, const ExtractLVertMesh_Params *); \ | CHECK_TYPE(params, const ExtractLVertMesh_Params *); \ | ||||
| { \ | { \ | ||||
| const MVert *mvert = mr->mvert; \ | const MVert *mvert = mr->mvert; \ | ||||
| const int *lverts = (params)->lvert; \ | const int *lverts = (params)->lvert; \ | ||||
| const int _lvert_index_end = (params)->lvert_range[1]; \ | const int _lvert_index_end = (params)->lvert_range[1]; \ | ||||
| Show All 34 Lines | typedef struct MeshExtract { | ||||
| ExtractLVertBMeshFn *iter_lvert_bm; | ExtractLVertBMeshFn *iter_lvert_bm; | ||||
| ExtractLVertMeshFn *iter_lvert_mesh; | ExtractLVertMeshFn *iter_lvert_mesh; | ||||
| /** Executed on one worker thread after all elements iterations. */ | /** Executed on one worker thread after all elements iterations. */ | ||||
| ExtractFinishFn *finish; | ExtractFinishFn *finish; | ||||
| /** Used to request common data. */ | /** Used to request common data. */ | ||||
| const eMRDataType data_flag; | const eMRDataType data_flag; | ||||
| /** Used to know if the element callbacks are thread-safe and can be parallelized. */ | /** Used to know if the element callbacks are thread-safe and can be parallelized. */ | ||||
| const bool use_threading; | const bool use_threading; | ||||
| /** | |||||
| * Offset in bytes of the buffer inside a MeshBufferCache instance. Points to a vertex or index | |||||
| * buffer. | |||||
| */ | |||||
| const size_t mesh_buffer_offset; | |||||
| } MeshExtract; | } MeshExtract; | ||||
| static void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferCache *mbc) | |||||
| { | |||||
| /* NOTE: POINTER_OFFSET on windows platforms casts internally to `void *`, but on GCC/CLANG to | |||||
mano-wii: Here it looks like you can use the macro `POINTER_OFFSET` | |||||
| * `MeshBufferCache *`. What shows a different usage versus intent. */ | |||||
| void **buffer_ptr = (void **)POINTER_OFFSET(mbc, extractor->mesh_buffer_offset); | |||||
| void *buffer = *buffer_ptr; | |||||
| BLI_assert(buffer); | |||||
| return buffer; | |||||
| } | |||||
| typedef struct MeshExtractRunData { | |||||
| const MeshExtract *extractor; | |||||
| void *buffer; | |||||
| void *user_data; | |||||
| } MeshExtractRunData; | |||||
| typedef struct MeshExtractRunDataArray { | |||||
Done Inline ActionsAlthough it does not avoid the '4' bytes padding after member len, wouldn't that member be better at the end of the struct? mano-wii: Although it does not avoid the '4' bytes padding after member `len`, wouldn't that member be… | |||||
Done Inline ActionsNot in this case. Adding the len at the start would enable prefetching. Will add a comment for that. jbakker: Not in this case. Adding the len at the start would enable prefetching. Will add a comment for… | |||||
Done Inline ActionsSecond thoughts that it doesn’t matter that much. It is just the way how I think about cpu optimized code. In cpp we would replace this with an blender array and would be hidden. jbakker: Second thoughts that it doesn’t matter that much. It is just the way how I think about cpu… | |||||
Done Inline ActionsOn second thought, keeping the MeshExtractRunData at the end can be good for structure with variable size. mano-wii: On second thought, keeping the `MeshExtractRunData` at the end can be good for structure with… | |||||
| int len; | |||||
| MeshExtractRunData items[M_EXTRACT_LEN]; | |||||
| } MeshExtractRunDataArray; | |||||
| static void mesh_extract_run_data_array_init(MeshExtractRunDataArray *array) | |||||
| { | |||||
| array->len = 0; | |||||
| } | |||||
| static void mesh_extract_run_data_array_add_ex(MeshExtractRunDataArray *array, | |||||
| const MeshExtractRunData *run_data) | |||||
| { | |||||
| array->items[array->len] = *run_data; | |||||
| array->len++; | |||||
| } | |||||
| static void mesh_extract_run_data_array_add(MeshExtractRunDataArray *array, | |||||
| const MeshExtract *extractor) | |||||
| { | |||||
| MeshExtractRunData run_data; | |||||
| run_data.extractor = extractor; | |||||
| run_data.buffer = NULL; | |||||
| run_data.user_data = NULL; | |||||
| mesh_extract_run_data_array_add_ex(array, &run_data); | |||||
| } | |||||
| static void mesh_extract_run_data_array_filter_iter_type(const MeshExtractRunDataArray *src, | |||||
| MeshExtractRunDataArray *dst, | |||||
| eMRIterType iter_type) | |||||
| { | |||||
| for (int i = 0; i < src->len; i++) { | |||||
| const MeshExtractRunData *data = &src->items[i]; | |||||
| const MeshExtract *extractor = data->extractor; | |||||
| if ((iter_type & MR_ITER_LOOPTRI) && extractor->iter_looptri_bm) { | |||||
| BLI_assert(extractor->iter_looptri_mesh); | |||||
| mesh_extract_run_data_array_add_ex(dst, data); | |||||
| continue; | |||||
| } | |||||
| if ((iter_type & MR_ITER_POLY) && extractor->iter_poly_bm) { | |||||
| BLI_assert(extractor->iter_poly_mesh); | |||||
| mesh_extract_run_data_array_add_ex(dst, data); | |||||
| continue; | |||||
| } | |||||
| if ((iter_type & MR_ITER_LEDGE) && extractor->iter_ledge_bm) { | |||||
| BLI_assert(extractor->iter_ledge_mesh); | |||||
| mesh_extract_run_data_array_add_ex(dst, data); | |||||
| continue; | |||||
| } | |||||
| if ((iter_type & MR_ITER_LVERT) && extractor->iter_lvert_bm) { | |||||
| BLI_assert(extractor->iter_lvert_mesh); | |||||
| mesh_extract_run_data_array_add_ex(dst, data); | |||||
| continue; | |||||
| } | |||||
| } | |||||
| } | |||||
| static void mesh_extract_run_data_array_filter_threading( | |||||
| const MeshExtractRunDataArray *src, MeshExtractRunDataArray *dst_multi_threaded) | |||||
| { | |||||
| for (int i = 0; i < src->len; i++) { | |||||
| const MeshExtract *extractor = src->items[i].extractor; | |||||
| if (extractor->use_threading) { | |||||
| mesh_extract_run_data_array_add(dst_multi_threaded, extractor); | |||||
| } | |||||
| } | |||||
| } | |||||
| BLI_INLINE eMRIterType mesh_extract_iter_type(const MeshExtract *ext) | BLI_INLINE eMRIterType mesh_extract_iter_type(const MeshExtract *ext) | ||||
| { | { | ||||
| eMRIterType type = 0; | eMRIterType type = 0; | ||||
| SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri_mesh), MR_ITER_LOOPTRI); | 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_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_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); | SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert_mesh), MR_ITER_LVERT); | ||||
| return type; | return type; | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | static void *extract_tris_init(const MeshRenderData *mr, | ||||
| int visible_tri_tot = ofs; | int visible_tri_tot = ofs; | ||||
| GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, visible_tri_tot, mr->loop_len); | GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, visible_tri_tot, mr->loop_len); | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_tris_iter_looptri_bm(const MeshRenderData *mr, | static void extract_tris_iter_looptri_bm(const MeshRenderData *mr, | ||||
| const struct ExtractTriBMesh_Params *params, | BMLoop **elt, | ||||
| const int UNUSED(elt_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_Tri_Data *data = _data; | MeshExtract_Tri_Data *data = _data; | ||||
| const int mat_last = mr->mat_len - 1; | 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)) { | if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { | ||||
| int *mat_tri_ofs = data->tri_mat_end; | int *mat_tri_ofs = data->tri_mat_end; | ||||
| const int mat = min_ii(elt[0]->f->mat_nr, mat_last); | const int mat = min_ii(elt[0]->f->mat_nr, mat_last); | ||||
| GPU_indexbuf_set_tri_verts(&data->elb, | GPU_indexbuf_set_tri_verts(&data->elb, | ||||
| mat_tri_ofs[mat]++, | mat_tri_ofs[mat]++, | ||||
| BM_elem_index_get(elt[0]), | BM_elem_index_get(elt[0]), | ||||
| BM_elem_index_get(elt[1]), | BM_elem_index_get(elt[1]), | ||||
| BM_elem_index_get(elt[2])); | BM_elem_index_get(elt[2])); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_tris_iter_looptri_mesh(const MeshRenderData *mr, | static void extract_tris_iter_looptri_mesh(const MeshRenderData *mr, | ||||
| const struct ExtractTriMesh_Params *params, | const MLoopTri *mlt, | ||||
| const int UNUSED(elt_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_Tri_Data *data = _data; | MeshExtract_Tri_Data *data = _data; | ||||
| const int mat_last = mr->mat_len - 1; | 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]; | const MPoly *mp = &mr->mpoly[mlt->poly]; | ||||
| if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | ||||
| int *mat_tri_ofs = data->tri_mat_end; | int *mat_tri_ofs = data->tri_mat_end; | ||||
| const int mat = min_ii(mp->mat_nr, mat_last); | const int mat = min_ii(mp->mat_nr, mat_last); | ||||
| GPU_indexbuf_set_tri_verts( | GPU_indexbuf_set_tri_verts( | ||||
| &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]); | &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, | static void extract_tris_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| void *ibo, | void *buf, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| MeshExtract_Tri_Data *data = _data; | MeshExtract_Tri_Data *data = _data; | ||||
| GPU_indexbuf_build_in_place(&data->elb, ibo); | GPU_indexbuf_build_in_place(&data->elb, ibo); | ||||
| /* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch | /* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch | ||||
| * is created before the surfaces-per-material. */ | * is created before the surfaces-per-material. */ | ||||
| if (mr->use_final_mesh && cache->final.tris_per_mat) { | if (mr->use_final_mesh && cache->final.tris_per_mat) { | ||||
| MeshBufferCache *mbc = &cache->final; | MeshBufferCache *mbc_final = &cache->final; | ||||
| for (int i = 0; i < mr->mat_len; i++) { | for (int i = 0; i < mr->mat_len; i++) { | ||||
| /* These IBOs have not been queried yet but we create them just in case they are needed | /* These IBOs have not been queried yet but we create them just in case they are needed | ||||
| * later since they are not tracked by mesh_buffer_cache_create_requested(). */ | * later since they are not tracked by mesh_buffer_cache_create_requested(). */ | ||||
| if (mbc->tris_per_mat[i] == NULL) { | if (mbc_final->tris_per_mat[i] == NULL) { | ||||
| mbc->tris_per_mat[i] = GPU_indexbuf_calloc(); | mbc_final->tris_per_mat[i] = GPU_indexbuf_calloc(); | ||||
| } | } | ||||
| /* Multiply by 3 because these are triangle indices. */ | /* Multiply by 3 because these are triangle indices. */ | ||||
| const int mat_start = data->tri_mat_start[i]; | const int mat_start = data->tri_mat_start[i]; | ||||
| const int mat_end = data->tri_mat_end[i]; | const int mat_end = data->tri_mat_end[i]; | ||||
| const int start = mat_start * 3; | const int start = mat_start * 3; | ||||
| const int len = (mat_end - mat_start) * 3; | const int len = (mat_end - mat_start) * 3; | ||||
| GPU_indexbuf_create_subrange_in_place(mbc->tris_per_mat[i], ibo, start, len); | GPU_indexbuf_create_subrange_in_place(mbc_final->tris_per_mat[i], ibo, start, len); | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(data->tri_mat_start); | MEM_freeN(data->tri_mat_start); | ||||
| MEM_freeN(data->tri_mat_end); | MEM_freeN(data->tri_mat_end); | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_tris = { | static const MeshExtract extract_tris = { | ||||
| .init = extract_tris_init, | .init = extract_tris_init, | ||||
| .iter_looptri_bm = extract_tris_iter_looptri_bm, | .iter_looptri_bm = extract_tris_iter_looptri_bm, | ||||
| .iter_looptri_mesh = extract_tris_iter_looptri_mesh, | .iter_looptri_mesh = extract_tris_iter_looptri_mesh, | ||||
| .finish = extract_tris_finish, | .finish = extract_tris_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.tris)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edges Indices | /** \name Extract Edges Indices | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_lines_init(const MeshRenderData *mr, | static void *extract_lines_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf)) | void *UNUSED(buf)) | ||||
| { | { | ||||
| GPUIndexBufBuilder *elb = MEM_mallocN(sizeof(*elb), __func__); | GPUIndexBufBuilder *elb = MEM_mallocN(sizeof(*elb), __func__); | ||||
| /* Put loose edges at the end. */ | /* Put loose edges at the end. */ | ||||
| GPU_indexbuf_init( | GPU_indexbuf_init( | ||||
| elb, GPU_PRIM_LINES, mr->edge_len + mr->edge_loose_len, mr->loop_len + mr->loop_loose_len); | elb, GPU_PRIM_LINES, mr->edge_len + mr->edge_loose_len, mr->loop_len + mr->loop_loose_len); | ||||
| return elb; | return elb; | ||||
| } | } | ||||
| static void extract_lines_iter_poly_bm(const MeshRenderData *mr, | static void extract_lines_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *elb) | 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; | BMLoop *l_iter, *l_first; | ||||
| /* Use #BMLoop.prev to match mesh order (to avoid minor differences in data extraction). */ | /* Use #BMLoop.prev to match mesh order (to avoid minor differences in data extraction). */ | ||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f)->prev; | l_iter = l_first = BM_FACE_FIRST_LOOP(f)->prev; | ||||
| do { | do { | ||||
| if (!BM_elem_flag_test(l_iter->e, BM_ELEM_HIDDEN)) { | if (!BM_elem_flag_test(l_iter->e, BM_ELEM_HIDDEN)) { | ||||
| GPU_indexbuf_set_line_verts(elb, | GPU_indexbuf_set_line_verts(elb, | ||||
| BM_elem_index_get(l_iter->e), | BM_elem_index_get(l_iter->e), | ||||
| BM_elem_index_get(l_iter), | BM_elem_index_get(l_iter), | ||||
| BM_elem_index_get(l_iter->next)); | BM_elem_index_get(l_iter->next)); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(l_iter->e)); | GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(l_iter->e)); | ||||
| } | } | ||||
| } while ((l_iter = l_iter->next) != l_first); | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, | static void extract_lines_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| /* Using poly & loop iterator would complicate accessing the adjacent loop. */ | /* Using poly & loop iterator would complicate accessing the adjacent loop. */ | ||||
| const MLoop *mloop = mr->mloop; | const MLoop *mloop = mr->mloop; | ||||
| const MEdge *medge = mr->medge; | const MEdge *medge = mr->medge; | ||||
| if (mr->use_hide || (mr->extract_type == MR_EXTRACT_MAPPED) || (mr->e_origindex != NULL)) { | 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); | const int ml_index_last = mp->loopstart + (mp->totloop - 1); | ||||
| int ml_index = ml_index_last, ml_index_next = mp->loopstart; | int ml_index = ml_index_last, ml_index_next = mp->loopstart; | ||||
| do { | do { | ||||
| const MLoop *ml = &mloop[ml_index]; | const MLoop *ml = &mloop[ml_index]; | ||||
| const MEdge *med = &medge[ml->e]; | const MEdge *med = &medge[ml->e]; | ||||
| if (!((mr->use_hide && (med->flag & ME_HIDE)) || | if (!((mr->use_hide && (med->flag & ME_HIDE)) || | ||||
| ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && | ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && | ||||
| (mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) { | (mr->e_origindex[ml->e] == ORIGINDEX_NONE)))) { | ||||
| GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); | GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_line_restart(elb, ml->e); | GPU_indexbuf_set_line_restart(elb, ml->e); | ||||
| } | } | ||||
| } while ((ml_index = ml_index_next++) != ml_index_last); | } while ((ml_index = ml_index_next++) != ml_index_last); | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| } | |||||
| else { | else { | ||||
| EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) | |||||
| { | |||||
| const int ml_index_last = mp->loopstart + (mp->totloop - 1); | const int ml_index_last = mp->loopstart + (mp->totloop - 1); | ||||
| int ml_index = ml_index_last, ml_index_next = mp->loopstart; | int ml_index = ml_index_last, ml_index_next = mp->loopstart; | ||||
| do { | do { | ||||
| const MLoop *ml = &mloop[ml_index]; | const MLoop *ml = &mloop[ml_index]; | ||||
| GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); | GPU_indexbuf_set_line_verts(elb, ml->e, ml_index, ml_index_next); | ||||
| } while ((ml_index = ml_index_next++) != ml_index_last); | } while ((ml_index = ml_index_next++) != ml_index_last); | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| } | |||||
| } | } | ||||
| static void extract_lines_iter_ledge_bm(const MeshRenderData *mr, | static void extract_lines_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) | |||||
| { | |||||
| const int l_index_offset = mr->edge_len + ledge_index; | const int l_index_offset = mr->edge_len + ledge_index; | ||||
| if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { | if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { | ||||
| const int l_index = mr->loop_len + ledge_index * 2; | const int l_index = mr->loop_len + ledge_index * 2; | ||||
| GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1); | GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_line_restart(elb, l_index_offset); | GPU_indexbuf_set_line_restart(elb, l_index_offset); | ||||
| } | } | ||||
| /* Don't render the edge twice. */ | /* Don't render the edge twice. */ | ||||
| GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed)); | GPU_indexbuf_set_line_restart(elb, BM_elem_index_get(eed)); | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr, | static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *med, | ||||
| const uint ledge_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) | |||||
| { | |||||
| const int l_index_offset = mr->edge_len + ledge_index; | const int l_index_offset = mr->edge_len + ledge_index; | ||||
| const int e_index = mr->ledges[ledge_index]; | const int e_index = mr->ledges[ledge_index]; | ||||
| if (!((mr->use_hide && (med->flag & ME_HIDE)) || | if (!((mr->use_hide && (med->flag & ME_HIDE)) || | ||||
| ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && | ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && | ||||
| (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { | (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { | ||||
| const int l_index = mr->loop_len + ledge_index * 2; | const int l_index = mr->loop_len + ledge_index * 2; | ||||
| GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1); | GPU_indexbuf_set_line_verts(elb, l_index_offset, l_index, l_index + 1); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_line_restart(elb, l_index_offset); | GPU_indexbuf_set_line_restart(elb, l_index_offset); | ||||
| } | } | ||||
| /* Don't render the edge twice. */ | /* Don't render the edge twice. */ | ||||
| GPU_indexbuf_set_line_restart(elb, e_index); | GPU_indexbuf_set_line_restart(elb, e_index); | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_lines_finish(const MeshRenderData *UNUSED(mr), | static void extract_lines_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| GPU_indexbuf_build_in_place(elb, ibo); | GPU_indexbuf_build_in_place(elb, ibo); | ||||
| MEM_freeN(elb); | MEM_freeN(elb); | ||||
| } | } | ||||
| static const MeshExtract extract_lines = { | static const MeshExtract extract_lines = { | ||||
| .init = extract_lines_init, | .init = extract_lines_init, | ||||
| .iter_poly_bm = extract_lines_iter_poly_bm, | .iter_poly_bm = extract_lines_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_lines_iter_poly_mesh, | .iter_poly_mesh = extract_lines_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_lines_iter_ledge_bm, | .iter_ledge_bm = extract_lines_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_lines_iter_ledge_mesh, | .iter_ledge_mesh = extract_lines_iter_ledge_mesh, | ||||
| .finish = extract_lines_finish, | .finish = extract_lines_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Loose Edges Sub Buffer | /** \name Extract Loose Edges Sub Buffer | ||||
| * \{ */ | * \{ */ | ||||
| static void extract_lines_loose_subbuffer(const MeshRenderData *mr, struct MeshBatchCache *cache) | static void extract_lines_loose_subbuffer(const MeshRenderData *mr, struct MeshBatchCache *cache) | ||||
| { | { | ||||
| BLI_assert(cache->final.ibo.lines); | BLI_assert(cache->final.ibo.lines); | ||||
| /* Multiply by 2 because these are edges indices. */ | /* Multiply by 2 because these are edges indices. */ | ||||
| const int start = mr->edge_len * 2; | const int start = mr->edge_len * 2; | ||||
| const int len = mr->edge_loose_len * 2; | const int len = mr->edge_loose_len * 2; | ||||
| GPU_indexbuf_create_subrange_in_place( | GPU_indexbuf_create_subrange_in_place( | ||||
| cache->final.ibo.lines_loose, cache->final.ibo.lines, start, len); | cache->final.ibo.lines_loose, cache->final.ibo.lines, start, len); | ||||
| cache->no_loose_wire = (len == 0); | cache->no_loose_wire = (len == 0); | ||||
| } | } | ||||
| static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, | static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| void *ibo, | void *buf, | ||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| GPU_indexbuf_build_in_place(elb, ibo); | GPU_indexbuf_build_in_place(elb, ibo); | ||||
| extract_lines_loose_subbuffer(mr, cache); | extract_lines_loose_subbuffer(mr, cache); | ||||
| MEM_freeN(elb); | MEM_freeN(elb); | ||||
| } | } | ||||
| static const MeshExtract extract_lines_with_lines_loose = { | static const MeshExtract extract_lines_with_lines_loose = { | ||||
| .init = extract_lines_init, | .init = extract_lines_init, | ||||
| .iter_poly_bm = extract_lines_iter_poly_bm, | .iter_poly_bm = extract_lines_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_lines_iter_poly_mesh, | .iter_poly_mesh = extract_lines_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_lines_iter_ledge_bm, | .iter_ledge_bm = extract_lines_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_lines_iter_ledge_mesh, | .iter_ledge_mesh = extract_lines_iter_ledge_mesh, | ||||
| .finish = extract_lines_with_lines_loose_finish, | .finish = extract_lines_with_lines_loose_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Point Indices | /** \name Extract Point Indices | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_points_init(const MeshRenderData *mr, | static void *extract_points_init(const MeshRenderData *mr, | ||||
| Show All 27 Lines | if (!((mr->use_hide && (mv->flag & ME_HIDE)) || | ||||
| (mr->v_origindex[v_index] == ORIGINDEX_NONE)))) { | (mr->v_origindex[v_index] == ORIGINDEX_NONE)))) { | ||||
| GPU_indexbuf_set_point_vert(elb, v_index, l_index); | GPU_indexbuf_set_point_vert(elb, v_index, l_index); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_point_restart(elb, v_index); | GPU_indexbuf_set_point_restart(elb, v_index); | ||||
| } | } | ||||
| } | } | ||||
| static void extract_points_iter_poly_bm(const MeshRenderData *mr, | static void extract_points_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| vert_set_bm(elb, l->v, l_index); | do { | ||||
| } | const int l_index = BM_elem_index_get(l_iter); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| vert_set_bm(elb, l_iter->v, l_index); | |||||
| } while ((l_iter = l_iter->next) != l_first); | |||||
| } | } | ||||
| static void extract_points_iter_poly_mesh(const MeshRenderData *mr, | static void extract_points_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| vert_set_mesh(elb, mr, ml->v, ml_index); | vert_set_mesh(elb, mr, ml->v, ml_index); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static void extract_points_iter_ledge_bm(const MeshRenderData *mr, | static void extract_points_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| 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->v1, mr->loop_len + (ledge_index * 2)); | ||||
| vert_set_bm(elb, eed->v2, mr->loop_len + (ledge_index * 2) + 1); | vert_set_bm(elb, eed->v2, mr->loop_len + (ledge_index * 2) + 1); | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_points_iter_ledge_mesh(const MeshRenderData *mr, | static void extract_points_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *med, | ||||
| const uint ledge_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| 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->v1, mr->loop_len + (ledge_index * 2)); | ||||
| vert_set_mesh(elb, mr, med->v2, mr->loop_len + (ledge_index * 2) + 1); | vert_set_mesh(elb, mr, med->v2, mr->loop_len + (ledge_index * 2) + 1); | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_points_iter_lvert_bm(const MeshRenderData *mr, | static void extract_points_iter_lvert_bm(const MeshRenderData *mr, | ||||
| const ExtractLVertBMesh_Params *params, | BMVert *eve, | ||||
| const int lvert_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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); | vert_set_bm(elb, eve, offset + lvert_index); | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_points_iter_lvert_mesh(const MeshRenderData *mr, | static void extract_points_iter_lvert_mesh(const MeshRenderData *mr, | ||||
| const ExtractLVertMesh_Params *params, | const MVert *UNUSED(mv), | ||||
| const int lvert_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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); | 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), | static void extract_points_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| GPU_indexbuf_build_in_place(elb, ibo); | GPU_indexbuf_build_in_place(elb, ibo); | ||||
| MEM_freeN(elb); | MEM_freeN(elb); | ||||
| } | } | ||||
| static const MeshExtract extract_points = { | static const MeshExtract extract_points = { | ||||
| .init = extract_points_init, | .init = extract_points_init, | ||||
| .iter_poly_bm = extract_points_iter_poly_bm, | .iter_poly_bm = extract_points_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_points_iter_poly_mesh, | .iter_poly_mesh = extract_points_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_points_iter_ledge_bm, | .iter_ledge_bm = extract_points_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_points_iter_ledge_mesh, | .iter_ledge_mesh = extract_points_iter_ledge_mesh, | ||||
| .iter_lvert_bm = extract_points_iter_lvert_bm, | .iter_lvert_bm = extract_points_iter_lvert_bm, | ||||
| .iter_lvert_mesh = extract_points_iter_lvert_mesh, | .iter_lvert_mesh = extract_points_iter_lvert_mesh, | ||||
| .finish = extract_points_finish, | .finish = extract_points_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.points)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Facedots Indices | /** \name Extract Facedots Indices | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_fdots_init(const MeshRenderData *mr, | static void *extract_fdots_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf)) | void *UNUSED(buf)) | ||||
| { | { | ||||
| GPUIndexBufBuilder *elb = MEM_mallocN(sizeof(*elb), __func__); | GPUIndexBufBuilder *elb = MEM_mallocN(sizeof(*elb), __func__); | ||||
| GPU_indexbuf_init(elb, GPU_PRIM_POINTS, mr->poly_len, mr->poly_len); | GPU_indexbuf_init(elb, GPU_PRIM_POINTS, mr->poly_len, mr->poly_len); | ||||
| return elb; | return elb; | ||||
| } | } | ||||
| static void extract_fdots_iter_poly_bm(const MeshRenderData *mr, | static void extract_fdots_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int f_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) | |||||
| { | |||||
| if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { | if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { | ||||
| GPU_indexbuf_set_point_vert(elb, f_index, f_index); | GPU_indexbuf_set_point_vert(elb, f_index, f_index); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_point_restart(elb, f_index); | GPU_indexbuf_set_point_restart(elb, f_index); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, | static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| if (mr->use_subsurf_fdots) { | if (mr->use_subsurf_fdots) { | ||||
| /* Check #ME_VERT_FACEDOT. */ | /* Check #ME_VERT_FACEDOT. */ | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| const MVert *mv = &mr->mvert[ml->v]; | const MVert *mv = &mr->mvert[ml->v]; | ||||
| if ((mv->flag & ME_VERT_FACEDOT) && !(mr->use_hide && (mp->flag & ME_HIDE))) { | if ((mv->flag & ME_VERT_FACEDOT) && !(mr->use_hide && (mp->flag & ME_HIDE))) { | ||||
| GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); | GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); | ||||
| } | return; | ||||
| else { | |||||
| GPU_indexbuf_set_point_restart(elb, mp_index); | |||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | GPU_indexbuf_set_point_restart(elb, mp_index); | ||||
| } | } | ||||
| else { | else { | ||||
| EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) | |||||
| { | |||||
| if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | ||||
| GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); | GPU_indexbuf_set_point_vert(elb, mp_index, mp_index); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_point_restart(elb, mp_index); | GPU_indexbuf_set_point_restart(elb, mp_index); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| } | |||||
| } | } | ||||
| static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), | static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *elb) | void *elb) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| GPU_indexbuf_build_in_place(elb, ibo); | GPU_indexbuf_build_in_place(elb, ibo); | ||||
| MEM_freeN(elb); | MEM_freeN(elb); | ||||
| } | } | ||||
| static const MeshExtract extract_fdots = { | static const MeshExtract extract_fdots = { | ||||
| .init = extract_fdots_init, | .init = extract_fdots_init, | ||||
| .iter_poly_bm = extract_fdots_iter_poly_bm, | .iter_poly_bm = extract_fdots_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_fdots_iter_poly_mesh, | .iter_poly_mesh = extract_fdots_iter_poly_mesh, | ||||
| .finish = extract_fdots_finish, | .finish = extract_fdots_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.fdots)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Paint Mask Line Indices | /** \name Extract Paint Mask Line Indices | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshExtract_LinePaintMask_Data { | typedef struct MeshExtract_LinePaintMask_Data { | ||||
| GPUIndexBufBuilder elb; | GPUIndexBufBuilder elb; | ||||
| /** One bit per edge set if face is selected. */ | /** One bit per edge set if face is selected. */ | ||||
| BLI_bitmap select_map[0]; | BLI_bitmap select_map[0]; | ||||
| } MeshExtract_LinePaintMask_Data; | } MeshExtract_LinePaintMask_Data; | ||||
| static void *extract_lines_paint_mask_init(const MeshRenderData *mr, | static void *extract_lines_paint_mask_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf)) | void *UNUSED(ibo)) | ||||
| { | { | ||||
| size_t bitmap_size = BLI_BITMAP_SIZE(mr->edge_len); | size_t bitmap_size = BLI_BITMAP_SIZE(mr->edge_len); | ||||
| MeshExtract_LinePaintMask_Data *data = MEM_callocN(sizeof(*data) + bitmap_size, __func__); | MeshExtract_LinePaintMask_Data *data = MEM_callocN(sizeof(*data) + bitmap_size, __func__); | ||||
| GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr->edge_len, mr->loop_len); | GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr->edge_len, mr->loop_len); | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, | static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_LinePaintMask_Data *data = _data; | MeshExtract_LinePaintMask_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| const int e_index = ml->e; | const int e_index = ml->e; | ||||
| const MEdge *me = &mr->medge[e_index]; | const MEdge *me = &mr->medge[e_index]; | ||||
| if (!((mr->use_hide && (me->flag & ME_HIDE)) || | if (!((mr->use_hide && (me->flag & ME_HIDE)) || | ||||
| ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && | ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && | ||||
| (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { | (mr->e_origindex[e_index] == ORIGINDEX_NONE)))) { | ||||
| const int ml_index_last = mp->totloop + mp->loopstart - 1; | 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 int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); | ||||
| Show All 13 Lines | if (!((mr->use_hide && (me->flag & ME_HIDE)) || | ||||
| GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other); | GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_line_restart(&data->elb, e_index); | GPU_indexbuf_set_line_restart(&data->elb, e_index); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), | static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| MeshExtract_LinePaintMask_Data *data = _data; | MeshExtract_LinePaintMask_Data *data = _data; | ||||
| GPU_indexbuf_build_in_place(&data->elb, ibo); | GPU_indexbuf_build_in_place(&data->elb, ibo); | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_lines_paint_mask = { | static const MeshExtract extract_lines_paint_mask = { | ||||
| .init = extract_lines_paint_mask_init, | .init = extract_lines_paint_mask_init, | ||||
| .iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh, | .iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh, | ||||
| .finish = extract_lines_paint_mask_finish, | .finish = extract_lines_paint_mask_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_paint_mask)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Line Adjacency Indices | /** \name Extract Line Adjacency Indices | ||||
| * \{ */ | * \{ */ | ||||
| #define NO_EDGE INT_MAX | #define NO_EDGE INT_MAX | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | else { | ||||
| else { | else { | ||||
| GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l_opposite); | GPU_indexbuf_add_line_adj_verts(elb, l1, l2, l3, l_opposite); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData *UNUSED(mr), | static void extract_lines_adjacency_iter_looptri_bm(const MeshRenderData *UNUSED(mr), | ||||
| const struct ExtractTriBMesh_Params *params, | BMLoop **elt, | ||||
| const int UNUSED(elt_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params) | |||||
| { | |||||
| if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { | if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) { | ||||
| lines_adjacency_triangle(BM_elem_index_get(elt[0]->v), | lines_adjacency_triangle(BM_elem_index_get(elt[0]->v), | ||||
| BM_elem_index_get(elt[1]->v), | BM_elem_index_get(elt[1]->v), | ||||
| BM_elem_index_get(elt[2]->v), | BM_elem_index_get(elt[2]->v), | ||||
| BM_elem_index_get(elt[0]), | BM_elem_index_get(elt[0]), | ||||
| BM_elem_index_get(elt[1]), | BM_elem_index_get(elt[1]), | ||||
| BM_elem_index_get(elt[2]), | BM_elem_index_get(elt[2]), | ||||
| data); | data); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr, | static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr, | ||||
| const struct ExtractTriMesh_Params *params, | const MLoopTri *mlt, | ||||
| const int UNUSED(elt_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params) | |||||
| { | |||||
| const MPoly *mp = &mr->mpoly[mlt->poly]; | const MPoly *mp = &mr->mpoly[mlt->poly]; | ||||
| if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | if (!(mr->use_hide && (mp->flag & ME_HIDE))) { | ||||
| lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v, | lines_adjacency_triangle(mr->mloop[mlt->tri[0]].v, | ||||
| mr->mloop[mlt->tri[1]].v, | mr->mloop[mlt->tri[1]].v, | ||||
| mr->mloop[mlt->tri[2]].v, | mr->mloop[mlt->tri[2]].v, | ||||
| mlt->tri[0], | mlt->tri[0], | ||||
| mlt->tri[1], | mlt->tri[1], | ||||
| mlt->tri[2], | mlt->tri[2], | ||||
| data); | data); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr), | static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| void *ibo, | void *buf, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| MeshExtract_LineAdjacency_Data *data = _data; | MeshExtract_LineAdjacency_Data *data = _data; | ||||
| /* Create edges for remaining non manifold edges. */ | /* Create edges for remaining non manifold edges. */ | ||||
| EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh); | EdgeHashIterator *ehi = BLI_edgehashIterator_new(data->eh); | ||||
| for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { | for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { | ||||
| uint v2, v3, l1, l2, l3; | uint v2, v3, l1, l2, l3; | ||||
| int v_data = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); | int v_data = POINTER_AS_INT(BLI_edgehashIterator_getValue(ehi)); | ||||
| if (v_data != NO_EDGE) { | if (v_data != NO_EDGE) { | ||||
| BLI_edgehashIterator_getKey(ehi, &v2, &v3); | BLI_edgehashIterator_getKey(ehi, &v2, &v3); | ||||
| Show All 20 Lines | |||||
| static const MeshExtract extract_lines_adjacency = { | static const MeshExtract extract_lines_adjacency = { | ||||
| .init = extract_lines_adjacency_init, | .init = extract_lines_adjacency_init, | ||||
| .iter_looptri_bm = extract_lines_adjacency_iter_looptri_bm, | .iter_looptri_bm = extract_lines_adjacency_iter_looptri_bm, | ||||
| .iter_looptri_mesh = extract_lines_adjacency_iter_looptri_mesh, | .iter_looptri_mesh = extract_lines_adjacency_iter_looptri_mesh, | ||||
| .finish = extract_lines_adjacency_finish, | .finish = extract_lines_adjacency_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.lines_adjacency)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit UV Triangles Indices | /** \name Extract Edit UV Triangles Indices | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshExtract_EditUvElem_Data { | typedef struct MeshExtract_EditUvElem_Data { | ||||
| Show All 15 Lines | BLI_INLINE void edituv_tri_add( | ||||
| MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2, int v3) | MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2, int v3) | ||||
| { | { | ||||
| if (!hidden && (data->sync_selection || selected)) { | if (!hidden && (data->sync_selection || selected)) { | ||||
| GPU_indexbuf_add_tri_verts(&data->elb, v1, v2, v3); | GPU_indexbuf_add_tri_verts(&data->elb, v1, v2, v3); | ||||
| } | } | ||||
| } | } | ||||
| static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData *UNUSED(mr), | static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData *UNUSED(mr), | ||||
| const struct ExtractTriBMesh_Params *params, | BMLoop **elt, | ||||
| const int UNUSED(elt_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, _elt_index, params) | |||||
| { | |||||
| edituv_tri_add(data, | edituv_tri_add(data, | ||||
| BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN), | BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN), | ||||
| BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT), | BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT), | ||||
| BM_elem_index_get(elt[0]), | BM_elem_index_get(elt[0]), | ||||
| BM_elem_index_get(elt[1]), | BM_elem_index_get(elt[1]), | ||||
| BM_elem_index_get(elt[2])); | BM_elem_index_get(elt[2])); | ||||
| } | } | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr, | static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr, | ||||
| const struct ExtractTriMesh_Params *params, | const MLoopTri *mlt, | ||||
| const int UNUSED(elt_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, _mlt_index, params) | |||||
| { | |||||
| const MPoly *mp = &mr->mpoly[mlt->poly]; | const MPoly *mp = &mr->mpoly[mlt->poly]; | ||||
| edituv_tri_add(data, | edituv_tri_add(data, | ||||
| (mp->flag & ME_HIDE) != 0, | (mp->flag & ME_HIDE) != 0, | ||||
| (mp->flag & ME_FACE_SEL) != 0, | (mp->flag & ME_FACE_SEL) != 0, | ||||
| mlt->tri[0], | mlt->tri[0], | ||||
| mlt->tri[1], | mlt->tri[1], | ||||
| mlt->tri[2]); | mlt->tri[2]); | ||||
| } | } | ||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), | static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| MeshExtract_EditUvElem_Data *extract_data = data; | MeshExtract_EditUvElem_Data *extract_data = data; | ||||
| GPU_indexbuf_build_in_place(&extract_data->elb, ibo); | GPU_indexbuf_build_in_place(&extract_data->elb, ibo); | ||||
| MEM_freeN(extract_data); | MEM_freeN(extract_data); | ||||
| } | } | ||||
| static const MeshExtract extract_edituv_tris = { | static const MeshExtract extract_edituv_tris = { | ||||
| .init = extract_edituv_tris_init, | .init = extract_edituv_tris_init, | ||||
| .iter_looptri_bm = extract_edituv_tris_iter_looptri_bm, | .iter_looptri_bm = extract_edituv_tris_iter_looptri_bm, | ||||
| .iter_looptri_mesh = extract_edituv_tris_iter_looptri_mesh, | .iter_looptri_mesh = extract_edituv_tris_iter_looptri_mesh, | ||||
| .finish = extract_edituv_tris_finish, | .finish = extract_edituv_tris_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_tris)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit UV Line Indices around faces | /** \name Extract Edit UV Line Indices around faces | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_edituv_lines_init(const MeshRenderData *mr, | static void *extract_edituv_lines_init(const MeshRenderData *mr, | ||||
| Show All 10 Lines | |||||
| BLI_INLINE void edituv_edge_add( | BLI_INLINE void edituv_edge_add( | ||||
| MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2) | MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2) | ||||
| { | { | ||||
| if (!hidden && (data->sync_selection || selected)) { | if (!hidden && (data->sync_selection || selected)) { | ||||
| GPU_indexbuf_add_line_verts(&data->elb, v1, v2); | GPU_indexbuf_add_line_verts(&data->elb, v1, v2); | ||||
| } | } | ||||
| } | } | ||||
| static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *mr, | static void extract_edituv_lines_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| edituv_edge_add(data, | edituv_edge_add(data, | ||||
| BM_elem_flag_test(loop->f, BM_ELEM_HIDDEN), | BM_elem_flag_test_bool(f, BM_ELEM_HIDDEN), | ||||
| BM_elem_flag_test(loop->f, BM_ELEM_SELECT), | BM_elem_flag_test_bool(f, BM_ELEM_SELECT), | ||||
| l_index, | l_index, | ||||
| BM_elem_index_get(loop->next)); | BM_elem_index_get(l_iter->next)); | ||||
| } | } while ((l_iter = l_iter->next) != l_first); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop); | |||||
| } | } | ||||
| static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| const int ml_index_last = mp->totloop + mp->loopstart - 1; | 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 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); | const bool real_edge = (mr->e_origindex == NULL || mr->e_origindex[ml->e] != ORIGINDEX_NONE); | ||||
| edituv_edge_add(data, | edituv_edge_add(data, | ||||
| (mp->flag & ME_HIDE) != 0 || !real_edge, | (mp->flag & ME_HIDE) != 0 || !real_edge, | ||||
| (mp->flag & ME_FACE_SEL) != 0, | (mp->flag & ME_FACE_SEL) != 0, | ||||
| ml_index, | ml_index, | ||||
| ml_index_next); | ml_index_next); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), | static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| MeshExtract_EditUvElem_Data *extract_data = data; | MeshExtract_EditUvElem_Data *extract_data = data; | ||||
| GPU_indexbuf_build_in_place(&extract_data->elb, ibo); | GPU_indexbuf_build_in_place(&extract_data->elb, ibo); | ||||
| MEM_freeN(extract_data); | MEM_freeN(extract_data); | ||||
| } | } | ||||
| static const MeshExtract extract_edituv_lines = { | static const MeshExtract extract_edituv_lines = { | ||||
| .init = extract_edituv_lines_init, | .init = extract_edituv_lines_init, | ||||
| .iter_poly_bm = extract_edituv_lines_iter_poly_bm, | .iter_poly_bm = extract_edituv_lines_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edituv_lines_iter_poly_mesh, | .iter_poly_mesh = extract_edituv_lines_iter_poly_mesh, | ||||
| .finish = extract_edituv_lines_finish, | .finish = extract_edituv_lines_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_lines)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit UV Points Indices | /** \name Extract Edit UV Points Indices | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_edituv_points_init(const MeshRenderData *mr, | static void *extract_edituv_points_init(const MeshRenderData *mr, | ||||
| Show All 12 Lines | BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data, | ||||
| bool selected, | bool selected, | ||||
| int v1) | int v1) | ||||
| { | { | ||||
| if (!hidden && (data->sync_selection || selected)) { | if (!hidden && (data->sync_selection || selected)) { | ||||
| GPU_indexbuf_add_point_vert(&data->elb, v1); | GPU_indexbuf_add_point_vert(&data->elb, v1); | ||||
| } | } | ||||
| } | } | ||||
| static void extract_edituv_points_iter_poly_bm(const MeshRenderData *mr, | static void extract_edituv_points_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| edituv_point_add(data, | do { | ||||
| BM_elem_flag_test(l->f, BM_ELEM_HIDDEN), | const int l_index = BM_elem_index_get(l_iter); | ||||
| BM_elem_flag_test(l->f, BM_ELEM_SELECT), | |||||
| l_index); | edituv_point_add( | ||||
| } | data, BM_elem_flag_test(f, BM_ELEM_HIDDEN), BM_elem_flag_test(f, BM_ELEM_SELECT), l_index); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | } | ||||
| static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && | const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && | ||||
| mr->v_origindex[ml->v] != ORIGINDEX_NONE); | mr->v_origindex[ml->v] != ORIGINDEX_NONE); | ||||
| edituv_point_add( | edituv_point_add( | ||||
| data, ((mp->flag & ME_HIDE) != 0) || !real_vert, (mp->flag & ME_FACE_SEL) != 0, ml_index); | 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), | static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| MeshExtract_EditUvElem_Data *extract_data = data; | MeshExtract_EditUvElem_Data *extract_data = data; | ||||
| GPU_indexbuf_build_in_place(&extract_data->elb, ibo); | GPU_indexbuf_build_in_place(&extract_data->elb, ibo); | ||||
| MEM_freeN(extract_data); | MEM_freeN(extract_data); | ||||
| } | } | ||||
| static const MeshExtract extract_edituv_points = { | static const MeshExtract extract_edituv_points = { | ||||
| .init = extract_edituv_points_init, | .init = extract_edituv_points_init, | ||||
| .iter_poly_bm = extract_edituv_points_iter_poly_bm, | .iter_poly_bm = extract_edituv_points_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edituv_points_iter_poly_mesh, | .iter_poly_mesh = extract_edituv_points_iter_poly_mesh, | ||||
| .finish = extract_edituv_points_finish, | .finish = extract_edituv_points_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_points)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit UV Facedots Indices | /** \name Extract Edit UV Facedots Indices | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_edituv_fdots_init(const MeshRenderData *mr, | static void *extract_edituv_fdots_init(const MeshRenderData *mr, | ||||
| Show All 15 Lines | BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data, | ||||
| if (!hidden && (data->sync_selection || selected)) { | if (!hidden && (data->sync_selection || selected)) { | ||||
| GPU_indexbuf_set_point_vert(&data->elb, face_index, face_index); | GPU_indexbuf_set_point_vert(&data->elb, face_index, face_index); | ||||
| } | } | ||||
| else { | else { | ||||
| GPU_indexbuf_set_point_restart(&data->elb, face_index); | GPU_indexbuf_set_point_restart(&data->elb, face_index); | ||||
| } | } | ||||
| } | } | ||||
| static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *mr, | static void extract_edituv_fdots_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int f_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) | edituv_facedot_add(data, | ||||
| { | BM_elem_flag_test_bool(f, BM_ELEM_HIDDEN), | ||||
| edituv_facedot_add( | BM_elem_flag_test_bool(f, BM_ELEM_SELECT), | ||||
| data, BM_elem_flag_test(f, BM_ELEM_HIDDEN), BM_elem_flag_test(f, BM_ELEM_SELECT), f_index); | f_index); | ||||
| } | |||||
| EXTRACT_POLY_FOREACH_BM_END; | |||||
| } | } | ||||
| static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| if (mr->use_subsurf_fdots) { | if (mr->use_subsurf_fdots) { | ||||
| /* Check #ME_VERT_FACEDOT. */ | /* Check #ME_VERT_FACEDOT. */ | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && | const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && | ||||
| mr->p_origindex[mp_index] != ORIGINDEX_NONE); | mr->p_origindex[mp_index] != ORIGINDEX_NONE); | ||||
| const bool subd_fdot = (!mr->use_subsurf_fdots || | const bool subd_fdot = (!mr->use_subsurf_fdots || | ||||
| (mr->mvert[ml->v].flag & ME_VERT_FACEDOT) != 0); | (mr->mvert[ml->v].flag & ME_VERT_FACEDOT) != 0); | ||||
| edituv_facedot_add(data, | edituv_facedot_add(data, | ||||
| ((mp->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot, | ((mp->flag & ME_HIDE) != 0) || !real_fdot || !subd_fdot, | ||||
| (mp->flag & ME_FACE_SEL) != 0, | (mp->flag & ME_FACE_SEL) != 0, | ||||
| mp_index); | mp_index); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| else { | else { | ||||
| EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) | |||||
| { | |||||
| const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && | const bool real_fdot = (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex && | ||||
| mr->p_origindex[mp_index] != ORIGINDEX_NONE); | mr->p_origindex[mp_index] != ORIGINDEX_NONE); | ||||
| edituv_facedot_add(data, | edituv_facedot_add( | ||||
| ((mp->flag & ME_HIDE) != 0) || !real_fdot, | data, ((mp->flag & ME_HIDE) != 0) || !real_fdot, (mp->flag & ME_FACE_SEL) != 0, mp_index); | ||||
| (mp->flag & ME_FACE_SEL) != 0, | |||||
| mp_index); | |||||
| } | |||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| } | } | ||||
| } | } | ||||
| static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), | static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *ibo, | void *buf, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| GPUIndexBuf *ibo = buf; | |||||
| MeshExtract_EditUvElem_Data *data = _data; | MeshExtract_EditUvElem_Data *data = _data; | ||||
| GPU_indexbuf_build_in_place(&data->elb, ibo); | GPU_indexbuf_build_in_place(&data->elb, ibo); | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_edituv_fdots = { | static const MeshExtract extract_edituv_fdots = { | ||||
| .init = extract_edituv_fdots_init, | .init = extract_edituv_fdots_init, | ||||
| .iter_poly_bm = extract_edituv_fdots_iter_poly_bm, | .iter_poly_bm = extract_edituv_fdots_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edituv_fdots_iter_poly_mesh, | .iter_poly_mesh = extract_edituv_fdots_iter_poly_mesh, | ||||
| .finish = extract_edituv_fdots_finish, | .finish = extract_edituv_fdots_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, ibo.edituv_fdots)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Position and Vertex Normal | /** \name Extract Position and Vertex Normal | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct PosNorLoop { | typedef struct PosNorLoop { | ||||
| float pos[3]; | float pos[3]; | ||||
| GPUPackedNormal nor; | GPUPackedNormal nor; | ||||
| } PosNorLoop; | } PosNorLoop; | ||||
| typedef struct MeshExtract_PosNor_Data { | typedef struct MeshExtract_PosNor_Data { | ||||
| PosNorLoop *vbo_data; | PosNorLoop *vbo_data; | ||||
| GPUNormal normals[]; | GPUNormal normals[]; | ||||
| } MeshExtract_PosNor_Data; | } MeshExtract_PosNor_Data; | ||||
| static void *extract_pos_nor_init(const MeshRenderData *mr, | static void *extract_pos_nor_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 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, "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_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| GPU_vertformat_alias_add(&format, "vnor"); | GPU_vertformat_alias_add(&format, "vnor"); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | ||||
| /* Pack normals per vert, reduce amount of computation. */ | /* Pack normals per vert, reduce amount of computation. */ | ||||
| size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; | size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; | ||||
| MeshExtract_PosNor_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); | MeshExtract_PosNor_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); | ||||
| data->vbo_data = (PosNorLoop *)GPU_vertbuf_get_data(vbo); | data->vbo_data = (PosNorLoop *)GPU_vertbuf_get_data(vbo); | ||||
| Show All 11 Lines | else { | ||||
| for (int v = 0; v < mr->vert_len; v++, mv++) { | for (int v = 0; v < mr->vert_len; v++, mv++) { | ||||
| data->normals[v].low = GPU_normal_convert_i10_s3(mv->no); | data->normals[v].low = GPU_normal_convert_i10_s3(mv->no); | ||||
| } | } | ||||
| } | } | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, | static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNor_Data *data = _data; | MeshExtract_PosNor_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| PosNorLoop *vert = &data->vbo_data[l_index]; | PosNorLoop *vert = &data->vbo_data[l_index]; | ||||
| copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v)); | copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v)); | ||||
| vert->nor = data->normals[BM_elem_index_get(l->v)].low; | vert->nor = data->normals[BM_elem_index_get(l_iter->v)].low; | ||||
| BMFace *efa = l->f; | vert->nor.w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; | ||||
| vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | |||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | } | ||||
| static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, | static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNor_Data *data = _data; | MeshExtract_PosNor_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | |||||
| { | const MLoop *mloop = mr->mloop; | ||||
| const int ml_index_end = mp->loopstart + mp->totloop; | |||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| PosNorLoop *vert = &data->vbo_data[ml_index]; | PosNorLoop *vert = &data->vbo_data[ml_index]; | ||||
| const MVert *mv = &mr->mvert[ml->v]; | const MVert *mv = &mr->mvert[ml->v]; | ||||
| copy_v3_v3(vert->pos, mv->co); | copy_v3_v3(vert->pos, mv->co); | ||||
| vert->nor = data->normals[ml->v].low; | vert->nor = data->normals[ml->v].low; | ||||
| /* Flag for paint mode overlay. */ | /* Flag for paint mode overlay. */ | ||||
| if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || | if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || | ||||
| ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && | ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && | ||||
| (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { | (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { | ||||
| vert->nor.w = -1; | vert->nor.w = -1; | ||||
| } | } | ||||
| else if (mv->flag & SELECT) { | else if (mv->flag & SELECT) { | ||||
| vert->nor.w = 1; | vert->nor.w = 1; | ||||
| } | } | ||||
| else { | else { | ||||
| vert->nor.w = 0; | vert->nor.w = 0; | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr, | static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNor_Data *data = _data; | MeshExtract_PosNor_Data *data = _data; | ||||
| EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) | |||||
| { | |||||
| int l_index = mr->loop_len + ledge_index * 2; | int l_index = mr->loop_len + ledge_index * 2; | ||||
| PosNorLoop *vert = &data->vbo_data[l_index]; | PosNorLoop *vert = &data->vbo_data[l_index]; | ||||
| copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); | 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)); | copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); | ||||
| vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low; | vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low; | ||||
| vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low; | vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low; | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr, | static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *med, | ||||
| const uint ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNor_Data *data = _data; | MeshExtract_PosNor_Data *data = _data; | ||||
| EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) | |||||
| { | |||||
| const int ml_index = mr->loop_len + ledge_index * 2; | const int ml_index = mr->loop_len + ledge_index * 2; | ||||
| PosNorLoop *vert = &data->vbo_data[ml_index]; | PosNorLoop *vert = &data->vbo_data[ml_index]; | ||||
| copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); | copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); | ||||
| copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); | copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); | ||||
| vert[0].nor = data->normals[med->v1].low; | vert[0].nor = data->normals[med->v1].low; | ||||
| vert[1].nor = data->normals[med->v2].low; | vert[1].nor = data->normals[med->v2].low; | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr, | static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr, | ||||
| const ExtractLVertBMesh_Params *params, | BMVert *eve, | ||||
| const int lvert_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNor_Data *data = _data; | MeshExtract_PosNor_Data *data = _data; | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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; | const int l_index = offset + lvert_index; | ||||
| PosNorLoop *vert = &data->vbo_data[l_index]; | PosNorLoop *vert = &data->vbo_data[l_index]; | ||||
| copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); | copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); | ||||
| vert->nor = data->normals[BM_elem_index_get(eve)].low; | vert->nor = data->normals[BM_elem_index_get(eve)].low; | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, | static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, | ||||
| const ExtractLVertMesh_Params *params, | const MVert *mv, | ||||
| const int lvert_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNor_Data *data = _data; | MeshExtract_PosNor_Data *data = _data; | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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 ml_index = offset + lvert_index; | ||||
| const int v_index = mr->lverts[lvert_index]; | const int v_index = mr->lverts[lvert_index]; | ||||
| PosNorLoop *vert = &data->vbo_data[ml_index]; | PosNorLoop *vert = &data->vbo_data[ml_index]; | ||||
| copy_v3_v3(vert->pos, mv->co); | copy_v3_v3(vert->pos, mv->co); | ||||
| vert->nor = data->normals[v_index].low; | vert->nor = data->normals[v_index].low; | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), | static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(vbo), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_pos_nor = { | static const MeshExtract extract_pos_nor = { | ||||
| .init = extract_pos_nor_init, | .init = extract_pos_nor_init, | ||||
| .iter_poly_bm = extract_pos_nor_iter_poly_bm, | .iter_poly_bm = extract_pos_nor_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_pos_nor_iter_poly_mesh, | .iter_poly_mesh = extract_pos_nor_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_pos_nor_iter_ledge_bm, | .iter_ledge_bm = extract_pos_nor_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh, | .iter_ledge_mesh = extract_pos_nor_iter_ledge_mesh, | ||||
| .iter_lvert_bm = extract_pos_nor_iter_lvert_bm, | .iter_lvert_bm = extract_pos_nor_iter_lvert_bm, | ||||
| .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh, | .iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh, | ||||
| .finish = extract_pos_nor_finish, | .finish = extract_pos_nor_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Position and High Quality Vertex Normal | /** \name Extract Position and High Quality Vertex Normal | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct PosNorHQLoop { | typedef struct PosNorHQLoop { | ||||
| float pos[3]; | float pos[3]; | ||||
| short nor[4]; | short nor[4]; | ||||
| } PosNorHQLoop; | } PosNorHQLoop; | ||||
| typedef struct MeshExtract_PosNorHQ_Data { | typedef struct MeshExtract_PosNorHQ_Data { | ||||
| PosNorHQLoop *vbo_data; | PosNorHQLoop *vbo_data; | ||||
| GPUNormal normals[]; | GPUNormal normals[]; | ||||
| } MeshExtract_PosNorHQ_Data; | } MeshExtract_PosNorHQ_Data; | ||||
| static void *extract_pos_nor_hq_init(const MeshRenderData *mr, | static void *extract_pos_nor_hq_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| /* WARNING Adjust #PosNorHQLoop struct accordingly. */ | /* WARNING Adjust #PosNorHQLoop struct accordingly. */ | ||||
| GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); | ||||
| GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| GPU_vertformat_alias_add(&format, "vnor"); | GPU_vertformat_alias_add(&format, "vnor"); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | ||||
| /* Pack normals per vert, reduce amount of computation. */ | /* Pack normals per vert, reduce amount of computation. */ | ||||
| size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; | size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; | ||||
| MeshExtract_PosNorHQ_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); | MeshExtract_PosNorHQ_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); | ||||
| data->vbo_data = (PosNorHQLoop *)GPU_vertbuf_get_data(vbo); | data->vbo_data = (PosNorHQLoop *)GPU_vertbuf_get_data(vbo); | ||||
| Show All 11 Lines | else { | ||||
| for (int v = 0; v < mr->vert_len; v++, mv++) { | for (int v = 0; v < mr->vert_len; v++, mv++) { | ||||
| copy_v3_v3_short(data->normals[v].high, mv->no); | copy_v3_v3_short(data->normals[v].high, mv->no); | ||||
| } | } | ||||
| } | } | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr, | static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNorHQ_Data *data = _data; | MeshExtract_PosNorHQ_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| PosNorHQLoop *vert = &data->vbo_data[l_index]; | PosNorHQLoop *vert = &data->vbo_data[l_index]; | ||||
| copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v)); | copy_v3_v3(vert->pos, bm_vert_co_get(mr, l_iter->v)); | ||||
| copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l->v)].high); | copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l_iter->v)].high); | ||||
| BMFace *efa = l->f; | BMFace *efa = l_iter->f; | ||||
| vert->nor[3] = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; | vert->nor[3] = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; | ||||
| } | } while ((l_iter = l_iter->next) != l_first); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | } | ||||
| static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, | static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNorHQ_Data *data = _data; | MeshExtract_PosNorHQ_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| PosNorHQLoop *vert = &data->vbo_data[ml_index]; | PosNorHQLoop *vert = &data->vbo_data[ml_index]; | ||||
| const MVert *mv = &mr->mvert[ml->v]; | const MVert *mv = &mr->mvert[ml->v]; | ||||
| copy_v3_v3(vert->pos, mv->co); | copy_v3_v3(vert->pos, mv->co); | ||||
| copy_v3_v3_short(vert->nor, data->normals[ml->v].high); | copy_v3_v3_short(vert->nor, data->normals[ml->v].high); | ||||
| /* Flag for paint mode overlay. */ | /* Flag for paint mode overlay. */ | ||||
| if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || | if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || | ||||
| ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && | ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && | ||||
| (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { | (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { | ||||
| vert->nor[3] = -1; | vert->nor[3] = -1; | ||||
| } | } | ||||
| else if (mv->flag & SELECT) { | else if (mv->flag & SELECT) { | ||||
| vert->nor[3] = 1; | vert->nor[3] = 1; | ||||
| } | } | ||||
| else { | else { | ||||
| vert->nor[3] = 0; | vert->nor[3] = 0; | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr, | static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNorHQ_Data *data = _data; | MeshExtract_PosNorHQ_Data *data = _data; | ||||
| EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) | |||||
| { | |||||
| int l_index = mr->loop_len + ledge_index * 2; | int l_index = mr->loop_len + ledge_index * 2; | ||||
| PosNorHQLoop *vert = &data->vbo_data[l_index]; | PosNorHQLoop *vert = &data->vbo_data[l_index]; | ||||
| copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); | 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)); | copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); | ||||
| copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high); | copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high); | ||||
| vert[0].nor[3] = 0; | vert[0].nor[3] = 0; | ||||
| copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high); | copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high); | ||||
| vert[1].nor[3] = 0; | vert[1].nor[3] = 0; | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr, | static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *med, | ||||
| const uint ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNorHQ_Data *data = _data; | MeshExtract_PosNorHQ_Data *data = _data; | ||||
| EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) | |||||
| { | |||||
| const int ml_index = mr->loop_len + ledge_index * 2; | const int ml_index = mr->loop_len + ledge_index * 2; | ||||
| PosNorHQLoop *vert = &data->vbo_data[ml_index]; | PosNorHQLoop *vert = &data->vbo_data[ml_index]; | ||||
| copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); | copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); | ||||
| copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); | copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); | ||||
| copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high); | copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high); | ||||
| vert[0].nor[3] = 0; | vert[0].nor[3] = 0; | ||||
| copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high); | copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high); | ||||
| vert[1].nor[3] = 0; | vert[1].nor[3] = 0; | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr, | static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr, | ||||
| const ExtractLVertBMesh_Params *params, | BMVert *eve, | ||||
| const int lvert_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNorHQ_Data *data = _data; | MeshExtract_PosNorHQ_Data *data = _data; | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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; | const int l_index = offset + lvert_index; | ||||
| PosNorHQLoop *vert = &data->vbo_data[l_index]; | PosNorHQLoop *vert = &data->vbo_data[l_index]; | ||||
| copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); | copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); | ||||
| copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high); | copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high); | ||||
| vert->nor[3] = 0; | vert->nor[3] = 0; | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr, | static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr, | ||||
| const ExtractLVertMesh_Params *params, | const MVert *mv, | ||||
| const int lvert_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_PosNorHQ_Data *data = _data; | MeshExtract_PosNorHQ_Data *data = _data; | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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 ml_index = offset + lvert_index; | ||||
| const int v_index = mr->lverts[lvert_index]; | const int v_index = mr->lverts[lvert_index]; | ||||
| PosNorHQLoop *vert = &data->vbo_data[ml_index]; | PosNorHQLoop *vert = &data->vbo_data[ml_index]; | ||||
| copy_v3_v3(vert->pos, mv->co); | copy_v3_v3(vert->pos, mv->co); | ||||
| copy_v3_v3_short(vert->nor, data->normals[v_index].high); | copy_v3_v3_short(vert->nor, data->normals[v_index].high); | ||||
| vert->nor[3] = 0; | vert->nor[3] = 0; | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr), | static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(vbo), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_pos_nor_hq = { | static const MeshExtract extract_pos_nor_hq = { | ||||
| .init = extract_pos_nor_hq_init, | .init = extract_pos_nor_hq_init, | ||||
| .iter_poly_bm = extract_pos_nor_hq_iter_poly_bm, | .iter_poly_bm = extract_pos_nor_hq_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh, | .iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm, | .iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_pos_nor_hq_iter_ledge_mesh, | .iter_ledge_mesh = extract_pos_nor_hq_iter_ledge_mesh, | ||||
| .iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm, | .iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm, | ||||
| .iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh, | .iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh, | ||||
| .finish = extract_pos_nor_hq_finish, | .finish = extract_pos_nor_hq_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.pos_nor)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract HQ Loop Normal | /** \name Extract HQ Loop Normal | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct gpuHQNor { | typedef struct gpuHQNor { | ||||
| short x, y, z, w; | short x, y, z, w; | ||||
| } gpuHQNor; | } gpuHQNor; | ||||
| static void *extract_lnor_hq_init(const MeshRenderData *mr, | static void *extract_lnor_hq_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| GPU_vertformat_alias_add(&format, "lnor"); | GPU_vertformat_alias_add(&format, "lnor"); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| return GPU_vertbuf_get_data(vbo); | return GPU_vertbuf_get_data(vbo); | ||||
| } | } | ||||
| static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, | static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| BMLoop *l_iter, *l_first; | |||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | |||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| if (mr->loop_normals) { | if (mr->loop_normals) { | ||||
| 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]); | normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, mr->loop_normals[l_index]); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(_l); | |||||
| } | |||||
| else { | else { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { | ||||
| { | normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_vert_no_get(mr, l_iter->v)); | ||||
| 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 { | else { | ||||
| normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, l->f)); | normal_float_to_short_v3(&((gpuHQNor *)data)[l_index].x, bm_face_no_get(mr, f)); | ||||
| } | |||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | } | ||||
| } while ((l_iter = l_iter->next) != l_first); | |||||
| } | } | ||||
| static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, | static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| gpuHQNor *lnor_data = &((gpuHQNor *)data)[ml_index]; | gpuHQNor *lnor_data = &((gpuHQNor *)data)[ml_index]; | ||||
| if (mr->loop_normals) { | if (mr->loop_normals) { | ||||
| normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); | normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); | ||||
| } | } | ||||
| else if (mp->flag & ME_SMOOTH) { | else if (mp->flag & ME_SMOOTH) { | ||||
| copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no); | copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no); | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 9 Lines | for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | ||||
| } | } | ||||
| else if (mp->flag & ME_FACE_SEL) { | else if (mp->flag & ME_FACE_SEL) { | ||||
| lnor_data->w = 1; | lnor_data->w = 1; | ||||
| } | } | ||||
| else { | else { | ||||
| lnor_data->w = 0; | lnor_data->w = 0; | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static const MeshExtract extract_lnor_hq = { | static const MeshExtract extract_lnor_hq = { | ||||
| .init = extract_lnor_hq_init, | .init = extract_lnor_hq_init, | ||||
| .iter_poly_bm = extract_lnor_hq_iter_poly_bm, | .iter_poly_bm = extract_lnor_hq_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh, | .iter_poly_mesh = extract_lnor_hq_iter_poly_mesh, | ||||
| .data_flag = MR_DATA_LOOP_NOR, | .data_flag = MR_DATA_LOOP_NOR, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Loop Normal | /** \name Extract Loop Normal | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_lnor_init(const MeshRenderData *mr, | static void *extract_lnor_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| GPU_vertformat_alias_add(&format, "lnor"); | GPU_vertformat_alias_add(&format, "lnor"); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| return GPU_vertbuf_get_data(vbo); | return GPU_vertbuf_get_data(vbo); | ||||
| } | } | ||||
| static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, | static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| BMLoop *l_iter, *l_first; | |||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | |||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| if (mr->loop_normals) { | if (mr->loop_normals) { | ||||
| 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]); | ((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 { | else { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { | ||||
| { | ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3( | ||||
| if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH)) { | bm_vert_no_get(mr, l_iter->v)); | ||||
| ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, l->v)); | |||||
| } | } | ||||
| else { | else { | ||||
| ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, l->f)); | ((GPUPackedNormal *)data)[l_index] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, 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); | |||||
| } | } | ||||
| ((GPUPackedNormal *)data)[l_index].w = BM_elem_flag_test(f, BM_ELEM_HIDDEN) ? -1 : 0; | |||||
| } while ((l_iter = l_iter->next) != l_first); | |||||
| } | } | ||||
| static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, | static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[ml_index]; | GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[ml_index]; | ||||
| if (mr->loop_normals) { | if (mr->loop_normals) { | ||||
| *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); | *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); | ||||
| } | } | ||||
| else if (mp->flag & ME_SMOOTH) { | else if (mp->flag & ME_SMOOTH) { | ||||
| *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no); | *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no); | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 9 Lines | for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | ||||
| } | } | ||||
| else if (mp->flag & ME_FACE_SEL) { | else if (mp->flag & ME_FACE_SEL) { | ||||
| lnor_data->w = 1; | lnor_data->w = 1; | ||||
| } | } | ||||
| else { | else { | ||||
| lnor_data->w = 0; | lnor_data->w = 0; | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static const MeshExtract extract_lnor = { | static const MeshExtract extract_lnor = { | ||||
| .init = extract_lnor_init, | .init = extract_lnor_init, | ||||
| .iter_poly_bm = extract_lnor_iter_poly_bm, | .iter_poly_bm = extract_lnor_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_lnor_iter_poly_mesh, | .iter_poly_mesh = extract_lnor_iter_poly_mesh, | ||||
| .data_flag = MR_DATA_LOOP_NOR, | .data_flag = MR_DATA_LOOP_NOR, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.lnor)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract UV layers | /** \name Extract UV layers | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPUVertFormat format = {0}; | GPUVertFormat format = {0}; | ||||
| GPU_vertformat_deinterleave(&format); | GPU_vertformat_deinterleave(&format); | ||||
| CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | ||||
| uint32_t uv_layers = cache->cd_used.uv; | uint32_t uv_layers = cache->cd_used.uv; | ||||
| /* HACK to fix T68857 */ | /* HACK to fix T68857 */ | ||||
| if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { | if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { | ||||
| int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); | int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); | ||||
| Show All 33 Lines | static void *extract_uv_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | ||||
| int v_len = mr->loop_len; | int v_len = mr->loop_len; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | ||||
| /* VBO will not be used, only allocate minimum of memory. */ | /* VBO will not be used, only allocate minimum of memory. */ | ||||
| v_len = 1; | v_len = 1; | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, v_len); | GPU_vertbuf_data_alloc(vbo, v_len); | ||||
| float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo); | float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo); | ||||
| for (int i = 0; i < MAX_MTFACE; i++) { | for (int i = 0; i < MAX_MTFACE; i++) { | ||||
| if (uv_layers & (1 << i)) { | if (uv_layers & (1 << i)) { | ||||
| if (mr->extract_type == MR_EXTRACT_BMESH) { | if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i); | int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i); | ||||
| Show All 16 Lines | if (uv_layers & (1 << i)) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static const MeshExtract extract_uv = { | static const MeshExtract extract_uv = {.init = extract_uv_init, | ||||
| .init = extract_uv_init, | |||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.uv)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Tangent layers | /** \name Extract Tangent layers | ||||
| * \{ */ | * \{ */ | ||||
| static void extract_tan_ex(const MeshRenderData *mr, | static void extract_tan_ex_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| GPUVertBuf *vbo, | GPUVertBuf *vbo, | ||||
| const bool do_hq) | const bool do_hq) | ||||
| { | { | ||||
| GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10; | GPUVertCompType comp_type = do_hq ? GPU_COMP_I16 : GPU_COMP_I10; | ||||
| GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT; | GPUVertFetchMode fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT; | ||||
| GPUVertFormat format = {0}; | GPUVertFormat format = {0}; | ||||
| GPU_vertformat_deinterleave(&format); | GPU_vertformat_deinterleave(&format); | ||||
| CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | ||||
| ▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | else { | ||||
| } | } | ||||
| } | } | ||||
| CustomData_free(&loop_data, mr->loop_len); | CustomData_free(&loop_data, mr->loop_len); | ||||
| } | } | ||||
| static void *extract_tan_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | static void *extract_tan_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | ||||
| { | { | ||||
| extract_tan_ex(mr, cache, buf, false); | extract_tan_ex_init(mr, cache, buf, false); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static const MeshExtract extract_tan = { | static const MeshExtract extract_tan = {.init = extract_tan_init, | ||||
| .init = extract_tan_init, | .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | | ||||
| .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, | MR_DATA_LOOPTRI, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.tan)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract HQ Tangent layers | /** \name Extract HQ Tangent layers | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_tan_hq_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | static void *extract_tan_hq_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | ||||
| { | { | ||||
| extract_tan_ex(mr, cache, buf, true); | extract_tan_ex_init(mr, cache, buf, true); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static const MeshExtract extract_tan_hq = { | static const MeshExtract extract_tan_hq = { | ||||
| .init = extract_tan_hq_init, | .init = extract_tan_hq_init, | ||||
| .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, | .data_flag = MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | }; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Sculpt Data | /** \name Extract Sculpt Data | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_sculpt_data_init(const MeshRenderData *mr, | static void *extract_sculpt_data_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPUVertFormat format = {0}; | GPUVertFormat format = {0}; | ||||
| CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | 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; | CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; | ||||
| CustomData *cd_pdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata; | CustomData *cd_pdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata; | ||||
| float *cd_mask = CustomData_get_layer(cd_vdata, CD_PAINT_MASK); | float *cd_mask = CustomData_get_layer(cd_vdata, CD_PAINT_MASK); | ||||
| int *cd_face_set = CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS); | int *cd_face_set = CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS); | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| typedef struct gpuSculptData { | typedef struct gpuSculptData { | ||||
| uint8_t face_set_color[4]; | uint8_t face_set_color[4]; | ||||
| float mask; | float mask; | ||||
| } gpuSculptData; | } gpuSculptData; | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | static void *extract_sculpt_data_init(const MeshRenderData *mr, | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static const MeshExtract extract_sculpt_data = { | static const MeshExtract extract_sculpt_data = { | ||||
| .init = extract_sculpt_data_init, | .init = extract_sculpt_data_init, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| /* TODO: enable threading. */ | /* TODO: enable threading. */ | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.sculpt_data)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract VCol | /** \name Extract VCol | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPUVertFormat format = {0}; | GPUVertFormat format = {0}; | ||||
| GPU_vertformat_deinterleave(&format); | GPU_vertformat_deinterleave(&format); | ||||
| CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | 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; | CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata; | ||||
| uint32_t vcol_layers = cache->cd_used.vcol; | uint32_t vcol_layers = cache->cd_used.vcol; | ||||
| uint32_t svcol_layers = cache->cd_used.sculpt_vcol; | uint32_t svcol_layers = cache->cd_used.sculpt_vcol; | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | for (int i = 0; i < 8; i++) { | ||||
| if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { | 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); | BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); | ||||
| GPU_vertformat_alias_add(&format, attr_name); | GPU_vertformat_alias_add(&format, attr_name); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| typedef struct gpuMeshVcol { | typedef struct gpuMeshVcol { | ||||
| ushort r, g, b, a; | ushort r, g, b, a; | ||||
| } gpuMeshVcol; | } gpuMeshVcol; | ||||
| gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo); | gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo); | ||||
| ▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | static void *extract_vcol_init(const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf) | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static const MeshExtract extract_vcol = { | static const MeshExtract extract_vcol = { | ||||
| .init = extract_vcol_init, | .init = extract_vcol_init, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vcol)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Orco | /** \name Extract Orco | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshExtract_Orco_Data { | typedef struct MeshExtract_Orco_Data { | ||||
| float (*vbo_data)[4]; | float (*vbo_data)[4]; | ||||
| float (*orco)[3]; | float (*orco)[3]; | ||||
| } MeshExtract_Orco_Data; | } MeshExtract_Orco_Data; | ||||
| static void *extract_orco_init(const MeshRenderData *mr, | static void *extract_orco_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex | /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex | ||||
| * attributes. This is a substantial waste of video-ram 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" | * Unfortunately, at the time of writing, I did not found any other "non disruptive" | ||||
| * alternative. */ | * alternative. */ | ||||
| GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| CustomData *cd_vdata = &mr->me->vdata; | CustomData *cd_vdata = &mr->me->vdata; | ||||
| MeshExtract_Orco_Data *data = MEM_mallocN(sizeof(*data), __func__); | MeshExtract_Orco_Data *data = MEM_mallocN(sizeof(*data), __func__); | ||||
| data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo); | data->vbo_data = (float(*)[4])GPU_vertbuf_get_data(vbo); | ||||
| data->orco = CustomData_get_layer(cd_vdata, CD_ORCO); | 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); | BLI_assert(data->orco); | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_orco_iter_poly_bm(const MeshRenderData *mr, | static void extract_orco_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; | MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(loop, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| float *loop_orco = orco_data->vbo_data[l_index]; | float *loop_orco = orco_data->vbo_data[l_index]; | ||||
| copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(loop->v)]); | copy_v3_v3(loop_orco, orco_data->orco[BM_elem_index_get(l_iter->v)]); | ||||
| loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ | loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ | ||||
| } | } while ((l_iter = l_iter->next) != l_first); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(loop); | |||||
| } | } | ||||
| static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, | static void extract_orco_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; | MeshExtract_Orco_Data *orco_data = (MeshExtract_Orco_Data *)data; | ||||
| float *loop_orco = orco_data->vbo_data[ml_index]; | float *loop_orco = orco_data->vbo_data[ml_index]; | ||||
| copy_v3_v3(loop_orco, orco_data->orco[ml->v]); | copy_v3_v3(loop_orco, orco_data->orco[ml->v]); | ||||
| loop_orco[3] = 0.0; /* Tag as not a generic attribute. */ | 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), | static void extract_orco_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_orco = { | static const MeshExtract extract_orco = { | ||||
| .init = extract_orco_init, | .init = extract_orco_init, | ||||
| .iter_poly_bm = extract_orco_iter_poly_bm, | .iter_poly_bm = extract_orco_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_orco_iter_poly_mesh, | .iter_poly_mesh = extract_orco_iter_poly_mesh, | ||||
| .finish = extract_orco_finish, | .finish = extract_orco_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.orco)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edge Factor | /** \name Extract Edge Factor | ||||
| * Defines how much an edge is visible. | * Defines how much an edge is visible. | ||||
| * \{ */ | * \{ */ | ||||
| Show All 19 Lines | static float loop_edge_factor_get(const float f_no[3], | ||||
| CLAMP(d, 0.0f, 1.0f); | CLAMP(d, 0.0f, 1.0f); | ||||
| return d; | return d; | ||||
| } | } | ||||
| static void *extract_edge_fac_init(const MeshRenderData *mr, | static void *extract_edge_fac_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | ||||
| MeshExtract_EdgeFac_Data *data; | MeshExtract_EdgeFac_Data *data; | ||||
| if (mr->extract_type == MR_EXTRACT_MESH) { | if (mr->extract_type == MR_EXTRACT_MESH) { | ||||
| size_t edge_loop_count_size = sizeof(uint32_t) * mr->edge_len; | size_t edge_loop_count_size = sizeof(uint32_t) * mr->edge_len; | ||||
| data = MEM_callocN(sizeof(*data) + edge_loop_count_size, __func__); | data = MEM_callocN(sizeof(*data) + edge_loop_count_size, __func__); | ||||
| Show All 14 Lines | else { | ||||
| data->use_edge_render = true; | data->use_edge_render = true; | ||||
| } | } | ||||
| data->vbo_data = GPU_vertbuf_get_data(vbo); | data->vbo_data = GPU_vertbuf_get_data(vbo); | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr, | static void extract_edge_fac_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_EdgeFac_Data *data = _data; | MeshExtract_EdgeFac_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| if (BM_edge_is_manifold(l->e)) { | do { | ||||
| float ratio = loop_edge_factor_get(bm_face_no_get(mr, l->f), | const int l_index = BM_elem_index_get(l_iter); | ||||
| bm_vert_co_get(mr, l->v), | |||||
| bm_vert_no_get(mr, l->v), | if (BM_edge_is_manifold(l_iter->e)) { | ||||
| bm_vert_co_get(mr, l->next->v)); | float ratio = loop_edge_factor_get(bm_face_no_get(mr, f), | ||||
| bm_vert_co_get(mr, l_iter->v), | |||||
| bm_vert_no_get(mr, l_iter->v), | |||||
| bm_vert_co_get(mr, l_iter->next->v)); | |||||
| data->vbo_data[l_index] = ratio * 253 + 1; | data->vbo_data[l_index] = ratio * 253 + 1; | ||||
| } | } | ||||
| else { | else { | ||||
| data->vbo_data[l_index] = 255; | data->vbo_data[l_index] = 255; | ||||
| } | } | ||||
| } | } while ((l_iter = l_iter->next) != l_first); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | } | ||||
| static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; | MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; | ||||
| const MLoop *mloop = mr->mloop; | |||||
| const int ml_index_end = mp->loopstart + mp->totloop; | |||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| if (data->use_edge_render) { | if (data->use_edge_render) { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | |||||
| { | |||||
| const MEdge *med = &mr->medge[ml->e]; | const MEdge *med = &mr->medge[ml->e]; | ||||
| data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0; | data->vbo_data[ml_index] = (med->flag & ME_EDGERENDER) ? 255 : 0; | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | |||||
| else { | else { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | |||||
| { | |||||
| /* Count loop per edge to detect non-manifold. */ | /* Count loop per edge to detect non-manifold. */ | ||||
| if (data->edge_loop_count[ml->e] < 3) { | if (data->edge_loop_count[ml->e] < 3) { | ||||
| data->edge_loop_count[ml->e]++; | data->edge_loop_count[ml->e]++; | ||||
| } | } | ||||
| if (data->edge_loop_count[ml->e] == 2) { | if (data->edge_loop_count[ml->e] == 2) { | ||||
| /* Manifold */ | /* Manifold */ | ||||
| const int ml_index_last = mp->totloop + mp->loopstart - 1; | 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 int ml_index_other = (ml_index == ml_index_last) ? mp->loopstart : (ml_index + 1); | ||||
| const MLoop *ml_next = &mr->mloop[ml_index_other]; | const MLoop *ml_next = &mr->mloop[ml_index_other]; | ||||
| const MVert *v1 = &mr->mvert[ml->v]; | const MVert *v1 = &mr->mvert[ml->v]; | ||||
| const MVert *v2 = &mr->mvert[ml_next->v]; | const MVert *v2 = &mr->mvert[ml_next->v]; | ||||
| float vnor_f[3]; | float vnor_f[3]; | ||||
| normal_short_to_float_v3(vnor_f, v1->no); | 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); | 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; | data->vbo_data[ml_index] = ratio * 253 + 1; | ||||
| } | } | ||||
| else { | else { | ||||
| /* Non-manifold */ | /* Non-manifold */ | ||||
| data->vbo_data[ml_index] = 255; | data->vbo_data[ml_index] = 255; | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| } | } | ||||
| static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr, | static void extract_edge_fac_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *UNUSED(eed), | ||||
| const int ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_EdgeFac_Data *data = _data; | 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) + 0] = 255; | ||||
| data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255; | data->vbo_data[mr->loop_len + (ledge_index * 2) + 1] = 255; | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr, | static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *UNUSED(med), | ||||
| const uint ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_EdgeFac_Data *data = _data; | 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 + 0] = 255; | ||||
| data->vbo_data[mr->loop_len + ledge_index * 2 + 1] = 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, | static void extract_edge_fac_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf, | void *buf, | ||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| MeshExtract_EdgeFac_Data *data = _data; | MeshExtract_EdgeFac_Data *data = _data; | ||||
| if (GPU_crappy_amd_driver()) { | if (GPU_crappy_amd_driver()) { | ||||
| GPUVertBuf *vbo = (GPUVertBuf *)buf; | |||||
| /* Some AMD drivers strangely crash with VBO's with a one byte format. | /* Some AMD drivers strangely crash with VBO's with a one byte format. | ||||
| * To workaround we reinitialize the VBO with another format and convert | * To workaround we reinitialize the VBO with another format and convert | ||||
| * all bytes to floats. */ | * all bytes to floats. */ | ||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | ||||
| } | } | ||||
| /* We keep the data reference in data->vbo_data. */ | /* We keep the data reference in data->vbo_data. */ | ||||
| Show All 18 Lines | static const MeshExtract extract_edge_fac = { | ||||
| .init = extract_edge_fac_init, | .init = extract_edge_fac_init, | ||||
| .iter_poly_bm = extract_edge_fac_iter_poly_bm, | .iter_poly_bm = extract_edge_fac_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edge_fac_iter_poly_mesh, | .iter_poly_mesh = extract_edge_fac_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_edge_fac_iter_ledge_bm, | .iter_ledge_bm = extract_edge_fac_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh, | .iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh, | ||||
| .finish = extract_edge_fac_finish, | .finish = extract_edge_fac_finish, | ||||
| .data_flag = MR_DATA_POLY_NOR, | .data_flag = MR_DATA_POLY_NOR, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_fac)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Vertex Weight | /** \name Extract Vertex Weight | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshExtract_Weight_Data { | typedef struct MeshExtract_Weight_Data { | ||||
| float *vbo_data; | float *vbo_data; | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeightState *wstate) | ||||
| CLAMP(input, 0.0f, 1.0f); | CLAMP(input, 0.0f, 1.0f); | ||||
| return input; | return input; | ||||
| } | } | ||||
| static void *extract_weights_init(const MeshRenderData *mr, | static void *extract_weights_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | ||||
| MeshExtract_Weight_Data *data = MEM_callocN(sizeof(*data), __func__); | MeshExtract_Weight_Data *data = MEM_callocN(sizeof(*data), __func__); | ||||
| data->vbo_data = (float *)GPU_vertbuf_get_data(vbo); | data->vbo_data = (float *)GPU_vertbuf_get_data(vbo); | ||||
| data->wstate = &cache->weight_state; | data->wstate = &cache->weight_state; | ||||
| if (data->wstate->defgroup_active == -1) { | if (data->wstate->defgroup_active == -1) { | ||||
| /* Nothing to show. */ | /* Nothing to show. */ | ||||
| data->dvert = NULL; | data->dvert = NULL; | ||||
| data->cd_ofs = -1; | data->cd_ofs = -1; | ||||
| } | } | ||||
| else if (mr->extract_type == MR_EXTRACT_BMESH) { | else if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| data->dvert = NULL; | data->dvert = NULL; | ||||
| data->cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MDEFORMVERT); | data->cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MDEFORMVERT); | ||||
| } | } | ||||
| else { | else { | ||||
| data->dvert = CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT); | data->dvert = CustomData_get_layer(&mr->me->vdata, CD_MDEFORMVERT); | ||||
| data->cd_ofs = -1; | data->cd_ofs = -1; | ||||
| } | } | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_weights_iter_poly_bm(const MeshRenderData *mr, | static void extract_weights_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_Weight_Data *data = _data; | MeshExtract_Weight_Data *data = _data; | ||||
| BMLoop *l_iter, *l_first; | |||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | |||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| if (data->cd_ofs != -1) { | 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_iter->v, data->cd_ofs); | ||||
| { | |||||
| 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); | data->vbo_data[l_index] = evaluate_vertex_weight(dvert, data->wstate); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | |||||
| else { | else { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | |||||
| { | |||||
| data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate); | data->vbo_data[l_index] = evaluate_vertex_weight(NULL, data->wstate); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | |||||
| } | } | ||||
| static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, | static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_Weight_Data *data = _data; | MeshExtract_Weight_Data *data = _data; | ||||
| const MLoop *mloop = mr->mloop; | |||||
| const int ml_index_end = mp->loopstart + mp->totloop; | |||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| if (data->dvert != NULL) { | 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]; | const MDeformVert *dvert = &data->dvert[ml->v]; | ||||
| data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); | data->vbo_data[ml_index] = evaluate_vertex_weight(dvert, data->wstate); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | |||||
| else { | else { | ||||
| const MDeformVert *dvert = NULL; | 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); | 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), | static void extract_weights_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_weights = { | static const MeshExtract extract_weights = { | ||||
| .init = extract_weights_init, | .init = extract_weights_init, | ||||
| .iter_poly_bm = extract_weights_iter_poly_bm, | .iter_poly_bm = extract_weights_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_weights_iter_poly_mesh, | .iter_poly_mesh = extract_weights_iter_poly_mesh, | ||||
| .finish = extract_weights_finish, | .finish = extract_weights_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.weights)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit Mode Data / Flags | /** \name Extract Edit Mode Data / Flags | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct EditLoopData { | typedef struct EditLoopData { | ||||
| ▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { | ||||
| eattr->e_flag |= VFLAG_VERT_SELECTED; | eattr->e_flag |= VFLAG_VERT_SELECTED; | ||||
| } | } | ||||
| } | } | ||||
| static void *extract_edit_data_init(const MeshRenderData *mr, | static void *extract_edit_data_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 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_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); | ||||
| GPU_vertformat_alias_add(&format, "flag"); | GPU_vertformat_alias_add(&format, "flag"); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | ||||
| return GPU_vertbuf_get_data(vbo); | return GPU_vertbuf_get_data(vbo); | ||||
| } | } | ||||
| static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, | static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| BMLoop *l_iter, *l_first; | |||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | |||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | |||||
| { | |||||
| EditLoopData *data = (EditLoopData *)_data + l_index; | EditLoopData *data = (EditLoopData *)_data + l_index; | ||||
| memset(data, 0x0, sizeof(*data)); | memset(data, 0x0, sizeof(*data)); | ||||
| mesh_render_data_face_flag(mr, l->f, -1, data); | mesh_render_data_face_flag(mr, f, -1, data); | ||||
| mesh_render_data_edge_flag(mr, l->e, data); | mesh_render_data_edge_flag(mr, l_iter->e, data); | ||||
| mesh_render_data_vert_flag(mr, l->v, data); | mesh_render_data_vert_flag(mr, l_iter->v, data); | ||||
| } | } while ((l_iter = l_iter->next) != l_first); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | } | ||||
| static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| EditLoopData *data = (EditLoopData *)_data + ml_index; | EditLoopData *data = (EditLoopData *)_data + ml_index; | ||||
| memset(data, 0x0, sizeof(*data)); | memset(data, 0x0, sizeof(*data)); | ||||
| BMFace *efa = bm_original_face_get(mr, mp_index); | BMFace *efa = bm_original_face_get(mr, mp_index); | ||||
| BMEdge *eed = bm_original_edge_get(mr, ml->e); | BMEdge *eed = bm_original_edge_get(mr, ml->e); | ||||
| BMVert *eve = bm_original_vert_get(mr, ml->v); | BMVert *eve = bm_original_vert_get(mr, ml->v); | ||||
| if (efa) { | if (efa) { | ||||
| mesh_render_data_face_flag(mr, efa, -1, data); | mesh_render_data_face_flag(mr, efa, -1, data); | ||||
| } | } | ||||
| if (eed) { | if (eed) { | ||||
| mesh_render_data_edge_flag(mr, eed, data); | mesh_render_data_edge_flag(mr, eed, data); | ||||
| } | } | ||||
| if (eve) { | if (eve) { | ||||
| mesh_render_data_vert_flag(mr, eve, data); | mesh_render_data_vert_flag(mr, eve, data); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr, | static void extract_edit_data_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) | |||||
| { | |||||
| EditLoopData *data = (EditLoopData *)_data + mr->loop_len + (ledge_index * 2); | EditLoopData *data = (EditLoopData *)_data + mr->loop_len + (ledge_index * 2); | ||||
| memset(data, 0x0, sizeof(*data) * 2); | memset(data, 0x0, sizeof(*data) * 2); | ||||
| mesh_render_data_edge_flag(mr, eed, &data[0]); | mesh_render_data_edge_flag(mr, eed, &data[0]); | ||||
| data[1] = data[0]; | data[1] = data[0]; | ||||
| mesh_render_data_vert_flag(mr, eed->v1, &data[0]); | mesh_render_data_vert_flag(mr, eed->v1, &data[0]); | ||||
| mesh_render_data_vert_flag(mr, eed->v2, &data[1]); | 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, | static void extract_edit_data_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *med, | ||||
| const uint ledge_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) | |||||
| { | |||||
| EditLoopData *data = (EditLoopData *)_data + mr->loop_len + ledge_index * 2; | EditLoopData *data = (EditLoopData *)_data + mr->loop_len + ledge_index * 2; | ||||
| memset(data, 0x0, sizeof(*data) * 2); | memset(data, 0x0, sizeof(*data) * 2); | ||||
| const int e_index = mr->ledges[ledge_index]; | const int e_index = mr->ledges[ledge_index]; | ||||
| BMEdge *eed = bm_original_edge_get(mr, e_index); | BMEdge *eed = bm_original_edge_get(mr, e_index); | ||||
| BMVert *eve1 = bm_original_vert_get(mr, med->v1); | BMVert *eve1 = bm_original_vert_get(mr, med->v1); | ||||
| BMVert *eve2 = bm_original_vert_get(mr, med->v2); | BMVert *eve2 = bm_original_vert_get(mr, med->v2); | ||||
| if (eed) { | if (eed) { | ||||
| mesh_render_data_edge_flag(mr, eed, &data[0]); | mesh_render_data_edge_flag(mr, eed, &data[0]); | ||||
| data[1] = data[0]; | data[1] = data[0]; | ||||
| } | } | ||||
| if (eve1) { | if (eve1) { | ||||
| mesh_render_data_vert_flag(mr, eve1, &data[0]); | mesh_render_data_vert_flag(mr, eve1, &data[0]); | ||||
| } | } | ||||
| if (eve2) { | if (eve2) { | ||||
| mesh_render_data_vert_flag(mr, eve2, &data[1]); | mesh_render_data_vert_flag(mr, eve2, &data[1]); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr, | static void extract_edit_data_iter_lvert_bm(const MeshRenderData *mr, | ||||
| const ExtractLVertBMesh_Params *params, | BMVert *eve, | ||||
| const int lvert_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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; | EditLoopData *data = (EditLoopData *)_data + offset + lvert_index; | ||||
| memset(data, 0x0, sizeof(*data)); | memset(data, 0x0, sizeof(*data)); | ||||
| mesh_render_data_vert_flag(mr, eve, data); | mesh_render_data_vert_flag(mr, eve, data); | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, | static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr, | ||||
| const ExtractLVertMesh_Params *params, | const MVert *UNUSED(mv), | ||||
| const int lvert_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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; | EditLoopData *data = (EditLoopData *)_data + offset + lvert_index; | ||||
| memset(data, 0x0, sizeof(*data)); | memset(data, 0x0, sizeof(*data)); | ||||
| const int v_index = mr->lverts[lvert_index]; | const int v_index = mr->lverts[lvert_index]; | ||||
| BMVert *eve = bm_original_vert_get(mr, v_index); | BMVert *eve = bm_original_vert_get(mr, v_index); | ||||
| if (eve) { | if (eve) { | ||||
| mesh_render_data_vert_flag(mr, eve, data); | mesh_render_data_vert_flag(mr, eve, data); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_MESH_END; | |||||
| } | |||||
| static const MeshExtract extract_edit_data = { | static const MeshExtract extract_edit_data = { | ||||
| .init = extract_edit_data_init, | .init = extract_edit_data_init, | ||||
| .iter_poly_bm = extract_edit_data_iter_poly_bm, | .iter_poly_bm = extract_edit_data_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edit_data_iter_poly_mesh, | .iter_poly_mesh = extract_edit_data_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_edit_data_iter_ledge_bm, | .iter_ledge_bm = extract_edit_data_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_edit_data_iter_ledge_mesh, | .iter_ledge_mesh = extract_edit_data_iter_ledge_mesh, | ||||
| .iter_lvert_bm = extract_edit_data_iter_lvert_bm, | .iter_lvert_bm = extract_edit_data_iter_lvert_bm, | ||||
| .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh, | .iter_lvert_mesh = extract_edit_data_iter_lvert_mesh, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edit_data)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit UV Data / Flags | /** \name Extract Edit UV Data / Flags | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshExtract_EditUVData_Data { | typedef struct MeshExtract_EditUVData_Data { | ||||
| EditLoopData *vbo_data; | EditLoopData *vbo_data; | ||||
| int cd_ofs; | int cd_ofs; | ||||
| } MeshExtract_EditUVData_Data; | } MeshExtract_EditUVData_Data; | ||||
| static void *extract_edituv_data_init(const MeshRenderData *mr, | static void *extract_edituv_data_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 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_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT); | ||||
| GPU_vertformat_alias_add(&format, "flag"); | GPU_vertformat_alias_add(&format, "flag"); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; | ||||
| MeshExtract_EditUVData_Data *data = MEM_callocN(sizeof(*data), __func__); | MeshExtract_EditUVData_Data *data = MEM_callocN(sizeof(*data), __func__); | ||||
| data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); | data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); | ||||
| data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); | data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr, | static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| MeshExtract_EditUVData_Data *data = _data; | MeshExtract_EditUVData_Data *data = _data; | ||||
| EditLoopData *eldata = &data->vbo_data[l_index]; | EditLoopData *eldata = &data->vbo_data[l_index]; | ||||
| memset(eldata, 0x0, sizeof(*eldata)); | memset(eldata, 0x0, sizeof(*eldata)); | ||||
| mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata); | mesh_render_data_loop_flag(mr, l_iter, data->cd_ofs, eldata); | ||||
| mesh_render_data_face_flag(mr, l->f, data->cd_ofs, eldata); | mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); | ||||
| mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); | mesh_render_data_loop_edge_flag(mr, l_iter, data->cd_ofs, eldata); | ||||
| } | } while ((l_iter = l_iter->next) != l_first); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | } | ||||
| static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_EditUVData_Data *data = _data; | MeshExtract_EditUVData_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| EditLoopData *eldata = &data->vbo_data[ml_index]; | EditLoopData *eldata = &data->vbo_data[ml_index]; | ||||
| memset(eldata, 0x0, sizeof(*eldata)); | memset(eldata, 0x0, sizeof(*eldata)); | ||||
| BMFace *efa = bm_original_face_get(mr, mp_index); | BMFace *efa = bm_original_face_get(mr, mp_index); | ||||
| if (efa) { | if (efa) { | ||||
| BMEdge *eed = bm_original_edge_get(mr, ml->e); | BMEdge *eed = bm_original_edge_get(mr, ml->e); | ||||
| BMVert *eve = bm_original_vert_get(mr, ml->v); | BMVert *eve = bm_original_vert_get(mr, ml->v); | ||||
| if (eed && eve) { | if (eed && eve) { | ||||
| /* Loop on an edge endpoint. */ | /* Loop on an edge endpoint. */ | ||||
| Show All 13 Lines | if (efa) { | ||||
| if (eed) { | if (eed) { | ||||
| /* Mapped points on an edge between two edit verts. */ | /* Mapped points on an edge between two edit verts. */ | ||||
| BMLoop *l = BM_face_edge_share_loop(efa, eed); | BMLoop *l = BM_face_edge_share_loop(efa, eed); | ||||
| mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata); | 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), | static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_edituv_data = { | static const MeshExtract extract_edituv_data = { | ||||
| .init = extract_edituv_data_init, | .init = extract_edituv_data_init, | ||||
| .iter_poly_bm = extract_edituv_data_iter_poly_bm, | .iter_poly_bm = extract_edituv_data_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edituv_data_iter_poly_mesh, | .iter_poly_mesh = extract_edituv_data_iter_poly_mesh, | ||||
| .finish = extract_edituv_data_finish, | .finish = extract_edituv_data_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_data)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit UV area stretch | /** \name Extract Edit UV area stretch | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_edituv_stretch_area_init(const MeshRenderData *mr, | static void *extract_edituv_stretch_area_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_I16, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| BLI_INLINE float area_ratio_get(float area, float uvarea) | BLI_INLINE float area_ratio_get(float area, float uvarea) | ||||
| { | { | ||||
| if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) { | if (area >= FLT_EPSILON && uvarea >= FLT_EPSILON) { | ||||
| /* Tag inversion by using the sign. */ | /* Tag inversion by using the sign. */ | ||||
| return (area > uvarea) ? (uvarea / area) : -(area / uvarea); | return (area > uvarea) ? (uvarea / area) : -(area / uvarea); | ||||
| } | } | ||||
| return 0.0f; | return 0.0f; | ||||
| } | } | ||||
| BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio) | BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio) | ||||
| { | { | ||||
| ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio; | ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio; | ||||
| return (ratio > 1.0f) ? (1.0f / ratio) : ratio; | return (ratio > 1.0f) ? (1.0f / ratio) : ratio; | ||||
| } | } | ||||
| static void mesh_edituv_stretch_area_finish(const MeshRenderData *mr, | static void extract_edituv_stretch_area_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| void *buf, | void *buf, | ||||
| void *UNUSED(data)) | void *UNUSED(data)) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| float tot_area = 0.0f, tot_uv_area = 0.0f; | float tot_area = 0.0f, tot_uv_area = 0.0f; | ||||
| float *area_ratio = MEM_mallocN(sizeof(float) * mr->poly_len, __func__); | float *area_ratio = MEM_mallocN(sizeof(float) * mr->poly_len, __func__); | ||||
| if (mr->extract_type == MR_EXTRACT_BMESH) { | if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| CustomData *cd_ldata = &mr->bm->ldata; | CustomData *cd_ldata = &mr->bm->ldata; | ||||
| int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); | int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV); | ||||
| BMFace *efa; | BMFace *efa; | ||||
| Show All 25 Lines | static void extract_edituv_stretch_area_finish(const MeshRenderData *mr, | ||||
| /* Convert in place to avoid an extra allocation */ | /* Convert in place to avoid an extra allocation */ | ||||
| uint16_t *poly_stretch = (uint16_t *)area_ratio; | uint16_t *poly_stretch = (uint16_t *)area_ratio; | ||||
| for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { | for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) { | ||||
| poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX; | poly_stretch[mp_index] = area_ratio[mp_index] * SHRT_MAX; | ||||
| } | } | ||||
| /* Copy face data for each loop. */ | /* Copy face data for each loop. */ | ||||
| GPUVertBuf *vbo = buf; | |||||
| uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo); | uint16_t *loop_stretch = (uint16_t *)GPU_vertbuf_get_data(vbo); | ||||
| if (mr->extract_type == MR_EXTRACT_BMESH) { | if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| BMFace *efa; | BMFace *efa; | ||||
| BMIter f_iter; | BMIter f_iter; | ||||
| int f, l_index = 0; | int f, l_index = 0; | ||||
| BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { | BM_ITER_MESH_INDEX (efa, &f_iter, mr->bm, BM_FACES_OF_MESH, f) { | ||||
| for (int i = 0; i < efa->len; i++, l_index++) { | for (int i = 0; i < efa->len; i++, l_index++) { | ||||
| Show All 11 Lines | else { | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(area_ratio); | MEM_freeN(area_ratio); | ||||
| } | } | ||||
| static const MeshExtract extract_edituv_stretch_area = { | static const MeshExtract extract_edituv_stretch_area = { | ||||
| .init = extract_edituv_stretch_area_init, | .init = extract_edituv_stretch_area_init, | ||||
| .finish = mesh_edituv_stretch_area_finish, | .finish = extract_edituv_stretch_area_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_area)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit UV angle stretch | /** \name Extract Edit UV angle stretch | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct UVStretchAngle { | typedef struct UVStretchAngle { | ||||
| ▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | #if 0 /* here for reference, this is done in shader now. */ | ||||
| return 1.0f - pow2f(1.0f - stretch); | return 1.0f - pow2f(1.0f - stretch); | ||||
| #endif | #endif | ||||
| } | } | ||||
| static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr, | static void *extract_edituv_stretch_angle_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| /* Waning: 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, "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); | GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| MeshExtract_StretchAngle_Data *data = MEM_callocN(sizeof(*data), __func__); | MeshExtract_StretchAngle_Data *data = MEM_callocN(sizeof(*data), __func__); | ||||
| data->vbo_data = (UVStretchAngle *)GPU_vertbuf_get_data(vbo); | data->vbo_data = (UVStretchAngle *)GPU_vertbuf_get_data(vbo); | ||||
| /* Special iterator needed 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) { | if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); | data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); | BLI_assert(ELEM(mr->extract_type, MR_EXTRACT_MAPPED, MR_EXTRACT_MESH)); | ||||
| data->luv = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); | data->luv = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); | ||||
| } | } | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr, | static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_StretchAngle_Data *data = _data; | MeshExtract_StretchAngle_Data *data = _data; | ||||
| float(*auv)[2] = data->auv, *last_auv = data->last_auv; | float(*auv)[2] = data->auv, *last_auv = data->last_auv; | ||||
| float(*av)[3] = data->av, *last_av = data->last_av; | float(*av)[3] = data->av, *last_av = data->last_av; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| do { | |||||
| const int l_index = BM_elem_index_get(l_iter); | |||||
| const MLoopUV *luv, *luv_next; | const MLoopUV *luv, *luv_next; | ||||
| BMLoop *l_next = l->next; | BMLoop *l_next = l_iter->next; | ||||
| BMFace *efa = l->f; | if (l_iter == BM_FACE_FIRST_LOOP(f)) { | ||||
| if (l == BM_FACE_FIRST_LOOP(efa)) { | |||||
| /* First loop in face. */ | /* First loop in face. */ | ||||
| BMLoop *l_tmp = l->prev; | BMLoop *l_tmp = l_iter->prev; | ||||
| BMLoop *l_next_tmp = l; | BMLoop *l_next_tmp = l_iter; | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs); | 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); | luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs); | ||||
| compute_normalize_edge_vectors(auv, | compute_normalize_edge_vectors(auv, | ||||
| av, | av, | ||||
| luv->uv, | luv->uv, | ||||
| luv_next->uv, | luv_next->uv, | ||||
| bm_vert_co_get(mr, l_tmp->v), | bm_vert_co_get(mr, l_tmp->v), | ||||
| bm_vert_co_get(mr, l_next_tmp->v)); | bm_vert_co_get(mr, l_next_tmp->v)); | ||||
| /* Save last edge. */ | /* Save last edge. */ | ||||
| copy_v2_v2(last_auv, auv[1]); | copy_v2_v2(last_auv, auv[1]); | ||||
| copy_v3_v3(last_av, av[1]); | copy_v3_v3(last_av, av[1]); | ||||
| } | } | ||||
| if (l_next == BM_FACE_FIRST_LOOP(efa)) { | if (l_next == BM_FACE_FIRST_LOOP(f)) { | ||||
| /* Move previous edge. */ | /* Move previous edge. */ | ||||
| copy_v2_v2(auv[0], auv[1]); | copy_v2_v2(auv[0], auv[1]); | ||||
| copy_v3_v3(av[0], av[1]); | copy_v3_v3(av[0], av[1]); | ||||
| /* Copy already calculated last edge. */ | /* Copy already calculated last edge. */ | ||||
| copy_v2_v2(auv[1], last_auv); | copy_v2_v2(auv[1], last_auv); | ||||
| copy_v3_v3(av[1], last_av); | copy_v3_v3(av[1], last_av); | ||||
| } | } | ||||
| else { | else { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs); | luv = BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs); | ||||
| luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs); | luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs); | ||||
| compute_normalize_edge_vectors( | compute_normalize_edge_vectors(auv, | ||||
| auv, av, luv->uv, luv_next->uv, bm_vert_co_get(mr, l->v), bm_vert_co_get(mr, l_next->v)); | av, | ||||
| luv->uv, | |||||
| luv_next->uv, | |||||
| bm_vert_co_get(mr, l_iter->v), | |||||
| bm_vert_co_get(mr, l_next->v)); | |||||
| } | } | ||||
| edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]); | edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]); | ||||
| } | } while ((l_iter = l_iter->next) != l_first); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | |||||
| } | } | ||||
| static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_StretchAngle_Data *data = _data; | MeshExtract_StretchAngle_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| { | for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | ||||
| float(*auv)[2] = data->auv, *last_auv = data->last_auv; | float(*auv)[2] = data->auv, *last_auv = data->last_auv; | ||||
| float(*av)[3] = data->av, *last_av = data->last_av; | float(*av)[3] = data->av, *last_av = data->last_av; | ||||
| int l_next = ml_index + 1, ml_index_end = mp->loopstart + mp->totloop; | int l_next = ml_index + 1; | ||||
| const MVert *v, *v_next; | const MVert *v, *v_next; | ||||
| if (ml_index == mp->loopstart) { | if (ml_index == mp->loopstart) { | ||||
| /* First loop in face. */ | /* First loop in face. */ | ||||
| const int ml_index_last = ml_index_end - 1; | const int ml_index_last = ml_index_end - 1; | ||||
| const int l_next_tmp = mp->loopstart; | const int l_next_tmp = mp->loopstart; | ||||
| v = &mr->mvert[mr->mloop[ml_index_last].v]; | v = &mr->mvert[mr->mloop[ml_index_last].v]; | ||||
| v_next = &mr->mvert[mr->mloop[l_next_tmp].v]; | v_next = &mr->mvert[mr->mloop[l_next_tmp].v]; | ||||
| compute_normalize_edge_vectors( | compute_normalize_edge_vectors( | ||||
| Show All 14 Lines | for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | ||||
| else { | else { | ||||
| v = &mr->mvert[mr->mloop[ml_index].v]; | v = &mr->mvert[mr->mloop[ml_index].v]; | ||||
| v_next = &mr->mvert[mr->mloop[l_next].v]; | v_next = &mr->mvert[mr->mloop[l_next].v]; | ||||
| compute_normalize_edge_vectors( | compute_normalize_edge_vectors( | ||||
| auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co); | auv, av, data->luv[ml_index].uv, data->luv[l_next].uv, v->co, v_next->co); | ||||
| } | } | ||||
| edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]); | edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[ml_index]); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| static void extract_edituv_stretch_angle_finish(const MeshRenderData *UNUSED(mr), | static void extract_edituv_stretch_angle_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_edituv_stretch_angle = { | static const MeshExtract extract_edituv_stretch_angle = { | ||||
| .init = extract_edituv_stretch_angle_init, | .init = extract_edituv_stretch_angle_init, | ||||
| .iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm, | .iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh, | .iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh, | ||||
| .finish = extract_edituv_stretch_angle_finish, | .finish = extract_edituv_stretch_angle_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edituv_stretch_angle)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Edit Mesh Analysis Colors | /** \name Extract Edit Mesh Analysis Colors | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_mesh_analysis_init(const MeshRenderData *mr, | static void *extract_mesh_analysis_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static void axis_from_enum_v3(float v[3], const char axis) | static void axis_from_enum_v3(float v[3], const char axis) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 537 Lines • ▼ Show 20 Lines | else { | ||||
| for (int l_index = 0; l_index < mr->loop_len; l_index++, ml++) { | 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); | r_sharp[l_index] = sharp_remap(vert_angles[ml->v], min, max, minmax_irange); | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(vert_angles); | MEM_freeN(vert_angles); | ||||
| } | } | ||||
| static void extract_mesh_analysis_finish(const MeshRenderData *mr, | static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf, | void *buf, | ||||
| void *UNUSED(data)) | void *UNUSED(data)) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| BLI_assert(mr->edit_bmesh); | BLI_assert(mr->edit_bmesh); | ||||
| GPUVertBuf *vbo = buf; | |||||
| float *l_weight = (float *)GPU_vertbuf_get_data(vbo); | float *l_weight = (float *)GPU_vertbuf_get_data(vbo); | ||||
| switch (mr->toolsettings->statvis.type) { | switch (mr->toolsettings->statvis.type) { | ||||
| case SCE_STATVIS_OVERHANG: | case SCE_STATVIS_OVERHANG: | ||||
| statvis_calc_overhang(mr, l_weight); | statvis_calc_overhang(mr, l_weight); | ||||
| break; | break; | ||||
| case SCE_STATVIS_THICKNESS: | case SCE_STATVIS_THICKNESS: | ||||
| statvis_calc_thickness(mr, l_weight); | statvis_calc_thickness(mr, l_weight); | ||||
| break; | break; | ||||
| case SCE_STATVIS_INTERSECT: | case SCE_STATVIS_INTERSECT: | ||||
| statvis_calc_intersect(mr, l_weight); | statvis_calc_intersect(mr, l_weight); | ||||
| break; | break; | ||||
| case SCE_STATVIS_DISTORT: | case SCE_STATVIS_DISTORT: | ||||
| statvis_calc_distort(mr, l_weight); | statvis_calc_distort(mr, l_weight); | ||||
| break; | break; | ||||
| case SCE_STATVIS_SHARP: | case SCE_STATVIS_SHARP: | ||||
| statvis_calc_sharp(mr, l_weight); | statvis_calc_sharp(mr, l_weight); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| static const MeshExtract extract_mesh_analysis = { | static const MeshExtract extract_mesh_analysis = { | ||||
| .init = extract_mesh_analysis_init, | .init = extract_mesh_analysis_init, | ||||
| .finish = extract_mesh_analysis_finish, | .finish = extract_analysis_iter_finish_mesh, | ||||
| /* This is not needed for all visualization types. | /* This is not needed for all visualization types. | ||||
| * * Maybe split into different extract. */ | * * Maybe split into different extract. */ | ||||
| .data_flag = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, | .data_flag = MR_DATA_POLY_NOR | MR_DATA_LOOPTRI, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.mesh_analysis)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Facedots positions | /** \name Extract Facedots positions | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_fdots_pos_init(const MeshRenderData *mr, | static void *extract_fdots_pos_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->poly_len); | GPU_vertbuf_data_alloc(vbo, mr->poly_len); | ||||
| return GPU_vertbuf_get_data(vbo); | return GPU_vertbuf_get_data(vbo); | ||||
| } | } | ||||
| static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, | static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int f_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| float(*center)[3] = data; | float(*center)[3] = data; | ||||
| EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) | |||||
| { | |||||
| float *co = center[f_index]; | float *co = center[f_index]; | ||||
| zero_v3(co); | zero_v3(co); | ||||
| BMLoop *l_iter, *l_first; | BMLoop *l_iter, *l_first; | ||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| do { | do { | ||||
| add_v3_v3(co, bm_vert_co_get(mr, l_iter->v)); | add_v3_v3(co, bm_vert_co_get(mr, l_iter->v)); | ||||
| } while ((l_iter = l_iter->next) != l_first); | } while ((l_iter = l_iter->next) != l_first); | ||||
| mul_v3_fl(co, 1.0f / (float)f->len); | mul_v3_fl(co, 1.0f / (float)f->len); | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, | static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| float(*center)[3] = (float(*)[3])data; | float(*center)[3] = (float(*)[3])data; | ||||
| float *co = center[mp_index]; | |||||
| zero_v3(co); | |||||
| const MVert *mvert = mr->mvert; | const MVert *mvert = mr->mvert; | ||||
| const MLoop *mloop = mr->mloop; | const MLoop *mloop = mr->mloop; | ||||
| const int ml_index_end = mp->loopstart + mp->totloop; | |||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| if (mr->use_subsurf_fdots) { | if (mr->use_subsurf_fdots) { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | |||||
| { | |||||
| const MVert *mv = &mr->mvert[ml->v]; | const MVert *mv = &mr->mvert[ml->v]; | ||||
| if (mv->flag & ME_VERT_FACEDOT) { | if (mv->flag & ME_VERT_FACEDOT) { | ||||
| copy_v3_v3(center[mp_index], mv->co); | copy_v3_v3(center[mp_index], mv->co); | ||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | |||||
| else { | else { | ||||
| EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) | |||||
| { | |||||
| float *co = center[mp_index]; | |||||
| zero_v3(co); | |||||
| const MLoop *ml = &mloop[mp->loopstart]; | |||||
| for (int i = 0; i < mp->totloop; i++, ml++) { | |||||
| const MVert *mv = &mvert[ml->v]; | const MVert *mv = &mvert[ml->v]; | ||||
| add_v3_v3(center[mp_index], mv->co); | add_v3_v3(center[mp_index], mv->co); | ||||
| } | } | ||||
| mul_v3_fl(co, 1.0f / (float)mp->totloop); | |||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| if (!mr->use_subsurf_fdots) { | |||||
| mul_v3_fl(co, 1.0f / (float)mp->totloop); | |||||
| } | } | ||||
| } | } | ||||
| static const MeshExtract extract_fdots_pos = { | static const MeshExtract extract_fdots_pos = { | ||||
| .init = extract_fdots_pos_init, | .init = extract_fdots_pos_init, | ||||
| .iter_poly_bm = extract_fdots_pos_iter_poly_bm, | .iter_poly_bm = extract_fdots_pos_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh, | .iter_poly_mesh = extract_fdots_pos_iter_poly_mesh, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_pos)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Facedots Normal and edit flag | /** \name Extract Facedots Normal and edit flag | ||||
| * \{ */ | * \{ */ | ||||
| #define NOR_AND_FLAG_DEFAULT 0 | #define NOR_AND_FLAG_DEFAULT 0 | ||||
| #define NOR_AND_FLAG_SELECT 1 | #define NOR_AND_FLAG_SELECT 1 | ||||
| #define NOR_AND_FLAG_ACTIVE -1 | #define NOR_AND_FLAG_ACTIVE -1 | ||||
| #define NOR_AND_FLAG_HIDDEN -2 | #define NOR_AND_FLAG_HIDDEN -2 | ||||
| static void *extract_fdots_nor_init(const MeshRenderData *mr, | static void *extract_fdots_nor_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->poly_len); | GPU_vertbuf_data_alloc(vbo, mr->poly_len); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static void extract_fdots_nor_finish(const MeshRenderData *mr, | static void extract_fdots_nor_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf, | void *buf, | ||||
| void *UNUSED(data)) | void *UNUSED(data)) | ||||
| { | { | ||||
| static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; | |||||
| GPUVertBuf *vbo = buf; | GPUVertBuf *vbo = buf; | ||||
| static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; | |||||
| GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo); | GPUPackedNormal *nor = (GPUPackedNormal *)GPU_vertbuf_get_data(vbo); | ||||
| BMFace *efa; | BMFace *efa; | ||||
| /* Quicker than doing it for each loop. */ | /* Quicker than doing it for each loop. */ | ||||
| if (mr->extract_type == MR_EXTRACT_BMESH) { | if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| for (int f = 0; f < mr->poly_len; f++) { | for (int f = 0; f < mr->poly_len; f++) { | ||||
| efa = BM_face_at_index(mr->bm, f); | efa = BM_face_at_index(mr->bm, f); | ||||
| const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); | const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); | ||||
| Show All 31 Lines | static void extract_fdots_nor_finish(const MeshRenderData *mr, | ||||
| } | } | ||||
| } | } | ||||
| static const MeshExtract extract_fdots_nor = { | static const MeshExtract extract_fdots_nor = { | ||||
| .init = extract_fdots_nor_init, | .init = extract_fdots_nor_init, | ||||
| .finish = extract_fdots_nor_finish, | .finish = extract_fdots_nor_finish, | ||||
| .data_flag = MR_DATA_POLY_NOR, | .data_flag = MR_DATA_POLY_NOR, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Facedots High Quality Normal and edit flag | /** \name Extract Facedots High Quality Normal and edit flag | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_fdots_nor_hq_init(const MeshRenderData *mr, | static void *extract_fdots_nor_hq_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->poly_len); | GPU_vertbuf_data_alloc(vbo, mr->poly_len); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static void extract_fdots_nor_hq_finish(const MeshRenderData *mr, | static void extract_fdots_nor_hq_finish(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf, | void *buf, | ||||
| void *UNUSED(data)) | void *UNUSED(data)) | ||||
| { | { | ||||
| static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; | |||||
| GPUVertBuf *vbo = buf; | GPUVertBuf *vbo = buf; | ||||
| static float invalid_normal[3] = {0.0f, 0.0f, 0.0f}; | |||||
| short *nor = (short *)GPU_vertbuf_get_data(vbo); | short *nor = (short *)GPU_vertbuf_get_data(vbo); | ||||
| BMFace *efa; | BMFace *efa; | ||||
| /* Quicker than doing it for each loop. */ | /* Quicker than doing it for each loop. */ | ||||
| if (mr->extract_type == MR_EXTRACT_BMESH) { | if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| for (int f = 0; f < mr->poly_len; f++) { | for (int f = 0; f < mr->poly_len; f++) { | ||||
| efa = BM_face_at_index(mr->bm, f); | efa = BM_face_at_index(mr->bm, f); | ||||
| const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); | const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); | ||||
| Show All 31 Lines | static void extract_fdots_nor_hq_finish(const MeshRenderData *mr, | ||||
| } | } | ||||
| } | } | ||||
| static const MeshExtract extract_fdots_nor_hq = { | static const MeshExtract extract_fdots_nor_hq = { | ||||
| .init = extract_fdots_nor_hq_init, | .init = extract_fdots_nor_hq_init, | ||||
| .finish = extract_fdots_nor_hq_finish, | .finish = extract_fdots_nor_hq_finish, | ||||
| .data_flag = MR_DATA_POLY_NOR, | .data_flag = MR_DATA_POLY_NOR, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_nor)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Facedots UV | /** \name Extract Facedots UV | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshExtract_FdotUV_Data { | typedef struct MeshExtract_FdotUV_Data { | ||||
| float (*vbo_data)[2]; | float (*vbo_data)[2]; | ||||
| MLoopUV *uv_data; | MLoopUV *uv_data; | ||||
| int cd_ofs; | int cd_ofs; | ||||
| } MeshExtract_FdotUV_Data; | } MeshExtract_FdotUV_Data; | ||||
| static void *extract_fdots_uv_init(const MeshRenderData *mr, | static void *extract_fdots_uv_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "u", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | ||||
| GPU_vertformat_alias_add(&format, "au"); | GPU_vertformat_alias_add(&format, "au"); | ||||
| GPU_vertformat_alias_add(&format, "pos"); | GPU_vertformat_alias_add(&format, "pos"); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->poly_len); | GPU_vertbuf_data_alloc(vbo, mr->poly_len); | ||||
| if (!mr->use_subsurf_fdots) { | if (!mr->use_subsurf_fdots) { | ||||
| /* Clear so we can accumulate on it. */ | /* Clear so we can accumulate on it. */ | ||||
| memset(GPU_vertbuf_get_data(vbo), 0x0, mr->poly_len * GPU_vertbuf_get_format(vbo)->stride); | memset(GPU_vertbuf_get_data(vbo), 0x0, mr->poly_len * GPU_vertbuf_get_format(vbo)->stride); | ||||
| } | } | ||||
| MeshExtract_FdotUV_Data *data = MEM_callocN(sizeof(*data), __func__); | MeshExtract_FdotUV_Data *data = MEM_callocN(sizeof(*data), __func__); | ||||
| data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo); | data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo); | ||||
| if (mr->extract_type == MR_EXTRACT_BMESH) { | if (mr->extract_type == MR_EXTRACT_BMESH) { | ||||
| data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); | data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); | ||||
| } | } | ||||
| else { | else { | ||||
| data->uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); | data->uv_data = CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV); | ||||
| } | } | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *mr, | static void extract_fdots_uv_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_FdotUV_Data *data = _data; | MeshExtract_FdotUV_Data *data = _data; | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| float w = 1.0f / (float)l->f->len; | do { | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, data->cd_ofs); | float w = 1.0f / (float)f->len; | ||||
| madd_v2_v2fl(data->vbo_data[BM_elem_index_get(l->f)], luv->uv, w); | const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs); | ||||
| } | madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv->uv, w); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | } | ||||
| static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, | static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_FdotUV_Data *data = _data; | MeshExtract_FdotUV_Data *data = _data; | ||||
| const MLoop *mloop = mr->mloop; | |||||
| const int ml_index_end = mp->loopstart + mp->totloop; | |||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| if (mr->use_subsurf_fdots) { | if (mr->use_subsurf_fdots) { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | |||||
| { | |||||
| const MVert *mv = &mr->mvert[ml->v]; | const MVert *mv = &mr->mvert[ml->v]; | ||||
| if (mv->flag & ME_VERT_FACEDOT) { | if (mv->flag & ME_VERT_FACEDOT) { | ||||
| copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv); | copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv); | ||||
| } | } | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | |||||
| else { | else { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | |||||
| { | |||||
| float w = 1.0f / (float)mp->totloop; | float w = 1.0f / (float)mp->totloop; | ||||
| madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w); | madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w); | ||||
| } | } | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; | |||||
| } | } | ||||
| } | } | ||||
| static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr), | static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_fdots_uv = { | static const MeshExtract extract_fdots_uv = { | ||||
| .init = extract_fdots_uv_init, | .init = extract_fdots_uv_init, | ||||
| .iter_poly_bm = extract_fdots_uv_iter_poly_bm, | .iter_poly_bm = extract_fdots_uv_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh, | .iter_poly_mesh = extract_fdots_uv_iter_poly_mesh, | ||||
| .finish = extract_fdots_uv_finish, | .finish = extract_fdots_uv_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_uv)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Facedots Edit UV flag | /** \name Extract Facedots Edit UV flag | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshExtract_EditUVFdotData_Data { | typedef struct MeshExtract_EditUVFdotData_Data { | ||||
| EditLoopData *vbo_data; | EditLoopData *vbo_data; | ||||
| int cd_ofs; | int cd_ofs; | ||||
| } MeshExtract_EditUVFdotData_Data; | } MeshExtract_EditUVFdotData_Data; | ||||
| static void *extract_fdots_edituv_data_init(const MeshRenderData *mr, | static void *extract_fdots_edituv_data_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U8, 4, GPU_FETCH_INT); | GPU_vertformat_attr_add(&format, "flag", GPU_COMP_U8, 4, GPU_FETCH_INT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->poly_len); | GPU_vertbuf_data_alloc(vbo, mr->poly_len); | ||||
| MeshExtract_EditUVFdotData_Data *data = MEM_callocN(sizeof(*data), __func__); | MeshExtract_EditUVFdotData_Data *data = MEM_callocN(sizeof(*data), __func__); | ||||
| data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); | data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo); | ||||
| data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); | data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV); | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr, | static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr, | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_EditUVFdotData_Data *data = _data; | 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)]; | EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)]; | ||||
| memset(eldata, 0x0, sizeof(*eldata)); | memset(eldata, 0x0, sizeof(*eldata)); | ||||
| mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); | mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata); | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr, | static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *UNUSED(mp), | ||||
| const int mp_index, | |||||
| void *_data) | void *_data) | ||||
| { | { | ||||
| MeshExtract_EditUVFdotData_Data *data = _data; | MeshExtract_EditUVFdotData_Data *data = _data; | ||||
| EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) | |||||
| { | |||||
| EditLoopData *eldata = &data->vbo_data[mp_index]; | EditLoopData *eldata = &data->vbo_data[mp_index]; | ||||
| memset(eldata, 0x0, sizeof(*eldata)); | memset(eldata, 0x0, sizeof(*eldata)); | ||||
| BMFace *efa = bm_original_face_get(mr, mp_index); | BMFace *efa = bm_original_face_get(mr, mp_index); | ||||
| if (efa) { | if (efa) { | ||||
| mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata); | 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), | static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr), | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *UNUSED(buf), | void *UNUSED(buf), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| } | } | ||||
| static const MeshExtract extract_fdots_edituv_data = { | static const MeshExtract extract_fdots_edituv_data = { | ||||
| .init = extract_fdots_edituv_data_init, | .init = extract_fdots_edituv_data_init, | ||||
| .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm, | .iter_poly_bm = extract_fdots_edituv_data_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh, | .iter_poly_mesh = extract_fdots_edituv_data_iter_poly_mesh, | ||||
| .finish = extract_fdots_edituv_data_finish, | .finish = extract_fdots_edituv_data_finish, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdots_edituv_data)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Skin Modifier Roots | /** \name Extract Skin Modifier Roots | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct SkinRootData { | typedef struct SkinRootData { | ||||
| float size; | float size; | ||||
| float local_pos[3]; | float local_pos[3]; | ||||
| } SkinRootData; | } SkinRootData; | ||||
| static void *extract_skin_roots_init(const MeshRenderData *mr, | static void *extract_skin_roots_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| /* Exclusively for edit mode. */ | /* Exclusively for edit mode. */ | ||||
| BLI_assert(mr->bm); | BLI_assert(mr->bm); | ||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); | ||||
| GPU_vertformat_attr_add(&format, "local_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); | GPU_vertformat_attr_add(&format, "local_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->bm->totvert); | GPU_vertbuf_data_alloc(vbo, mr->bm->totvert); | ||||
| SkinRootData *vbo_data = (SkinRootData *)GPU_vertbuf_get_data(vbo); | SkinRootData *vbo_data = (SkinRootData *)GPU_vertbuf_get_data(vbo); | ||||
| int root_len = 0; | int root_len = 0; | ||||
| int cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MVERT_SKIN); | int cd_ofs = CustomData_get_offset(&mr->bm->vdata, CD_MVERT_SKIN); | ||||
| Show All 14 Lines | static void *extract_skin_roots_init(const MeshRenderData *mr, | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static const MeshExtract extract_skin_roots = { | static const MeshExtract extract_skin_roots = { | ||||
| .init = extract_skin_roots_init, | .init = extract_skin_roots_init, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = false, | .use_threading = false, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.skin_roots)}; | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Selection Index | /** \name Extract Selection Index | ||||
| * \{ */ | * \{ */ | ||||
| static void *extract_select_idx_init(const MeshRenderData *mr, | static void *extract_select_idx_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| /* TODO rename "color" to something more descriptive. */ | /* TODO rename "color" to something more descriptive. */ | ||||
| GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT); | GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); | ||||
| return GPU_vertbuf_get_data(vbo); | return GPU_vertbuf_get_data(vbo); | ||||
| } | } | ||||
| /* 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 | * select element associated with this loop ID. This would remove the need for this separate | ||||
| * index VBO's. 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. */ | * shader to output original index. */ | ||||
| static void extract_poly_idx_iter_poly_bm(const MeshRenderData *mr, | static void extract_poly_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int f_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| ((uint32_t *)data)[l_index] = BM_elem_index_get(l->f); | do { | ||||
| } | const int l_index = BM_elem_index_get(l_iter); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | ((uint32_t *)data)[l_index] = f_index; | ||||
| } while ((l_iter = l_iter->next) != l_first); | |||||
| } | } | ||||
| static void extract_edge_idx_iter_poly_bm(const MeshRenderData *mr, | static void extract_edge_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| ((uint32_t *)data)[l_index] = BM_elem_index_get(l->e); | do { | ||||
| } | const int l_index = BM_elem_index_get(l_iter); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | ((uint32_t *)data)[l_index] = BM_elem_index_get(l_iter->e); | ||||
| } while ((l_iter = l_iter->next) != l_first); | |||||
| } | } | ||||
| static void extract_vert_idx_iter_poly_bm(const MeshRenderData *mr, | static void extract_vert_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *f, | ||||
| const int UNUSED(f_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) | BMLoop *l_iter, *l_first; | ||||
| { | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| ((uint32_t *)data)[l_index] = BM_elem_index_get(l->v); | do { | ||||
| } | const int l_index = BM_elem_index_get(l_iter); | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); | ((uint32_t *)data)[l_index] = BM_elem_index_get(l_iter->v); | ||||
| } while ((l_iter = l_iter->next) != l_first); | |||||
| } | } | ||||
| static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr, | static void extract_edge_idx_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| 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 + 0] = BM_elem_index_get(eed); | ||||
| ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = 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_iter_ledge_bm(const MeshRenderData *mr, | static void extract_vert_idx_iter_ledge_bm(const MeshRenderData *mr, | ||||
| const ExtractLEdgeBMesh_Params *params, | BMEdge *eed, | ||||
| const int ledge_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| 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 + 0] = BM_elem_index_get(eed->v1); | ||||
| ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = BM_elem_index_get(eed->v2); | ((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_iter_lvert_bm(const MeshRenderData *mr, | static void extract_vert_idx_iter_lvert_bm(const MeshRenderData *mr, | ||||
| const ExtractLVertBMesh_Params *params, | BMVert *eve, | ||||
| const int lvert_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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); | ((uint32_t *)data)[offset + lvert_index] = BM_elem_index_get(eve); | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, | static void extract_poly_idx_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int mp_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| { | for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | ||||
| ((uint32_t *)data)[ml_index] = (mr->p_origindex) ? mr->p_origindex[mp_index] : mp_index; | ((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_iter_poly_mesh(const MeshRenderData *mr, | static void extract_edge_idx_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| ((uint32_t *)data)[ml_index] = (mr->e_origindex) ? mr->e_origindex[ml->e] : ml->e; | ((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_iter_poly_mesh(const MeshRenderData *mr, | static void extract_vert_idx_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *mp, | ||||
| const int UNUSED(mp_index), | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) | const MLoop *mloop = mr->mloop; | ||||
| { | const int ml_index_end = mp->loopstart + mp->totloop; | ||||
| for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) { | |||||
| const MLoop *ml = &mloop[ml_index]; | |||||
| ((uint32_t *)data)[ml_index] = (mr->v_origindex) ? mr->v_origindex[ml->v] : ml->v; | ((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_iter_ledge_mesh(const MeshRenderData *mr, | static void extract_edge_idx_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *UNUSED(med), | ||||
| const uint ledge_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) | |||||
| { | |||||
| const int e_index = mr->ledges[ledge_index]; | const int e_index = mr->ledges[ledge_index]; | ||||
| const int e_orig = (mr->e_origindex) ? mr->e_origindex[e_index] : e_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 + 0] = e_orig; | ||||
| ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig; | ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = e_orig; | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr, | static void extract_vert_idx_iter_ledge_mesh(const MeshRenderData *mr, | ||||
| const ExtractLEdgeMesh_Params *params, | const MEdge *med, | ||||
| const uint ledge_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) | |||||
| { | |||||
| int v1_orig = (mr->v_origindex) ? mr->v_origindex[med->v1] : med->v1; | 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; | 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 + 0] = v1_orig; | ||||
| ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig; | ((uint32_t *)data)[mr->loop_len + ledge_index * 2 + 1] = v2_orig; | ||||
| } | } | ||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr, | static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr, | ||||
| const ExtractLVertMesh_Params *params, | const MVert *UNUSED(mv), | ||||
| const int lvert_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| const int offset = mr->loop_len + (mr->edge_loose_len * 2); | 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_index = mr->lverts[lvert_index]; | ||||
| const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index; | const int v_orig = (mr->v_origindex) ? mr->v_origindex[v_index] : v_index; | ||||
| ((uint32_t *)data)[offset + lvert_index] = v_orig; | ((uint32_t *)data)[offset + lvert_index] = v_orig; | ||||
| } | } | ||||
| EXTRACT_LVERT_FOREACH_MESH_END; | |||||
| } | |||||
| static const MeshExtract extract_poly_idx = { | static const MeshExtract extract_poly_idx = { | ||||
| .init = extract_select_idx_init, | .init = extract_select_idx_init, | ||||
| .iter_poly_bm = extract_poly_idx_iter_poly_bm, | .iter_poly_bm = extract_poly_idx_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_poly_idx_iter_poly_mesh, | .iter_poly_mesh = extract_poly_idx_iter_poly_mesh, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.poly_idx)}; | ||||
| static const MeshExtract extract_edge_idx = { | static const MeshExtract extract_edge_idx = { | ||||
| .init = extract_select_idx_init, | .init = extract_select_idx_init, | ||||
| .iter_poly_bm = extract_edge_idx_iter_poly_bm, | .iter_poly_bm = extract_edge_idx_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_edge_idx_iter_poly_mesh, | .iter_poly_mesh = extract_edge_idx_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_edge_idx_iter_ledge_bm, | .iter_ledge_bm = extract_edge_idx_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh, | .iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.edge_idx)}; | ||||
| static const MeshExtract extract_vert_idx = { | static const MeshExtract extract_vert_idx = { | ||||
| .init = extract_select_idx_init, | .init = extract_select_idx_init, | ||||
| .iter_poly_bm = extract_vert_idx_iter_poly_bm, | .iter_poly_bm = extract_vert_idx_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_vert_idx_iter_poly_mesh, | .iter_poly_mesh = extract_vert_idx_iter_poly_mesh, | ||||
| .iter_ledge_bm = extract_vert_idx_iter_ledge_bm, | .iter_ledge_bm = extract_vert_idx_iter_ledge_bm, | ||||
| .iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh, | .iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh, | ||||
| .iter_lvert_bm = extract_vert_idx_iter_lvert_bm, | .iter_lvert_bm = extract_vert_idx_iter_lvert_bm, | ||||
| .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh, | .iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.vert_idx)}; | ||||
| static void *extract_select_fdot_idx_init(const MeshRenderData *mr, | static void *extract_fdot_idx_init(const MeshRenderData *mr, | ||||
| struct MeshBatchCache *UNUSED(cache), | struct MeshBatchCache *UNUSED(cache), | ||||
| void *buf) | void *buf) | ||||
| { | { | ||||
| GPUVertBuf *vbo = buf; | |||||
| static GPUVertFormat format = {0}; | static GPUVertFormat format = {0}; | ||||
| if (format.attr_len == 0) { | if (format.attr_len == 0) { | ||||
| /* TODO rename "color" to something more descriptive. */ | /* TODO rename "color" to something more descriptive. */ | ||||
| GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT); | GPU_vertformat_attr_add(&format, "color", GPU_COMP_U32, 1, GPU_FETCH_INT); | ||||
| } | } | ||||
| GPUVertBuf *vbo = buf; | |||||
| GPU_vertbuf_init_with_format(vbo, &format); | GPU_vertbuf_init_with_format(vbo, &format); | ||||
| GPU_vertbuf_data_alloc(vbo, mr->poly_len); | GPU_vertbuf_data_alloc(vbo, mr->poly_len); | ||||
| return GPU_vertbuf_get_data(vbo); | return GPU_vertbuf_get_data(vbo); | ||||
| } | } | ||||
| static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *mr, | static void extract_fdot_idx_iter_poly_bm(const MeshRenderData *UNUSED(mr), | ||||
| const ExtractPolyBMesh_Params *params, | BMFace *UNUSED(f), | ||||
| const int f_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) | |||||
| { | |||||
| ((uint32_t *)data)[f_index] = f_index; | ((uint32_t *)data)[f_index] = f_index; | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_BM_END; | |||||
| } | |||||
| static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, | static void extract_fdot_idx_iter_poly_mesh(const MeshRenderData *mr, | ||||
| const ExtractPolyMesh_Params *params, | const MPoly *UNUSED(mp), | ||||
| const int mp_index, | |||||
| void *data) | void *data) | ||||
| { | { | ||||
| if (mr->p_origindex != NULL) { | 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]; | ((uint32_t *)data)[mp_index] = mr->p_origindex[mp_index]; | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| } | |||||
| else { | else { | ||||
| EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) | |||||
| { | |||||
| ((uint32_t *)data)[mp_index] = mp_index; | ((uint32_t *)data)[mp_index] = mp_index; | ||||
| } | } | ||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| } | |||||
| } | } | ||||
| static const MeshExtract extract_fdot_idx = { | static const MeshExtract extract_fdot_idx = { | ||||
| .init = extract_select_fdot_idx_init, | .init = extract_fdot_idx_init, | ||||
| .iter_poly_bm = extract_fdot_idx_iter_poly_bm, | .iter_poly_bm = extract_fdot_idx_iter_poly_bm, | ||||
| .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh, | .iter_poly_mesh = extract_fdot_idx_iter_poly_mesh, | ||||
| .data_flag = 0, | .data_flag = 0, | ||||
| .use_threading = true, | .use_threading = true, | ||||
| }; | .mesh_buffer_offset = offsetof(MeshBufferCache, vbo.fdot_idx)}; | ||||
| /* ---------------------------------------------------------------------- */ | |||||
| /** \name Extract | |||||
| * \{ */ | |||||
| static void extracts_flags_get(const MeshExtractRunDataArray *extractors, | |||||
| eMRIterType *r_iter_type, | |||||
| eMRDataType *r_data_flag) | |||||
| { | |||||
| eMRIterType iter_type = 0; | |||||
| eMRDataType data_flag = 0; | |||||
| for (int i = 0; i < extractors->len; i++) { | |||||
| const MeshExtract *extractor = extractors->items[i].extractor; | |||||
| iter_type |= mesh_extract_iter_type(extractor); | |||||
| data_flag |= extractor->data_flag; | |||||
| } | |||||
| if (r_iter_type) { | |||||
| *r_iter_type = iter_type; | |||||
| } | |||||
| if (r_data_flag) { | |||||
| *r_data_flag = data_flag; | |||||
| } | |||||
| } | |||||
| BLI_INLINE void extract_init(const MeshRenderData *mr, | |||||
| struct MeshBatchCache *cache, | |||||
| MeshExtractRunDataArray *extractors, | |||||
| MeshBufferCache *mbc) | |||||
| { | |||||
| /* Multi thread. */ | |||||
| for (int i = 0; i < extractors->len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors->items[i]; | |||||
| const MeshExtract *extractor = run_data->extractor; | |||||
| run_data->buffer = mesh_extract_buffer_get(extractor, mbc); | |||||
| run_data->user_data = extractor->init(mr, cache, run_data->buffer); | |||||
| } | |||||
| } | |||||
| BLI_INLINE void extract_iter_looptri_bm(const MeshRenderData *mr, | |||||
| const ExtractTriBMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_LOOPTRI); | |||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_BM_BEGIN(elt, elt_index, params) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_looptri_bm(mr, elt, elt_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_BM_END; | |||||
| } | |||||
| BLI_INLINE void extract_iter_looptri_mesh(const MeshRenderData *mr, | |||||
| const ExtractTriMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_LOOPTRI); | |||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_BEGIN(mlt, mlt_index, params) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_looptri_mesh(mr, mlt, mlt_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_TRIS_LOOPTRI_FOREACH_MESH_END; | |||||
| } | |||||
| BLI_INLINE void extract_iter_poly_bm(const MeshRenderData *mr, | |||||
| const ExtractPolyBMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_POLY); | |||||
| EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_poly_bm(mr, f, f_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_POLY_FOREACH_BM_END; | |||||
| } | |||||
| BLI_INLINE void extract_iter_poly_mesh(const MeshRenderData *mr, | |||||
| const ExtractPolyMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_POLY); | |||||
| EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_poly_mesh(mr, mp, mp_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_POLY_FOREACH_MESH_END; | |||||
| } | |||||
| BLI_INLINE void extract_iter_ledge_bm(const MeshRenderData *mr, | |||||
| const ExtractLEdgeBMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_LEDGE); | |||||
| EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_ledge_bm(mr, eed, ledge_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_LEDGE_FOREACH_BM_END; | |||||
| } | |||||
| BLI_INLINE void extract_iter_ledge_mesh(const MeshRenderData *mr, | |||||
| const ExtractLEdgeMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_LEDGE); | |||||
| EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_ledge_mesh(mr, med, ledge_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_LEDGE_FOREACH_MESH_END; | |||||
| } | |||||
| BLI_INLINE void extract_iter_lvert_bm(const MeshRenderData *mr, | |||||
| const ExtractLVertBMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_LVERT); | |||||
| EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_lvert_bm(mr, eve, lvert_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_LVERT_FOREACH_BM_END; | |||||
| } | |||||
| BLI_INLINE void extract_iter_lvert_mesh(const MeshRenderData *mr, | |||||
| const ExtractLVertMesh_Params *params, | |||||
| const MeshExtractRunDataArray *_extractors) | |||||
| { | |||||
| MeshExtractRunDataArray extractors; | |||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| mesh_extract_run_data_array_filter_iter_type(_extractors, &extractors, MR_ITER_LVERT); | |||||
| EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr) | |||||
| { | |||||
| for (int i = 0; i < extractors.len; i++) { | |||||
| MeshExtractRunData *run_data = &extractors.items[i]; | |||||
| run_data->extractor->iter_lvert_mesh(mr, mv, lvert_index, run_data->user_data); | |||||
| } | |||||
| } | |||||
| EXTRACT_LVERT_FOREACH_MESH_END; | |||||
| } | |||||
| BLI_INLINE void extract_finish(const MeshRenderData *mr, | |||||
| struct MeshBatchCache *cache, | |||||
| const MeshExtractRunDataArray *extractors) | |||||
| { | |||||
| for (int i = 0; i < extractors->len; i++) { | |||||
| const MeshExtractRunData *run_data = &extractors->items[i]; | |||||
| const MeshExtract *extractor = run_data->extractor; | |||||
| if (extractor->finish) { | |||||
| extractor->finish(mr, cache, run_data->buffer, run_data->user_data); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* Single Thread. */ | |||||
| BLI_INLINE void extract_run_and_finish_init(const MeshRenderData *mr, | |||||
| struct MeshBatchCache *cache, | |||||
| MeshExtractRunDataArray *extractors, | |||||
| eMRIterType iter_type, | |||||
| MeshBufferCache *mbc) | |||||
| { | |||||
| extract_init(mr, cache, extractors, mbc); | |||||
| bool is_mesh = mr->extract_type != MR_EXTRACT_BMESH; | |||||
| if (iter_type & MR_ITER_LOOPTRI) { | |||||
| if (is_mesh) { | |||||
| extract_iter_looptri_mesh(mr, | |||||
| &(const ExtractTriMesh_Params){ | |||||
| .mlooptri = mr->mlooptri, | |||||
| .tri_range = {0, mr->tri_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| else { | |||||
| extract_iter_looptri_bm(mr, | |||||
| &(const ExtractTriBMesh_Params){ | |||||
| .looptris = mr->edit_bmesh->looptris, | |||||
| .tri_range = {0, mr->tri_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| } | |||||
| if (iter_type & MR_ITER_POLY) { | |||||
| if (is_mesh) { | |||||
| extract_iter_poly_mesh(mr, | |||||
| &(const ExtractPolyMesh_Params){ | |||||
| .poly_range = {0, mr->poly_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| else { | |||||
| extract_iter_poly_bm(mr, | |||||
| &(const ExtractPolyBMesh_Params){ | |||||
| .poly_range = {0, mr->poly_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| } | |||||
| if (iter_type & MR_ITER_LEDGE) { | |||||
| if (is_mesh) { | |||||
| extract_iter_ledge_mesh(mr, | |||||
| &(const ExtractLEdgeMesh_Params){ | |||||
| .ledge = mr->ledges, | |||||
| .ledge_range = {0, mr->edge_loose_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| else { | |||||
| extract_iter_ledge_bm(mr, | |||||
| &(const ExtractLEdgeBMesh_Params){ | |||||
| .ledge = mr->ledges, | |||||
| .ledge_range = {0, mr->edge_loose_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| } | |||||
| if (iter_type & MR_ITER_LVERT) { | |||||
| if (is_mesh) { | |||||
| extract_iter_lvert_mesh(mr, | |||||
| &(const ExtractLVertMesh_Params){ | |||||
| .lvert = mr->lverts, | |||||
| .lvert_range = {0, mr->vert_loose_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| else { | |||||
| extract_iter_lvert_bm(mr, | |||||
| &(const ExtractLVertBMesh_Params){ | |||||
| .lvert = mr->lverts, | |||||
| .lvert_range = {0, mr->vert_loose_len}, | |||||
| }, | |||||
| extractors); | |||||
| } | |||||
| } | |||||
| extract_finish(mr, cache, extractors); | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name ExtractTaskData | /** \name ExtractTaskData | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct ExtractUserData { | |||||
| void *user_data; | |||||
| } ExtractUserData; | |||||
| typedef enum ExtractTaskDataType { | |||||
| EXTRACT_MESH_EXTRACT, | |||||
| EXTRACT_LINES_LOOSE, | |||||
| } ExtractTaskDataType; | |||||
| typedef struct ExtractTaskData { | typedef struct ExtractTaskData { | ||||
| void *next, *prev; | void *next, *prev; | ||||
| const MeshRenderData *mr; | const MeshRenderData *mr; | ||||
| struct MeshBatchCache *cache; | struct MeshBatchCache *cache; | ||||
| const MeshExtract *extract; | MeshExtractRunDataArray *extractors; | ||||
| ExtractTaskDataType tasktype; | |||||
| eMRIterType iter_type; | eMRIterType iter_type; | ||||
| int start, end; | int start, end; | ||||
| /** Decremented each time a task is finished. */ | /** Decremented each time a task is finished. */ | ||||
| int32_t *task_counter; | int32_t *task_counter; | ||||
| void *buf; | MeshBufferCache *mbc; | ||||
| ExtractUserData *user_data; | |||||
| } ExtractTaskData; | } ExtractTaskData; | ||||
| static ExtractTaskData *extract_task_data_create_mesh_extract(const MeshRenderData *mr, | static ExtractTaskData *extract_extract_iter_task_data_create_mesh( | ||||
| const MeshRenderData *mr, | |||||
| struct MeshBatchCache *cache, | struct MeshBatchCache *cache, | ||||
| const MeshExtract *extract, | MeshExtractRunDataArray *extractors, | ||||
| void *buf, | MeshBufferCache *mbc, | ||||
| int32_t *task_counter) | int32_t *task_counter) | ||||
| { | { | ||||
| ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), __func__); | ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), __func__); | ||||
| taskdata->next = NULL; | taskdata->next = NULL; | ||||
| taskdata->prev = NULL; | taskdata->prev = NULL; | ||||
| taskdata->tasktype = EXTRACT_MESH_EXTRACT; | |||||
| taskdata->mr = mr; | taskdata->mr = mr; | ||||
| taskdata->cache = cache; | taskdata->cache = cache; | ||||
| taskdata->extract = extract; | taskdata->mbc = mbc; | ||||
| taskdata->buf = buf; | |||||
| /* #ExtractUserData is shared between the iterations as it holds counters to detect if the | /* #UserData 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 | * 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. | * 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 | * This structure makes sure that when extract_init is called, that the user data of all | ||||
| * iterations are updated. */ | * iterations are updated. */ | ||||
| taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__); | taskdata->extractors = extractors; | ||||
| taskdata->iter_type = mesh_extract_iter_type(extract); | |||||
| taskdata->task_counter = task_counter; | taskdata->task_counter = task_counter; | ||||
| extracts_flags_get(extractors, &taskdata->iter_type, NULL); | |||||
| taskdata->start = 0; | taskdata->start = 0; | ||||
| taskdata->end = INT_MAX; | taskdata->end = INT_MAX; | ||||
| return taskdata; | return taskdata; | ||||
| } | } | ||||
| static ExtractTaskData *extract_task_data_create_lines_loose(const MeshRenderData *mr, | |||||
| struct MeshBatchCache *cache) | |||||
| { | |||||
| ExtractTaskData *taskdata = MEM_callocN(sizeof(*taskdata), __func__); | |||||
| taskdata->tasktype = EXTRACT_LINES_LOOSE; | |||||
| taskdata->mr = mr; | |||||
| taskdata->cache = cache; | |||||
| return taskdata; | |||||
| } | |||||
| static void extract_task_data_free(void *data) | static void extract_task_data_free(void *data) | ||||
| { | { | ||||
| ExtractTaskData *task_data = data; | ExtractTaskData *task_data = data; | ||||
| MEM_SAFE_FREE(task_data->user_data); | MEM_SAFE_FREE(task_data->extractors); | ||||
| MEM_freeN(task_data); | MEM_freeN(task_data); | ||||
| } | } | ||||
| BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, | BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, | ||||
| const eMRIterType iter_type, | const eMRIterType iter_type, | ||||
| int start, | int start, | ||||
| int end, | int end, | ||||
| const MeshExtract *extract, | MeshExtractRunDataArray *extractors) | ||||
| void *user_data) | |||||
| { | { | ||||
| switch (mr->extract_type) { | switch (mr->extract_type) { | ||||
| case MR_EXTRACT_BMESH: | case MR_EXTRACT_BMESH: | ||||
| if (iter_type & MR_ITER_LOOPTRI) { | if (iter_type & MR_ITER_LOOPTRI) { | ||||
| extract->iter_looptri_bm(mr, | extract_iter_looptri_bm(mr, | ||||
| &(const ExtractTriBMesh_Params){ | &(const ExtractTriBMesh_Params){ | ||||
| .looptris = mr->edit_bmesh->looptris, | .looptris = mr->edit_bmesh->looptris, | ||||
| .tri_range = {start, min_ii(mr->tri_len, end)}, | .tri_range = {start, min_ii(mr->tri_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| if (iter_type & MR_ITER_POLY) { | if (iter_type & MR_ITER_POLY) { | ||||
| extract->iter_poly_bm(mr, | extract_iter_poly_bm(mr, | ||||
| &(const ExtractPolyBMesh_Params){ | &(const ExtractPolyBMesh_Params){ | ||||
| .poly_range = {start, min_ii(mr->poly_len, end)}, | .poly_range = {start, min_ii(mr->poly_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| if (iter_type & MR_ITER_LEDGE) { | if (iter_type & MR_ITER_LEDGE) { | ||||
| extract->iter_ledge_bm(mr, | extract_iter_ledge_bm(mr, | ||||
| &(const ExtractLEdgeBMesh_Params){ | &(const ExtractLEdgeBMesh_Params){ | ||||
| .ledge = mr->ledges, | .ledge = mr->ledges, | ||||
| .ledge_range = {start, min_ii(mr->edge_loose_len, end)}, | .ledge_range = {start, min_ii(mr->edge_loose_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| if (iter_type & MR_ITER_LVERT) { | if (iter_type & MR_ITER_LVERT) { | ||||
| extract->iter_lvert_bm(mr, | extract_iter_lvert_bm(mr, | ||||
| &(const ExtractLVertBMesh_Params){ | &(const ExtractLVertBMesh_Params){ | ||||
| .lvert = mr->lverts, | .lvert = mr->lverts, | ||||
| .lvert_range = {start, min_ii(mr->vert_loose_len, end)}, | .lvert_range = {start, min_ii(mr->vert_loose_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| break; | break; | ||||
| case MR_EXTRACT_MAPPED: | case MR_EXTRACT_MAPPED: | ||||
| case MR_EXTRACT_MESH: | case MR_EXTRACT_MESH: | ||||
| if (iter_type & MR_ITER_LOOPTRI) { | if (iter_type & MR_ITER_LOOPTRI) { | ||||
| extract->iter_looptri_mesh(mr, | extract_iter_looptri_mesh(mr, | ||||
| &(const ExtractTriMesh_Params){ | &(const ExtractTriMesh_Params){ | ||||
| .mlooptri = mr->mlooptri, | .mlooptri = mr->mlooptri, | ||||
| .tri_range = {start, min_ii(mr->tri_len, end)}, | .tri_range = {start, min_ii(mr->tri_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| if (iter_type & MR_ITER_POLY) { | if (iter_type & MR_ITER_POLY) { | ||||
| extract->iter_poly_mesh(mr, | extract_iter_poly_mesh(mr, | ||||
| &(const ExtractPolyMesh_Params){ | &(const ExtractPolyMesh_Params){ | ||||
| .poly_range = {start, min_ii(mr->poly_len, end)}, | .poly_range = {start, min_ii(mr->poly_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| if (iter_type & MR_ITER_LEDGE) { | if (iter_type & MR_ITER_LEDGE) { | ||||
| extract->iter_ledge_mesh(mr, | extract_iter_ledge_mesh(mr, | ||||
| &(const ExtractLEdgeMesh_Params){ | &(const ExtractLEdgeMesh_Params){ | ||||
| .ledge = mr->ledges, | .ledge = mr->ledges, | ||||
| .ledge_range = {start, min_ii(mr->edge_loose_len, end)}, | .ledge_range = {start, min_ii(mr->edge_loose_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| if (iter_type & MR_ITER_LVERT) { | if (iter_type & MR_ITER_LVERT) { | ||||
| extract->iter_lvert_mesh(mr, | extract_iter_lvert_mesh(mr, | ||||
| &(const ExtractLVertMesh_Params){ | &(const ExtractLVertMesh_Params){ | ||||
| .lvert = mr->lverts, | .lvert = mr->lverts, | ||||
| .lvert_range = {start, min_ii(mr->vert_loose_len, end)}, | .lvert_range = {start, min_ii(mr->vert_loose_len, end)}, | ||||
| }, | }, | ||||
| user_data); | extractors); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| static void extract_init(ExtractTaskData *data) | static void extract_task_init(ExtractTaskData *data) | ||||
| { | { | ||||
| if (data->tasktype == EXTRACT_MESH_EXTRACT) { | extract_init(data->mr, data->cache, data->extractors, data->mbc); | ||||
| data->user_data->user_data = data->extract->init(data->mr, data->cache, data->buf); | |||||
| } | |||||
| } | } | ||||
| static void extract_run(void *__restrict taskdata) | static void extract_task_run(void *__restrict taskdata) | ||||
| { | { | ||||
| ExtractTaskData *data = (ExtractTaskData *)taskdata; | ExtractTaskData *data = (ExtractTaskData *)taskdata; | ||||
| if (data->tasktype == EXTRACT_MESH_EXTRACT) { | mesh_extract_iter(data->mr, data->iter_type, data->start, data->end, data->extractors); | ||||
| mesh_extract_iter(data->mr, | |||||
| data->iter_type, | |||||
| data->start, | |||||
| data->end, | |||||
| data->extract, | |||||
| data->user_data->user_data); | |||||
| /* If this is the last task, we do the finish function. */ | /* If this is the last task, we do the finish function. */ | ||||
| int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1); | int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1); | ||||
| if (remainin_tasks == 0 && data->extract->finish != NULL) { | if (remainin_tasks == 0) { | ||||
| data->extract->finish(data->mr, data->cache, data->buf, data->user_data->user_data); | extract_finish(data->mr, data->cache, data->extractors); | ||||
| } | |||||
| } | |||||
| else if (data->tasktype == EXTRACT_LINES_LOOSE) { | |||||
| extract_lines_loose_subbuffer(data->mr, data->cache); | |||||
| } | } | ||||
| } | } | ||||
| static void extract_init_and_run(void *__restrict taskdata) | static void extract_task_init_and_run(void *__restrict taskdata) | ||||
| { | { | ||||
| extract_init((ExtractTaskData *)taskdata); | ExtractTaskData *data = (ExtractTaskData *)taskdata; | ||||
| extract_run(taskdata); | extract_run_and_finish_init(data->mr, data->cache, data->extractors, data->iter_type, data->mbc); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Task Node - Update Mesh Render Data | /** \name Task Node - Update Mesh Render Data | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct MeshRenderDataUpdateTaskData { | typedef struct MeshRenderDataUpdateTaskData { | ||||
| Show All 40 Lines | static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph, | ||||
| return task_node; | return task_node; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Task Node - Extract Single Threaded | /** \name Task Node - Extract Single Threaded | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct ExtractSingleThreadedTaskData { | |||||
| ListBase task_datas; | |||||
| } ExtractSingleThreadedTaskData; | |||||
| static void extract_single_threaded_task_data_free(ExtractSingleThreadedTaskData *taskdata) | static struct TaskNode *extract_single_threaded_task_node_create(struct TaskGraph *task_graph, | ||||
| { | ExtractTaskData *task_data) | ||||
| BLI_assert(taskdata); | |||||
| LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) { | |||||
| extract_task_data_free(td); | |||||
| } | |||||
| BLI_listbase_clear(&taskdata->task_datas); | |||||
| MEM_freeN(taskdata); | |||||
| } | |||||
| static void extract_single_threaded_task_node_exec(void *__restrict task_data) | |||||
| { | |||||
| ExtractSingleThreadedTaskData *extract_task_data = task_data; | |||||
| LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) { | |||||
| extract_init_and_run(td); | |||||
| } | |||||
| } | |||||
| static struct TaskNode *extract_single_threaded_task_node_create( | |||||
| struct TaskGraph *task_graph, ExtractSingleThreadedTaskData *task_data) | |||||
| { | { | ||||
| struct TaskNode *task_node = BLI_task_graph_node_create( | struct TaskNode *task_node = BLI_task_graph_node_create( | ||||
| task_graph, | task_graph, | ||||
| extract_single_threaded_task_node_exec, | extract_task_init_and_run, | ||||
| task_data, | task_data, | ||||
| (TaskGraphNodeFreeFunction)extract_single_threaded_task_data_free); | (TaskGraphNodeFreeFunction)extract_task_data_free); | ||||
| return task_node; | return task_node; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Task Node - UserData Initializer | /** \name Task Node - UserData Initializer | ||||
| * \{ */ | * \{ */ | ||||
| typedef struct UserDataInitTaskData { | typedef struct UserDataInitTaskData { | ||||
| ListBase task_datas; | ExtractTaskData *td; | ||||
| int32_t *task_counters; | int32_t task_counter; | ||||
| } UserDataInitTaskData; | } UserDataInitTaskData; | ||||
| static void user_data_init_task_data_free(UserDataInitTaskData *taskdata) | static void user_data_init_task_data_free(UserDataInitTaskData *taskdata) | ||||
| { | { | ||||
| BLI_assert(taskdata); | BLI_assert(taskdata); | ||||
| LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) { | extract_task_data_free(taskdata->td); | ||||
| extract_task_data_free(td); | |||||
| } | |||||
| BLI_listbase_clear(&taskdata->task_datas); | |||||
| MEM_SAFE_FREE(taskdata->task_counters); | |||||
| MEM_freeN(taskdata); | MEM_freeN(taskdata); | ||||
| } | } | ||||
| static void user_data_init_task_data_exec(void *__restrict task_data) | static void user_data_init_task_data_exec(void *__restrict task_data) | ||||
| { | { | ||||
| UserDataInitTaskData *extract_task_data = task_data; | UserDataInitTaskData *extract_task_data = task_data; | ||||
| LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) { | ExtractTaskData *taskdata_base = extract_task_data->td; | ||||
| extract_init(td); | extract_task_init(taskdata_base); | ||||
| } | |||||
| } | } | ||||
| static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph, | static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph, | ||||
| UserDataInitTaskData *task_data) | UserDataInitTaskData *task_data) | ||||
| { | { | ||||
| struct TaskNode *task_node = BLI_task_graph_node_create( | struct TaskNode *task_node = BLI_task_graph_node_create( | ||||
| task_graph, | task_graph, | ||||
| user_data_init_task_data_exec, | user_data_init_task_data_exec, | ||||
Done Inline ActionsUpdate or remove this incompatible disabled code. mano-wii: Update or remove this incompatible disabled code. | |||||
Done Inline ActionsI removed it for now. jbakker: I removed it for now.
We should strive to minimize loops during initialization. Although not… | |||||
| task_data, | task_data, | ||||
| (TaskGraphNodeFreeFunction)user_data_init_task_data_free); | (TaskGraphNodeFreeFunction)user_data_init_task_data_free); | ||||
| return task_node; | return task_node; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* ---------------------------------------------------------------------- */ | |||||
| /** \name Override extractors | |||||
| * Extractors can be overridden. When overridden a specialized version is used. The next functions | |||||
| * would check for any needed overrides and usage of the specialized version. | |||||
| * \{ */ | |||||
| static const MeshExtract *mesh_extract_override_hq_normals(const MeshExtract *extractor) | |||||
| { | |||||
| if (extractor == &extract_pos_nor) { | |||||
| return &extract_pos_nor_hq; | |||||
| } | |||||
| if (extractor == &extract_lnor) { | |||||
| return &extract_lnor_hq; | |||||
| } | |||||
| if (extractor == &extract_tan) { | |||||
| return &extract_tan_hq; | |||||
| } | |||||
| if (extractor == &extract_fdots_nor) { | |||||
| return &extract_fdots_nor_hq; | |||||
| } | |||||
| return extractor; | |||||
| } | |||||
| static const MeshExtract *mesh_extract_override_loose_lines(const MeshExtract *extractor) | |||||
| { | |||||
| if (extractor == &extract_lines) { | |||||
| return &extract_lines_with_lines_loose; | |||||
| } | |||||
| return extractor; | |||||
| } | |||||
| static const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor, | |||||
| const bool do_hq_normals, | |||||
| const bool do_lines_loose_subbuffer) | |||||
| { | |||||
| if (do_hq_normals) { | |||||
| extractor = mesh_extract_override_hq_normals(extractor); | |||||
| } | |||||
| if (do_lines_loose_subbuffer) { | |||||
| extractor = mesh_extract_override_loose_lines(extractor); | |||||
| } | |||||
| return extractor; | |||||
| } | |||||
| /** \} */ | |||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** \name Extract Loop | /** \name Extract Loop | ||||
| * \{ */ | * \{ */ | ||||
| static void extract_range_task_create(struct TaskGraph *task_graph, | static void extract_range_task_create(struct TaskGraph *task_graph, | ||||
| struct TaskNode *task_node_user_data_init, | struct TaskNode *task_node_user_data_init, | ||||
| ExtractTaskData *taskdata, | ExtractTaskData *taskdata, | ||||
| const eMRIterType type, | const eMRIterType type, | ||||
| int start, | int start, | ||||
| int length) | int length) | ||||
| { | { | ||||
| taskdata = MEM_dupallocN(taskdata); | taskdata = MEM_dupallocN(taskdata); | ||||
| atomic_add_and_fetch_int32(taskdata->task_counter, 1); | atomic_add_and_fetch_int32(taskdata->task_counter, 1); | ||||
| taskdata->iter_type = type; | taskdata->iter_type = type; | ||||
| taskdata->start = start; | taskdata->start = start; | ||||
| taskdata->end = start + length; | taskdata->end = start + length; | ||||
| struct TaskNode *task_node = BLI_task_graph_node_create( | struct TaskNode *task_node = BLI_task_graph_node_create( | ||||
| task_graph, extract_run, taskdata, MEM_freeN); | task_graph, extract_task_run, taskdata, MEM_freeN); | ||||
| BLI_task_graph_edge_create(task_node_user_data_init, task_node); | BLI_task_graph_edge_create(task_node_user_data_init, task_node); | ||||
| } | } | ||||
| static void extract_task_create(struct TaskGraph *task_graph, | static int extract_range_task_num_elements_get(const MeshRenderData *mr, | ||||
| struct TaskNode *task_node_mesh_render_data, | const eMRIterType iter_type) | ||||
| struct TaskNode *task_node_user_data_init, | |||||
| ListBase *single_threaded_task_datas, | |||||
| ListBase *user_data_init_task_datas, | |||||
| const Scene *scene, | |||||
| const MeshRenderData *mr, | |||||
| MeshBatchCache *cache, | |||||
| const MeshExtract *extract, | |||||
| void *buf, | |||||
| int32_t *task_counter) | |||||
| { | { | ||||
| BLI_assert(scene != NULL); | /* Divide task into sensible chunks. */ | ||||
| const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 || | int iter_len = 0; | ||||
| GPU_use_hq_normals_workaround(); | if (iter_type & MR_ITER_LOOPTRI) { | ||||
| if (do_hq_normals) { | iter_len += mr->tri_len; | ||||
| if (extract == &extract_lnor) { | |||||
| extract = &extract_lnor_hq; | |||||
| } | } | ||||
| else if (extract == &extract_pos_nor) { | if (iter_type & MR_ITER_POLY) { | ||||
| extract = &extract_pos_nor_hq; | iter_len += mr->poly_len; | ||||
| } | } | ||||
| else if (extract == &extract_tan) { | if (iter_type & MR_ITER_LEDGE) { | ||||
| extract = &extract_tan_hq; | iter_len += mr->edge_loose_len; | ||||
| } | } | ||||
| else if (extract == &extract_fdots_nor) { | if (iter_type & MR_ITER_LVERT) { | ||||
| extract = &extract_fdots_nor_hq; | iter_len += mr->vert_loose_len; | ||||
| } | } | ||||
| return iter_len; | |||||
| } | } | ||||
| /* Divide extraction of the VBO/IBO into sensible chunks of works. */ | static int extract_range_task_chunk_size_get(const MeshRenderData *mr, | ||||
| ExtractTaskData *taskdata = extract_task_data_create_mesh_extract( | const eMRIterType iter_type, | ||||
| mr, cache, extract, buf, task_counter); | const int num_threads) | ||||
| { | |||||
| /* Divide task into sensible chunks. */ | |||||
| const int num_elements = extract_range_task_num_elements_get(mr, iter_type); | |||||
| int range_len = (num_elements + num_threads) / num_threads; | |||||
| CLAMP_MIN(range_len, CHUNK_SIZE); | |||||
| return range_len; | |||||
| } | |||||
| /* Simple heuristic. */ | static void extract_task_in_ranges_create(struct TaskGraph *task_graph, | ||||
| const int chunk_size = 8192; | struct TaskNode *task_node_user_data_init, | ||||
| const bool use_thread = (mr->loop_len + mr->loop_loose_len) > chunk_size; | ExtractTaskData *taskdata_base, | ||||
| if (use_thread && extract->use_threading) { | const int num_threads) | ||||
| { | |||||
| const MeshRenderData *mr = taskdata_base->mr; | |||||
| const int range_len = extract_range_task_chunk_size_get( | |||||
| mr, taskdata_base->iter_type, num_threads); | |||||
| /* Divide task into sensible chunks. */ | if (taskdata_base->iter_type & MR_ITER_LOOPTRI) { | ||||
| if (taskdata->iter_type & MR_ITER_LOOPTRI) { | for (int i = 0; i < mr->tri_len; i += range_len) { | ||||
| for (int i = 0; i < mr->tri_len; i += chunk_size) { | |||||
| extract_range_task_create( | extract_range_task_create( | ||||
| task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size); | task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LOOPTRI, i, range_len); | ||||
| } | } | ||||
| } | } | ||||
| if (taskdata->iter_type & MR_ITER_POLY) { | if (taskdata_base->iter_type & MR_ITER_POLY) { | ||||
| for (int i = 0; i < mr->poly_len; i += chunk_size) { | for (int i = 0; i < mr->poly_len; i += range_len) { | ||||
| extract_range_task_create( | extract_range_task_create( | ||||
| task_graph, task_node_user_data_init, taskdata, MR_ITER_POLY, i, chunk_size); | task_graph, task_node_user_data_init, taskdata_base, MR_ITER_POLY, i, range_len); | ||||
| } | } | ||||
| } | } | ||||
| if (taskdata->iter_type & MR_ITER_LEDGE) { | if (taskdata_base->iter_type & MR_ITER_LEDGE) { | ||||
| for (int i = 0; i < mr->edge_loose_len; i += chunk_size) { | for (int i = 0; i < mr->edge_loose_len; i += range_len) { | ||||
| extract_range_task_create( | extract_range_task_create( | ||||
| task_graph, task_node_user_data_init, taskdata, MR_ITER_LEDGE, i, chunk_size); | task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LEDGE, i, range_len); | ||||
| } | } | ||||
| } | } | ||||
| if (taskdata->iter_type & MR_ITER_LVERT) { | if (taskdata_base->iter_type & MR_ITER_LVERT) { | ||||
| for (int i = 0; i < mr->vert_loose_len; i += chunk_size) { | for (int i = 0; i < mr->vert_loose_len; i += range_len) { | ||||
| extract_range_task_create( | extract_range_task_create( | ||||
| task_graph, task_node_user_data_init, taskdata, MR_ITER_LVERT, i, chunk_size); | task_graph, task_node_user_data_init, taskdata_base, MR_ITER_LVERT, i, range_len); | ||||
| } | } | ||||
| } | } | ||||
| BLI_addtail(user_data_init_task_datas, taskdata); | |||||
| } | |||||
| else if (use_thread) { | |||||
| /* One task for the whole VBO. */ | |||||
| (*task_counter)++; | |||||
| struct TaskNode *one_task = BLI_task_graph_node_create( | |||||
| task_graph, extract_init_and_run, taskdata, extract_task_data_free); | |||||
| BLI_task_graph_edge_create(task_node_mesh_render_data, one_task); | |||||
| } | |||||
| else { | |||||
| /* Single threaded extraction. */ | |||||
| (*task_counter)++; | |||||
| BLI_addtail(single_threaded_task_datas, taskdata); | |||||
| } | |||||
| } | } | ||||
| void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, | void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, | ||||
| MeshBatchCache *cache, | MeshBatchCache *cache, | ||||
| MeshBufferCache mbc, | MeshBufferCache *mbc, | ||||
| MeshBufferExtractionCache *extraction_cache, | MeshBufferExtractionCache *extraction_cache, | ||||
| Mesh *me, | Mesh *me, | ||||
| const bool is_editmode, | const bool is_editmode, | ||||
| const bool is_paint_mode, | const bool is_paint_mode, | ||||
| const bool is_mode_active, | const bool is_mode_active, | ||||
| const float obmat[4][4], | const float obmat[4][4], | ||||
| const bool do_final, | const bool do_final, | ||||
| const bool do_uvedit, | const bool do_uvedit, | ||||
| const bool use_subsurf_fdots, | const bool use_subsurf_fdots, | ||||
| const DRW_MeshCDMask *cd_layer_used, | const DRW_MeshCDMask *cd_layer_used, | ||||
| const Scene *scene, | const Scene *scene, | ||||
| const ToolSettings *ts, | const ToolSettings *ts, | ||||
| const bool use_hide) | const bool use_hide) | ||||
| { | { | ||||
| /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph. | /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph. | ||||
| * This sub-graph starts with an extract_render_data_node. This fills/converts the required data | * This sub-graph starts with an extract_render_data_node. This fills/converts the required | ||||
| * from Mesh. | * data from Mesh. | ||||
| * | * | ||||
| * Small extractions and extractions that can't be multi-threaded are grouped in a single | * Small extractions and extractions that can't be multi-threaded are grouped in a single | ||||
| * `extract_single_threaded_task_node`. | * `extract_single_threaded_task_node`. | ||||
| * | * | ||||
| * Other extractions will create a node for each loop exceeding 8192 items. these nodes are | * 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 | * 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. | * 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. | * counters are used to check if the finalize of a task has to be called. | ||||
| Show All 11 Lines | void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, | ||||
| * v | | +----------------------+ | * v | | +----------------------+ | ||||
| * +------------------+ | | +----------------------+ | * +------------------+ | | +----------------------+ | ||||
| * | single_threaded | | | --> | extract_task2_loop_2 | | * | single_threaded | | | --> | extract_task2_loop_2 | | ||||
| * +------------------+ +----------------------+ +----------------------+ | * +------------------+ +----------------------+ +----------------------+ | ||||
| * | +----------------------+ | * | +----------------------+ | ||||
| * +-----> | extract_task2_loop_3 | | * +-----> | extract_task2_loop_3 | | ||||
| * +----------------------+ | * +----------------------+ | ||||
| */ | */ | ||||
| eMRIterType iter_flag = 0; | const bool do_lines_loose_subbuffer = mbc->ibo.lines_loose != NULL; | ||||
| eMRDataType data_flag = 0; | const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 || | ||||
| GPU_use_hq_normals_workaround(); | |||||
| const bool do_lines_loose_subbuffer = mbc.ibo.lines_loose != NULL; | /* Create an array containing all the extractors that needs to be executed. */ | ||||
| bool do_extract = false; | MeshExtractRunDataArray extractors; | ||||
| mesh_extract_run_data_array_init(&extractors); | |||||
| #define TEST_ASSIGN(type, type_lowercase, name) \ | #define EXTRACT_ADD_REQUESTED(type, type_lowercase, name) \ | ||||
| do { \ | do { \ | ||||
| if (DRW_TEST_ASSIGN_##type(mbc.type_lowercase.name)) { \ | if (DRW_##type_lowercase##_requested(mbc->type_lowercase.name)) { \ | ||||
| iter_flag |= mesh_extract_iter_type(&extract_##name); \ | const MeshExtract *extractor = mesh_extract_override_get( \ | ||||
| data_flag |= extract_##name.data_flag; \ | &extract_##name, do_hq_normals, do_lines_loose_subbuffer); \ | ||||
| do_extract = true; \ | mesh_extract_run_data_array_add(&extractors, extractor); \ | ||||
| } \ | } \ | ||||
| } while (0) | } while (0) | ||||
| TEST_ASSIGN(VBO, vbo, pos_nor); | EXTRACT_ADD_REQUESTED(VBO, vbo, pos_nor); | ||||
| TEST_ASSIGN(VBO, vbo, lnor); | EXTRACT_ADD_REQUESTED(VBO, vbo, lnor); | ||||
| TEST_ASSIGN(VBO, vbo, uv); | EXTRACT_ADD_REQUESTED(VBO, vbo, uv); | ||||
| TEST_ASSIGN(VBO, vbo, tan); | EXTRACT_ADD_REQUESTED(VBO, vbo, tan); | ||||
| TEST_ASSIGN(VBO, vbo, vcol); | EXTRACT_ADD_REQUESTED(VBO, vbo, vcol); | ||||
| TEST_ASSIGN(VBO, vbo, sculpt_data); | EXTRACT_ADD_REQUESTED(VBO, vbo, sculpt_data); | ||||
| TEST_ASSIGN(VBO, vbo, orco); | EXTRACT_ADD_REQUESTED(VBO, vbo, orco); | ||||
| TEST_ASSIGN(VBO, vbo, edge_fac); | EXTRACT_ADD_REQUESTED(VBO, vbo, edge_fac); | ||||
| TEST_ASSIGN(VBO, vbo, weights); | EXTRACT_ADD_REQUESTED(VBO, vbo, weights); | ||||
| TEST_ASSIGN(VBO, vbo, edit_data); | EXTRACT_ADD_REQUESTED(VBO, vbo, edit_data); | ||||
| TEST_ASSIGN(VBO, vbo, edituv_data); | EXTRACT_ADD_REQUESTED(VBO, vbo, edituv_data); | ||||
| TEST_ASSIGN(VBO, vbo, edituv_stretch_area); | EXTRACT_ADD_REQUESTED(VBO, vbo, edituv_stretch_area); | ||||
| TEST_ASSIGN(VBO, vbo, edituv_stretch_angle); | EXTRACT_ADD_REQUESTED(VBO, vbo, edituv_stretch_angle); | ||||
| TEST_ASSIGN(VBO, vbo, mesh_analysis); | EXTRACT_ADD_REQUESTED(VBO, vbo, mesh_analysis); | ||||
| TEST_ASSIGN(VBO, vbo, fdots_pos); | EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_pos); | ||||
| TEST_ASSIGN(VBO, vbo, fdots_nor); | EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_nor); | ||||
| TEST_ASSIGN(VBO, vbo, fdots_uv); | EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_uv); | ||||
| TEST_ASSIGN(VBO, vbo, fdots_edituv_data); | EXTRACT_ADD_REQUESTED(VBO, vbo, fdots_edituv_data); | ||||
| TEST_ASSIGN(VBO, vbo, poly_idx); | EXTRACT_ADD_REQUESTED(VBO, vbo, poly_idx); | ||||
| TEST_ASSIGN(VBO, vbo, edge_idx); | EXTRACT_ADD_REQUESTED(VBO, vbo, edge_idx); | ||||
| TEST_ASSIGN(VBO, vbo, vert_idx); | EXTRACT_ADD_REQUESTED(VBO, vbo, vert_idx); | ||||
| TEST_ASSIGN(VBO, vbo, fdot_idx); | EXTRACT_ADD_REQUESTED(VBO, vbo, fdot_idx); | ||||
| TEST_ASSIGN(VBO, vbo, skin_roots); | EXTRACT_ADD_REQUESTED(VBO, vbo, skin_roots); | ||||
| TEST_ASSIGN(IBO, ibo, tris); | EXTRACT_ADD_REQUESTED(IBO, ibo, tris); | ||||
| TEST_ASSIGN(IBO, ibo, lines); | EXTRACT_ADD_REQUESTED(IBO, ibo, lines); | ||||
| TEST_ASSIGN(IBO, ibo, points); | EXTRACT_ADD_REQUESTED(IBO, ibo, points); | ||||
| TEST_ASSIGN(IBO, ibo, fdots); | EXTRACT_ADD_REQUESTED(IBO, ibo, fdots); | ||||
| TEST_ASSIGN(IBO, ibo, lines_paint_mask); | EXTRACT_ADD_REQUESTED(IBO, ibo, lines_paint_mask); | ||||
| TEST_ASSIGN(IBO, ibo, lines_adjacency); | EXTRACT_ADD_REQUESTED(IBO, ibo, lines_adjacency); | ||||
| TEST_ASSIGN(IBO, ibo, edituv_tris); | EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_tris); | ||||
| TEST_ASSIGN(IBO, ibo, edituv_lines); | EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_lines); | ||||
| TEST_ASSIGN(IBO, ibo, edituv_points); | EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_points); | ||||
| TEST_ASSIGN(IBO, ibo, edituv_fdots); | EXTRACT_ADD_REQUESTED(IBO, ibo, edituv_fdots); | ||||
| if (!do_extract) { | #undef EXTRACT_ADD_REQUESTED | ||||
| return; | |||||
| } | |||||
| if (do_lines_loose_subbuffer) { | if (extractors.len == 0) { | ||||
| iter_flag |= MR_ITER_LEDGE; | return; | ||||
| } | } | ||||
| #undef TEST_ASSIGN | eMRIterType iter_type; | ||||
| eMRDataType data_flag; | |||||
| #ifdef DEBUG_TIME | extracts_flags_get(&extractors, &iter_type, &data_flag); | ||||
| double rdata_start = PIL_check_seconds_timer(); | |||||
| #endif | |||||
| MeshRenderData *mr = mesh_render_data_create(me, | MeshRenderData *mr = mesh_render_data_create(me, | ||||
| extraction_cache, | extraction_cache, | ||||
| is_editmode, | is_editmode, | ||||
| is_paint_mode, | is_paint_mode, | ||||
| is_mode_active, | is_mode_active, | ||||
| obmat, | obmat, | ||||
| do_final, | do_final, | ||||
| do_uvedit, | do_uvedit, | ||||
| cd_layer_used, | cd_layer_used, | ||||
| ts, | ts, | ||||
| iter_flag); | iter_type); | ||||
| mr->use_hide = use_hide; | mr->use_hide = use_hide; | ||||
| mr->use_subsurf_fdots = use_subsurf_fdots; | mr->use_subsurf_fdots = use_subsurf_fdots; | ||||
| mr->use_final_mesh = do_final; | mr->use_final_mesh = do_final; | ||||
| #ifdef DEBUG_TIME | #ifdef DEBUG_TIME | ||||
| double rdata_end = PIL_check_seconds_timer(); | rdata_end = PIL_check_seconds_timer(); | ||||
| #endif | #endif | ||||
| size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t); | |||||
| int32_t *task_counters = MEM_callocN(counters_size, __func__); | |||||
| int counter_used = 0; | |||||
| struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create( | struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create( | ||||
| task_graph, mr, iter_flag, data_flag); | task_graph, mr, iter_type, data_flag); | ||||
| ExtractSingleThreadedTaskData *single_threaded_task_data = MEM_callocN( | |||||
| sizeof(ExtractSingleThreadedTaskData), __func__); | |||||
| UserDataInitTaskData *user_data_init_task_data = MEM_callocN(sizeof(UserDataInitTaskData), | |||||
| __func__); | |||||
| user_data_init_task_data->task_counters = task_counters; | |||||
| struct TaskNode *task_node_user_data_init = user_data_init_task_node_create( | |||||
| task_graph, user_data_init_task_data); | |||||
| #define EXTRACT(buf, name) \ | /* Simple heuristic. */ | ||||
| if (mbc.buf.name) { \ | const bool use_thread = (mr->loop_len + mr->loop_loose_len) > CHUNK_SIZE; | ||||
| extract_task_create(task_graph, \ | |||||
| task_node_mesh_render_data, \ | |||||
| task_node_user_data_init, \ | |||||
| &single_threaded_task_data->task_datas, \ | |||||
| &user_data_init_task_data->task_datas, \ | |||||
| scene, \ | |||||
| mr, \ | |||||
| cache, \ | |||||
| &extract_##name, \ | |||||
| mbc.buf.name, \ | |||||
| &task_counters[counter_used++]); \ | |||||
| } \ | |||||
| ((void)0) | |||||
| EXTRACT(vbo, pos_nor); | if (use_thread) { | ||||
| EXTRACT(vbo, lnor); | uint threads_to_use = 0; | ||||
| EXTRACT(vbo, uv); | |||||
| EXTRACT(vbo, tan); | /* First run the requested extractors that do not support asynchronous ranges. */ | ||||
| EXTRACT(vbo, vcol); | for (int i = 0; i < extractors.len; i++) { | ||||
| EXTRACT(vbo, sculpt_data); | const MeshExtract *extractor = extractors.items[i].extractor; | ||||
| EXTRACT(vbo, orco); | if (!extractor->use_threading) { | ||||
| EXTRACT(vbo, edge_fac); | MeshExtractRunDataArray *single_threaded_extractors = MEM_callocN( | ||||
| EXTRACT(vbo, weights); | sizeof(MeshExtractRunDataArray), | ||||
| EXTRACT(vbo, edit_data); | "mesh_buffer_cache_create_requested.single_threaded_extractors"); | ||||
| EXTRACT(vbo, edituv_data); | mesh_extract_run_data_array_add(single_threaded_extractors, extractor); | ||||
| EXTRACT(vbo, edituv_stretch_area); | ExtractTaskData *taskdata = extract_extract_iter_task_data_create_mesh( | ||||
| EXTRACT(vbo, edituv_stretch_angle); | mr, cache, single_threaded_extractors, mbc, NULL); | ||||
| EXTRACT(vbo, mesh_analysis); | struct TaskNode *task_node = extract_single_threaded_task_node_create(task_graph, | ||||
| EXTRACT(vbo, fdots_pos); | taskdata); | ||||
| EXTRACT(vbo, fdots_nor); | BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); | ||||
| EXTRACT(vbo, fdots_uv); | |||||
| EXTRACT(vbo, fdots_edituv_data); | |||||
| EXTRACT(vbo, poly_idx); | |||||
| EXTRACT(vbo, edge_idx); | |||||
| EXTRACT(vbo, vert_idx); | |||||
| EXTRACT(vbo, fdot_idx); | |||||
| EXTRACT(vbo, skin_roots); | |||||
| EXTRACT(ibo, tris); | |||||
| if (mbc.ibo.lines) { | |||||
| /* When `lines` and `lines_loose` are requested, schedule lines extraction that also creates | |||||
| * the `lines_loose` sub-buffer. */ | |||||
| const MeshExtract *lines_extractor = do_lines_loose_subbuffer ? | |||||
| &extract_lines_with_lines_loose : | |||||
| &extract_lines; | |||||
| extract_task_create(task_graph, | |||||
| task_node_mesh_render_data, | |||||
| task_node_user_data_init, | |||||
| &single_threaded_task_data->task_datas, | |||||
| &user_data_init_task_data->task_datas, | |||||
| scene, | |||||
| mr, | |||||
| cache, | |||||
| lines_extractor, | |||||
| mbc.ibo.lines, | |||||
| &task_counters[counter_used++]); | |||||
| } | |||||
| else { | |||||
| if (do_lines_loose_subbuffer) { | |||||
| ExtractTaskData *taskdata = extract_task_data_create_lines_loose(mr, cache); | |||||
| BLI_addtail(&single_threaded_task_data->task_datas, taskdata); | |||||
| } | } | ||||
| threads_to_use++; | |||||
| } | } | ||||
| EXTRACT(ibo, points); | |||||
| EXTRACT(ibo, fdots); | |||||
| EXTRACT(ibo, lines_paint_mask); | |||||
| EXTRACT(ibo, lines_adjacency); | |||||
| EXTRACT(ibo, edituv_tris); | |||||
| EXTRACT(ibo, edituv_lines); | |||||
| EXTRACT(ibo, edituv_points); | |||||
| EXTRACT(ibo, edituv_fdots); | |||||
| /* Only create the edge when there is user data that needs to be initialized. | /* Distribute the remaining extractors into ranges per core. */ | ||||
| * The task is still part of the graph so the task_data will be freed when the graph is freed. | MeshExtractRunDataArray *multi_threaded_extractors = MEM_callocN( | ||||
| sizeof(MeshExtractRunDataArray), | |||||
| "mesh_buffer_cache_create_requested.multi_threaded_extractors"); | |||||
| mesh_extract_run_data_array_filter_threading(&extractors, multi_threaded_extractors); | |||||
| if (multi_threaded_extractors->len) { | |||||
| /* | |||||
| * Determine the number of thread to use for multithreading. | |||||
| * Thread can be used for single threaded tasks. These typically take longer to execute so | |||||
| * fill the rest of the threads for range operations. | |||||
| */ | */ | ||||
| if (!BLI_listbase_is_empty(&user_data_init_task_data->task_datas)) { | int num_threads = BLI_task_scheduler_num_threads(); | ||||
| BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init); | if (threads_to_use < num_threads) { | ||||
| num_threads -= threads_to_use; | |||||
| } | } | ||||
| if (!BLI_listbase_is_empty(&single_threaded_task_data->task_datas)) { | UserDataInitTaskData *user_data_init_task_data = MEM_callocN( | ||||
| struct TaskNode *task_node = extract_single_threaded_task_node_create( | sizeof(UserDataInitTaskData), | ||||
| task_graph, single_threaded_task_data); | "mesh_buffer_cache_create_requested.user_data_init_task_data"); | ||||
| BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); | struct TaskNode *task_node_user_data_init = user_data_init_task_node_create( | ||||
| task_graph, user_data_init_task_data); | |||||
| user_data_init_task_data->td = extract_extract_iter_task_data_create_mesh( | |||||
| mr, cache, multi_threaded_extractors, mbc, &user_data_init_task_data->task_counter); | |||||
| extract_task_in_ranges_create( | |||||
| task_graph, task_node_user_data_init, user_data_init_task_data->td, num_threads); | |||||
| BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init); | |||||
| } | } | ||||
| else { | else { | ||||
| extract_single_threaded_task_data_free(single_threaded_task_data); | /* No tasks created freeing extractors list. */ | ||||
| MEM_freeN(multi_threaded_extractors); | |||||
| } | |||||
| } | |||||
| else { | |||||
| /* Run all requests on the same thread. */ | |||||
| MeshExtractRunDataArray *extractors_copy = MEM_mallocN( | |||||
| sizeof(MeshExtractRunDataArray), "mesh_buffer_cache_create_requested.extractors_copy"); | |||||
| memcpy(extractors_copy, &extractors, sizeof(MeshExtractRunDataArray)); | |||||
| ExtractTaskData *taskdata = extract_extract_iter_task_data_create_mesh( | |||||
| mr, cache, extractors_copy, mbc, NULL); | |||||
| struct TaskNode *task_node = extract_single_threaded_task_node_create(task_graph, taskdata); | |||||
| BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); | |||||
| } | } | ||||
| /* Trigger the sub-graph for this mesh. */ | /* Trigger the sub-graph for this mesh. */ | ||||
| BLI_task_graph_node_push_work(task_node_mesh_render_data); | BLI_task_graph_node_push_work(task_node_mesh_render_data); | ||||
| #undef EXTRACT | |||||
| #ifdef DEBUG_TIME | #ifdef DEBUG_TIME | ||||
| BLI_task_graph_work_and_wait(task_graph); | BLI_task_graph_work_and_wait(task_graph); | ||||
| double end = PIL_check_seconds_timer(); | double end = PIL_check_seconds_timer(); | ||||
| static double avg = 0; | static double avg = 0; | ||||
| static double avg_fps = 0; | static double avg_fps = 0; | ||||
| static double avg_rdata = 0; | static double avg_rdata = 0; | ||||
| static double end_prev = 0; | static double end_prev = 0; | ||||
| Show All 17 Lines | |||||
Here it looks like you can use the macro POINTER_OFFSET