diff options
Diffstat (limited to 'source/blender/blenkernel/intern/editmesh_cache.cc')
-rw-r--r-- | source/blender/blenkernel/intern/editmesh_cache.cc | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/editmesh_cache.cc b/source/blender/blenkernel/intern/editmesh_cache.cc new file mode 100644 index 00000000000..438d287fb28 --- /dev/null +++ b/source/blender/blenkernel/intern/editmesh_cache.cc @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bke + * + * Manage edit mesh cache: #EditMeshData + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_bounds.hh" +#include "BLI_math_vector.h" +#include "BLI_span.hh" + +#include "DNA_mesh_types.h" + +#include "BKE_editmesh.h" +#include "BKE_editmesh_cache.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/** \name Ensure Data (derived from coords) + * \{ */ + +void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, EditMeshData *emd) +{ + if (!(emd->vertexCos && (emd->polyNos == nullptr))) { + return; + } + + BMesh *bm = em->bm; + BMFace *efa; + BMIter fiter; + int i; + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + float(*polyNos)[3] = static_cast<float(*)[3]>( + MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__)); + + const float(*vertexCos)[3] = emd->vertexCos; + + BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { + BM_elem_index_set(efa, i); /* set_inline */ + BM_face_calc_normal_vcos(bm, efa, polyNos[i], vertexCos); + } + bm->elem_index_dirty &= ~BM_FACE; + + emd->polyNos = (const float(*)[3])polyNos; +} + +void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh *em, EditMeshData *emd) +{ + if (!(emd->vertexCos && (emd->vertexNos == nullptr))) { + return; + } + + BMesh *bm = em->bm; + const float(*vertexCos)[3], (*polyNos)[3]; + float(*vertexNos)[3]; + + /* Calculate vertex normals from poly normals. */ + BKE_editmesh_cache_ensure_poly_normals(em, emd); + + BM_mesh_elem_index_ensure(bm, BM_FACE); + + polyNos = emd->polyNos; + vertexCos = emd->vertexCos; + vertexNos = static_cast<float(*)[3]>(MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__)); + + BM_verts_calc_normal_vcos(bm, polyNos, vertexCos, vertexNos); + + emd->vertexNos = (const float(*)[3])vertexNos; +} + +void BKE_editmesh_cache_ensure_poly_centers(BMEditMesh *em, EditMeshData *emd) +{ + if (emd->polyCos != nullptr) { + return; + } + BMesh *bm = em->bm; + + BMFace *efa; + BMIter fiter; + int i; + + float(*polyCos)[3] = static_cast<float(*)[3]>( + MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__)); + + if (emd->vertexCos) { + const float(*vertexCos)[3]; + vertexCos = emd->vertexCos; + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { + BM_face_calc_center_median_vcos(bm, efa, polyCos[i], vertexCos); + } + } + else { + BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { + BM_face_calc_center_median(efa, polyCos[i]); + } + } + + emd->polyCos = (const float(*)[3])polyCos; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Calculate Min/Max + * \{ */ + +bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em, + struct EditMeshData *emd, + float min[3], + float max[3]) +{ + using namespace blender; + BMesh *bm = em->bm; + + if (bm->totvert) { + if (emd->vertexCos) { + Span<float3> vert_coords(reinterpret_cast<const float3 *>(emd->vertexCos), bm->totvert); + std::optional<bounds::MinMaxResult<float3>> bounds = bounds::min_max(vert_coords); + BLI_assert(bounds.has_value()); + copy_v3_v3(min, math::min(bounds->min, float3(min))); + copy_v3_v3(max, math::max(bounds->max, float3(max))); + } + else { + BMVert *eve; + BMIter iter; + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + minmax_v3v3_v3(min, max, eve->co); + } + } + return true; + } + + zero_v3(min); + zero_v3(max); + return false; +} + +/** \} */ |