diff options
Diffstat (limited to 'source/blender/draw/intern/mesh_extractors/extract_mesh.cc')
-rw-r--r-- | source/blender/draw/intern/mesh_extractors/extract_mesh.cc | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh.cc new file mode 100644 index 00000000000..ec7d3a933b4 --- /dev/null +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.cc @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2021 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup draw + * + * \brief Extraction of Mesh data into VBO to feed to GPU. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" + +#include "ED_uvedit.h" + +#include "extract_mesh.hh" + +#include "draw_cache_impl.h" + +void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferList *mbuflist) +{ + /* NOTE: POINTER_OFFSET on windows platforms casts internally to `void *`, but on GCC/CLANG to + * `MeshBufferList *`. What shows a different usage versus intent. */ + void **buffer_ptr = (void **)POINTER_OFFSET(mbuflist, extractor->mesh_buffer_offset); + void *buffer = *buffer_ptr; + BLI_assert(buffer); + return buffer; +} + +eMRIterType mesh_extract_iter_type(const MeshExtract *ext) +{ + eMRIterType type = (eMRIterType)0; + SET_FLAG_FROM_TEST(type, (ext->iter_looptri_bm || ext->iter_looptri_mesh), MR_ITER_LOOPTRI); + SET_FLAG_FROM_TEST(type, (ext->iter_poly_bm || ext->iter_poly_mesh), MR_ITER_POLY); + SET_FLAG_FROM_TEST(type, (ext->iter_ledge_bm || ext->iter_ledge_mesh), MR_ITER_LEDGE); + SET_FLAG_FROM_TEST(type, (ext->iter_lvert_bm || ext->iter_lvert_mesh), MR_ITER_LVERT); + return type; +} + +/* ---------------------------------------------------------------------- */ +/** \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_single_material(const MeshExtract *extractor) +{ + if (extractor == &extract_tris) { + return &extract_tris_single_mat; + } + return extractor; +} + +const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor, + const bool do_hq_normals, + const bool do_single_mat) +{ + if (do_hq_normals) { + extractor = mesh_extract_override_hq_normals(extractor); + } + + if (do_single_mat) { + extractor = mesh_extract_override_single_material(extractor); + } + + return extractor; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Extract Edit Flag Utils + * \{ */ + +void mesh_render_data_face_flag(const MeshRenderData *mr, + const BMFace *efa, + const int cd_ofs, + EditLoopData *eattr) +{ + if (efa == mr->efa_act) { + eattr->v_flag |= VFLAG_FACE_ACTIVE; + } + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + eattr->v_flag |= VFLAG_FACE_SELECTED; + } + + if (efa == mr->efa_act_uv) { + eattr->v_flag |= VFLAG_FACE_UV_ACTIVE; + } + if ((cd_ofs != -1) && uvedit_face_select_test_ex(mr->toolsettings, (BMFace *)efa, cd_ofs)) { + eattr->v_flag |= VFLAG_FACE_UV_SELECT; + } + +#ifdef WITH_FREESTYLE + if (mr->freestyle_face_ofs != -1) { + const FreestyleFace *ffa = (const FreestyleFace *)BM_ELEM_CD_GET_VOID_P( + efa, mr->freestyle_face_ofs); + if (ffa->flag & FREESTYLE_FACE_MARK) { + eattr->v_flag |= VFLAG_FACE_FREESTYLE; + } + } +#endif +} + +void mesh_render_data_loop_flag(const MeshRenderData *mr, + BMLoop *l, + const int cd_ofs, + EditLoopData *eattr) +{ + if (cd_ofs == -1) { + return; + } + MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_ofs); + if (luv != nullptr && (luv->flag & MLOOPUV_PINNED)) { + eattr->v_flag |= VFLAG_VERT_UV_PINNED; + } + if (uvedit_uv_select_test_ex(mr->toolsettings, l, cd_ofs)) { + eattr->v_flag |= VFLAG_VERT_UV_SELECT; + } +} + +void mesh_render_data_loop_edge_flag(const MeshRenderData *mr, + BMLoop *l, + const int cd_ofs, + EditLoopData *eattr) +{ + if (cd_ofs == -1) { + return; + } + if (uvedit_edge_select_test_ex(mr->toolsettings, l, cd_ofs)) { + eattr->v_flag |= VFLAG_EDGE_UV_SELECT; + eattr->v_flag |= VFLAG_VERT_UV_SELECT; + } +} + +/** \} */ |