Cleanup: Store more mesh runtime data with unique_ptr

Convert shrinkwrap data arrays to use C++ arrays and BitVector,
use references in "EditMeshData" code, and store both structs
with `std::unique_ptr` instead of a raw allocation.
This commit is contained in:
Hans Goudey
2023-12-04 15:22:00 -05:00
parent 0318d49995
commit 695e626d3f
15 changed files with 89 additions and 122 deletions
@@ -29,10 +29,10 @@ struct EditMeshData {
} // namespace blender::bke } // namespace blender::bke
void BKE_editmesh_cache_ensure_face_normals(BMEditMesh *em, blender::bke::EditMeshData *emd); void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMeshData &emd);
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh *em, blender::bke::EditMeshData *emd); void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMeshData &emd);
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh *em, blender::bke::EditMeshData *emd); void BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em, blender::bke::EditMeshData &emd);
std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax( std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax(
const BMEditMesh *em, const blender::bke::EditMeshData *emd); const BMEditMesh &em, const blender::bke::EditMeshData &emd);
@@ -23,7 +23,7 @@ struct Scene;
/** Return the number of derived triangles (looptris). */ /** Return the number of derived triangles (looptris). */
int BKE_mesh_runtime_looptri_len(const Mesh *mesh); int BKE_mesh_runtime_looptri_len(const Mesh *mesh);
bool BKE_mesh_runtime_ensure_edit_data(Mesh *mesh); void BKE_mesh_runtime_ensure_edit_data(Mesh *mesh);
/** /**
* Clear and free any derived caches associated with the mesh geometry data. Examples include BVH * Clear and free any derived caches associated with the mesh geometry data. Examples include BVH
+2 -2
View File
@@ -117,7 +117,7 @@ struct MeshRuntime {
* Lazily initialized SoA data from the #edit_mesh field in #Mesh. Used when the mesh is a BMesh * Lazily initialized SoA data from the #edit_mesh field in #Mesh. Used when the mesh is a BMesh
* wrapper (#ME_WRAPPER_TYPE_BMESH). * wrapper (#ME_WRAPPER_TYPE_BMESH).
*/ */
EditMeshData *edit_data = nullptr; std::unique_ptr<EditMeshData> edit_data;
/** /**
* Data used to efficiently draw the mesh in the viewport, especially useful when * Data used to efficiently draw the mesh in the viewport, especially useful when
@@ -134,7 +134,7 @@ struct MeshRuntime {
BVHCache *bvh_cache = nullptr; BVHCache *bvh_cache = nullptr;
/** Cache of non-manifold boundary data for Shrink-wrap Target Project. */ /** Cache of non-manifold boundary data for Shrink-wrap Target Project. */
ShrinkwrapBoundaryData *shrinkwrap_data = nullptr; std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_data;
/** Needed in case we need to lazily initialize the mesh. */ /** Needed in case we need to lazily initialize the mesh. */
CustomData_MeshMasks cd_mask_extra = {}; CustomData_MeshMasks cd_mask_extra = {};
+6 -7
View File
@@ -9,8 +9,9 @@
/* Shrinkwrap stuff */ /* Shrinkwrap stuff */
#include "BKE_bvhutils.hh" #include "BKE_bvhutils.hh"
#include "BLI_bitmap.h"
#include "BLI_array.hh"
#include "BLI_bit_vector.hh"
#include "BLI_math_vector_types.hh" #include "BLI_math_vector_types.hh"
#include "BLI_offset_indices.hh" #include "BLI_offset_indices.hh"
#include "BLI_span.hh" #include "BLI_span.hh"
@@ -48,23 +49,21 @@ struct ShrinkwrapBoundaryVertData {
struct ShrinkwrapBoundaryData { struct ShrinkwrapBoundaryData {
/* True if the edge belongs to exactly one face. */ /* True if the edge belongs to exactly one face. */
const BLI_bitmap *edge_is_boundary; blender::BitVector<> edge_is_boundary;
/* True if the looptri has any boundary edges. */ /* True if the looptri has any boundary edges. */
const BLI_bitmap *looptri_has_boundary; blender::BitVector<> looptri_has_boundary;
/* Mapping from vertex index to boundary vertex index, or -1. /* Mapping from vertex index to boundary vertex index, or -1.
* Used for compact storage of data about boundary vertices. */ * Used for compact storage of data about boundary vertices. */
const int *vert_boundary_id; blender::Array<int> vert_boundary_id;
unsigned int num_boundary_verts;
/* Direction data about boundary vertices. */ /* Direction data about boundary vertices. */
const ShrinkwrapBoundaryVertData *boundary_verts; blender::Array<ShrinkwrapBoundaryVertData> boundary_verts;
}; };
/** /**
* Free boundary data for target project. * Free boundary data for target project.
*/ */
void BKE_shrinkwrap_boundary_data_free(ShrinkwrapBoundaryData *data);
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh); void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh);
/* Information about a mesh and BVH tree. */ /* Information about a mesh and BVH tree. */
@@ -1035,9 +1035,9 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final)
case ME_WRAPPER_TYPE_MDATA: case ME_WRAPPER_TYPE_MDATA:
break; break;
case ME_WRAPPER_TYPE_BMESH: { case ME_WRAPPER_TYPE_BMESH: {
BMEditMesh *em = mesh_final->edit_mesh; BMEditMesh &em = *mesh_final->edit_mesh;
blender::bke::EditMeshData *emd = mesh_final->runtime->edit_data; blender::bke::EditMeshData &emd = *mesh_final->runtime->edit_data;
if (!emd->vertexCos.is_empty()) { if (!emd.vertexCos.is_empty()) {
BKE_editmesh_cache_ensure_vert_normals(em, emd); BKE_editmesh_cache_ensure_vert_normals(em, emd);
BKE_editmesh_cache_ensure_face_normals(em, emd); BKE_editmesh_cache_ensure_face_normals(em, emd);
} }
@@ -23,14 +23,14 @@
/** \name Ensure Data (derived from coords) /** \name Ensure Data (derived from coords)
* \{ */ * \{ */
void BKE_editmesh_cache_ensure_face_normals(BMEditMesh *em, blender::bke::EditMeshData *emd) void BKE_editmesh_cache_ensure_face_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
{ {
if (emd->vertexCos.is_empty() || !emd->faceNos.is_empty()) { if (emd.vertexCos.is_empty() || !emd.faceNos.is_empty()) {
return; return;
} }
BMesh *bm = em->bm; BMesh *bm = em.bm;
emd->faceNos.reinitialize(bm->totface); emd.faceNos.reinitialize(bm->totface);
BM_mesh_elem_index_ensure(bm, BM_VERT); BM_mesh_elem_index_ensure(bm, BM_VERT);
BMFace *efa; BMFace *efa;
@@ -39,52 +39,52 @@ void BKE_editmesh_cache_ensure_face_normals(BMEditMesh *em, blender::bke::EditMe
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
BM_elem_index_set(efa, i); /* set_inline */ BM_elem_index_set(efa, i); /* set_inline */
BM_face_calc_normal_vcos( BM_face_calc_normal_vcos(
bm, efa, emd->faceNos[i], reinterpret_cast<const float(*)[3]>(emd->vertexCos.data())); bm, efa, emd.faceNos[i], reinterpret_cast<const float(*)[3]>(emd.vertexCos.data()));
} }
bm->elem_index_dirty &= ~BM_FACE; bm->elem_index_dirty &= ~BM_FACE;
} }
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh *em, blender::bke::EditMeshData *emd) void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
{ {
if (emd->vertexCos.is_empty() || !emd->vertexNos.is_empty()) { if (emd.vertexCos.is_empty() || !emd.vertexNos.is_empty()) {
return; return;
} }
BMesh *bm = em->bm; BMesh *bm = em.bm;
/* Calculate vertex normals from face normals. */ /* Calculate vertex normals from face normals. */
BKE_editmesh_cache_ensure_face_normals(em, emd); BKE_editmesh_cache_ensure_face_normals(em, emd);
emd->vertexNos.reinitialize(bm->totvert); emd.vertexNos.reinitialize(bm->totvert);
BM_mesh_elem_index_ensure(bm, BM_FACE); BM_mesh_elem_index_ensure(bm, BM_FACE);
BM_verts_calc_normal_vcos(bm, BM_verts_calc_normal_vcos(bm,
reinterpret_cast<const float(*)[3]>(emd->faceNos.data()), reinterpret_cast<const float(*)[3]>(emd.faceNos.data()),
reinterpret_cast<const float(*)[3]>(emd->vertexCos.data()), reinterpret_cast<const float(*)[3]>(emd.vertexCos.data()),
reinterpret_cast<float(*)[3]>(emd->vertexNos.data())); reinterpret_cast<float(*)[3]>(emd.vertexNos.data()));
} }
void BKE_editmesh_cache_ensure_face_centers(BMEditMesh *em, blender::bke::EditMeshData *emd) void BKE_editmesh_cache_ensure_face_centers(BMEditMesh &em, blender::bke::EditMeshData &emd)
{ {
if (!emd->faceCos.is_empty()) { if (!emd.faceCos.is_empty()) {
return; return;
} }
BMesh *bm = em->bm; BMesh *bm = em.bm;
emd->faceCos.reinitialize(bm->totface); emd.faceCos.reinitialize(bm->totface);
BMFace *efa; BMFace *efa;
BMIter fiter; BMIter fiter;
int i; int i;
if (emd->vertexCos.is_empty()) { if (emd.vertexCos.is_empty()) {
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
BM_face_calc_center_median(efa, emd->faceCos[i]); BM_face_calc_center_median(efa, emd.faceCos[i]);
} }
} }
else { else {
BM_mesh_elem_index_ensure(bm, BM_VERT); BM_mesh_elem_index_ensure(bm, BM_VERT);
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
BM_face_calc_center_median_vcos( BM_face_calc_center_median_vcos(
bm, efa, emd->faceCos[i], reinterpret_cast<const float(*)[3]>(emd->vertexCos.data())); bm, efa, emd.faceCos[i], reinterpret_cast<const float(*)[3]>(emd.vertexCos.data()));
} }
} }
} }
@@ -96,15 +96,15 @@ void BKE_editmesh_cache_ensure_face_centers(BMEditMesh *em, blender::bke::EditMe
* \{ */ * \{ */
std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax( std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax(
const BMEditMesh *em, const blender::bke::EditMeshData *emd) const BMEditMesh &em, const blender::bke::EditMeshData &emd)
{ {
using namespace blender; using namespace blender;
BMesh *bm = em->bm; BMesh *bm = em.bm;
if (bm->totvert == 0) { if (bm->totvert == 0) {
return std::nullopt; return std::nullopt;
} }
if (emd->vertexCos.is_empty()) { if (emd.vertexCos.is_empty()) {
BMVert *eve; BMVert *eve;
BMIter iter; BMIter iter;
float3 min(std::numeric_limits<float>::max()); float3 min(std::numeric_limits<float>::max());
@@ -115,7 +115,7 @@ std::optional<blender::Bounds<blender::float3>> BKE_editmesh_cache_calc_minmax(
return Bounds<float3>{min, max}; return Bounds<float3>{min, max};
} }
return bounds::min_max(emd->vertexCos.as_span()); return bounds::min_max(emd.vertexCos.as_span());
} }
/** \} */ /** \} */
+1 -1
View File
@@ -1090,7 +1090,7 @@ std::optional<blender::Bounds<blender::float3>> Mesh::bounds_min_max() const
this->runtime->bounds_cache.ensure([&](Bounds<float3> &r_bounds) { this->runtime->bounds_cache.ensure([&](Bounds<float3> &r_bounds) {
switch (this->runtime->wrapper_type) { switch (this->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: case ME_WRAPPER_TYPE_BMESH:
r_bounds = *BKE_editmesh_cache_calc_minmax(this->edit_mesh, this->runtime->edit_data); r_bounds = *BKE_editmesh_cache_calc_minmax(*this->edit_mesh, *this->runtime->edit_data);
break; break;
case ME_WRAPPER_TYPE_MDATA: case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD: case ME_WRAPPER_TYPE_SUBD:
@@ -48,7 +48,7 @@ void BKE_mesh_foreach_mapped_vert(
const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vertexCos; const blender::Span<blender::float3> positions = mesh->runtime->edit_data->vertexCos;
blender::Span<blender::float3> vert_normals; blender::Span<blender::float3> vert_normals;
if (flag & MESH_FOREACH_USE_NORMAL) { if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime->edit_data); BKE_editmesh_cache_ensure_vert_normals(*em, *mesh->runtime->edit_data);
vert_normals = mesh->runtime->edit_data->vertexNos; vert_normals = mesh->runtime->edit_data->vertexNos;
} }
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
@@ -245,11 +245,11 @@ void BKE_mesh_foreach_mapped_face_center(
BMIter iter; BMIter iter;
int i; int i;
BKE_editmesh_cache_ensure_face_centers(em, mesh->runtime->edit_data); BKE_editmesh_cache_ensure_face_centers(*em, *mesh->runtime->edit_data);
face_centers = mesh->runtime->edit_data->faceCos; /* always set */ face_centers = mesh->runtime->edit_data->faceCos; /* always set */
if (flag & MESH_FOREACH_USE_NORMAL) { if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_editmesh_cache_ensure_face_normals(em, mesh->runtime->edit_data); BKE_editmesh_cache_ensure_face_normals(*em, *mesh->runtime->edit_data);
face_normals = mesh->runtime->edit_data->faceNos; /* maybe nullptr */ face_normals = mesh->runtime->edit_data->faceNos; /* maybe nullptr */
} }
@@ -70,9 +70,6 @@ MeshRuntime::~MeshRuntime()
free_mesh_eval(*this); free_mesh_eval(*this);
free_bvh_cache(*this); free_bvh_cache(*this);
free_batch_cache(*this); free_batch_cache(*this);
if (this->shrinkwrap_data) {
BKE_shrinkwrap_boundary_data_free(this->shrinkwrap_data);
}
} }
static int reset_bits_and_count(MutableBitSpan bits, const Span<int> indices_to_reset) static int reset_bits_and_count(MutableBitSpan bits, const Span<int> indices_to_reset)
@@ -282,13 +279,11 @@ void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri,
} }
} }
bool BKE_mesh_runtime_ensure_edit_data(Mesh *mesh) void BKE_mesh_runtime_ensure_edit_data(Mesh *mesh)
{ {
if (mesh->runtime->edit_data != nullptr) { if (!mesh->runtime->edit_data) {
return false; mesh->runtime->edit_data = std::make_unique<blender::bke::EditMeshData>();
} }
mesh->runtime->edit_data = MEM_new<blender::bke::EditMeshData>(__func__);
return true;
} }
void BKE_mesh_runtime_clear_cache(Mesh *mesh) void BKE_mesh_runtime_clear_cache(Mesh *mesh)
@@ -296,8 +291,7 @@ void BKE_mesh_runtime_clear_cache(Mesh *mesh)
using namespace blender::bke; using namespace blender::bke;
free_mesh_eval(*mesh->runtime); free_mesh_eval(*mesh->runtime);
free_batch_cache(*mesh->runtime); free_batch_cache(*mesh->runtime);
MEM_delete(mesh->runtime->edit_data); mesh->runtime->edit_data.reset();
mesh->runtime->edit_data = nullptr;
BKE_mesh_runtime_clear_geometry(mesh); BKE_mesh_runtime_clear_geometry(mesh);
} }
@@ -320,10 +314,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
mesh->runtime->looptri_faces_cache.tag_dirty(); mesh->runtime->looptri_faces_cache.tag_dirty();
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink(); mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink(); mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
if (mesh->runtime->shrinkwrap_data) { mesh->runtime->shrinkwrap_data.reset();
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
mesh->runtime->shrinkwrap_data = nullptr;
}
mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY; mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY;
} }
@@ -353,10 +344,7 @@ void BKE_mesh_tag_edges_split(Mesh *mesh)
} }
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink(); mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink(); mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
if (mesh->runtime->shrinkwrap_data) { mesh->runtime->shrinkwrap_data.reset();
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
mesh->runtime->shrinkwrap_data = nullptr;
}
} }
void BKE_mesh_tag_sharpness_changed(Mesh *mesh) void BKE_mesh_tag_sharpness_changed(Mesh *mesh)
@@ -125,9 +125,9 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
* be wrong, but it's not harmful. */ * be wrong, but it's not harmful. */
BKE_mesh_ensure_default_orig_index_customdata_no_check(me); BKE_mesh_ensure_default_orig_index_customdata_no_check(me);
blender::bke::EditMeshData *edit_data = me->runtime->edit_data; blender::bke::EditMeshData &edit_data = *me->runtime->edit_data;
if (!edit_data->vertexCos.is_empty()) { if (!edit_data.vertexCos.is_empty()) {
me->vert_positions_for_write().copy_from(edit_data->vertexCos); me->vert_positions_for_write().copy_from(edit_data.vertexCos);
me->runtime->is_original_bmesh = false; me->runtime->is_original_bmesh = false;
} }
@@ -135,8 +135,7 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
BKE_mesh_wrapper_deferred_finalize_mdata(me); BKE_mesh_wrapper_deferred_finalize_mdata(me);
} }
MEM_delete(me->runtime->edit_data); me->runtime->edit_data.reset();
me->runtime->edit_data = nullptr;
break; break;
} }
} }
@@ -170,7 +169,7 @@ const float (*BKE_mesh_wrapper_face_normals(Mesh *mesh))[3]
{ {
switch (mesh->runtime->wrapper_type) { switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: case ME_WRAPPER_TYPE_BMESH:
BKE_editmesh_cache_ensure_face_normals(mesh->edit_mesh, mesh->runtime->edit_data); BKE_editmesh_cache_ensure_face_normals(*mesh->edit_mesh, *mesh->runtime->edit_data);
if (mesh->runtime->edit_data->faceNos.is_empty()) { if (mesh->runtime->edit_data->faceNos.is_empty()) {
return nullptr; return nullptr;
} }
@@ -204,9 +203,9 @@ void BKE_mesh_wrapper_vert_coords_copy(const Mesh *me, blender::MutableSpan<floa
switch (me->runtime->wrapper_type) { switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: { case ME_WRAPPER_TYPE_BMESH: {
BMesh *bm = me->edit_mesh->bm; BMesh *bm = me->edit_mesh->bm;
blender::bke::EditMeshData *edit_data = me->runtime->edit_data; const blender::bke::EditMeshData &edit_data = *me->runtime->edit_data;
if (!edit_data->vertexCos.is_empty()) { if (!edit_data.vertexCos.is_empty()) {
positions.copy_from(edit_data->vertexCos); positions.copy_from(edit_data.vertexCos);
} }
else { else {
BMIter iter; BMIter iter;
@@ -236,10 +235,10 @@ void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const Mesh *me,
case ME_WRAPPER_TYPE_BMESH: { case ME_WRAPPER_TYPE_BMESH: {
BMesh *bm = me->edit_mesh->bm; BMesh *bm = me->edit_mesh->bm;
BLI_assert(vert_coords_len == bm->totvert); BLI_assert(vert_coords_len == bm->totvert);
const blender::bke::EditMeshData *edit_data = me->runtime->edit_data; const blender::bke::EditMeshData &edit_data = *me->runtime->edit_data;
if (!edit_data->vertexCos.is_empty()) { if (!edit_data.vertexCos.is_empty()) {
for (int i = 0; i < vert_coords_len; i++) { for (int i = 0; i < vert_coords_len; i++) {
mul_v3_m4v3(vert_coords[i], mat, edit_data->vertexCos[i]); mul_v3_m4v3(vert_coords[i], mat, edit_data.vertexCos[i]);
} }
} }
else { else {
+3 -3
View File
@@ -965,11 +965,11 @@ static void modwrap_dependsOnNormals(Mesh *me)
{ {
switch (me->runtime->wrapper_type) { switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: { case ME_WRAPPER_TYPE_BMESH: {
blender::bke::EditMeshData *edit_data = me->runtime->edit_data; blender::bke::EditMeshData &edit_data = *me->runtime->edit_data;
if (!edit_data->vertexCos.is_empty()) { if (!edit_data.vertexCos.is_empty()) {
/* Note that 'ensure' is acceptable here since these values aren't modified in-place. /* Note that 'ensure' is acceptable here since these values aren't modified in-place.
* If that changes we'll need to recalculate. */ * If that changes we'll need to recalculate. */
BKE_editmesh_cache_ensure_vert_normals(me->edit_mesh, edit_data); BKE_editmesh_cache_ensure_vert_normals(*me->edit_mesh, edit_data);
} }
else { else {
BM_mesh_normals_update(me->edit_mesh->bm); BM_mesh_normals_update(me->edit_mesh->bm);
@@ -478,7 +478,7 @@ static const Mesh *mesh_data_from_duplicator_object(Object *ob,
* We could change this but it matches 2.7x behavior. */ * We could change this but it matches 2.7x behavior. */
me_eval = BKE_object_get_editmesh_eval_cage(ob); me_eval = BKE_object_get_editmesh_eval_cage(ob);
if ((me_eval == nullptr) || (me_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH)) { if ((me_eval == nullptr) || (me_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
blender::bke::EditMeshData *emd = me_eval ? me_eval->runtime->edit_data : nullptr; blender::bke::EditMeshData *emd = me_eval ? me_eval->runtime->edit_data.get() : nullptr;
/* Only assign edit-mesh in the case we can't use `me_eval`. */ /* Only assign edit-mesh in the case we can't use `me_eval`. */
*r_em = em; *r_em = em;
@@ -487,7 +487,7 @@ static const Mesh *mesh_data_from_duplicator_object(Object *ob,
if ((emd != nullptr) && !emd->vertexCos.is_empty()) { if ((emd != nullptr) && !emd->vertexCos.is_empty()) {
*r_vert_coords = reinterpret_cast<const float(*)[3]>(emd->vertexCos.data()); *r_vert_coords = reinterpret_cast<const float(*)[3]>(emd->vertexCos.data());
if (r_vert_normals != nullptr) { if (r_vert_normals != nullptr) {
BKE_editmesh_cache_ensure_vert_normals(em, emd); BKE_editmesh_cache_ensure_vert_normals(*em, *emd);
*r_vert_normals = reinterpret_cast<const float(*)[3]>(emd->vertexNos.data()); *r_vert_normals = reinterpret_cast<const float(*)[3]>(emd->vertexNos.data());
} }
} }
+20 -39
View File
@@ -148,7 +148,7 @@ bool BKE_shrinkwrap_init_tree(
} }
if (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) { if (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
data->boundary = mesh->runtime->shrinkwrap_data; data->boundary = mesh->runtime->shrinkwrap_data.get();
} }
return true; return true;
@@ -159,16 +159,6 @@ void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data)
free_bvhtree_from_mesh(&data->treeData); free_bvhtree_from_mesh(&data->treeData);
} }
void BKE_shrinkwrap_boundary_data_free(ShrinkwrapBoundaryData *data)
{
MEM_freeN((void *)data->edge_is_boundary);
MEM_freeN((void *)data->looptri_has_boundary);
MEM_freeN((void *)data->vert_boundary_id);
MEM_freeN((void *)data->boundary_verts);
MEM_freeN(data);
}
/* Accumulate edge for average boundary edge direction. */ /* Accumulate edge for average boundary edge direction. */
static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata, static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata,
signed char *status, signed char *status,
@@ -193,7 +183,7 @@ static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata,
status[index] = (status[index] == 0) ? side : -1; status[index] = (status[index] == 0) ? side : -1;
} }
static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh) static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Mesh *mesh)
{ {
using namespace blender; using namespace blender;
const blender::Span<float3> positions = mesh->vert_positions(); const blender::Span<float3> positions = mesh->vert_positions();
@@ -214,36 +204,33 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
} }
/* Build the boundary edge bitmask. */ /* Build the boundary edge bitmask. */
BLI_bitmap *edge_is_boundary = BLI_BITMAP_NEW(mesh->totedge, blender::BitVector<> edge_is_boundary(mesh->totedge, false);
"ShrinkwrapBoundaryData::edge_is_boundary");
uint num_boundary_edges = 0; uint num_boundary_edges = 0;
for (int i = 0; i < mesh->totedge; i++) { for (int i = 0; i < mesh->totedge; i++) {
edge_mode[i] = (edge_mode[i] == 1); edge_mode[i] = (edge_mode[i] == 1);
if (edge_mode[i]) { if (edge_mode[i]) {
BLI_BITMAP_ENABLE(edge_is_boundary, i); edge_is_boundary[i].set();
num_boundary_edges++; num_boundary_edges++;
} }
} }
/* If no boundary, return nullptr. */ /* If no boundary, return nullptr. */
if (num_boundary_edges == 0) { if (num_boundary_edges == 0) {
MEM_freeN(edge_is_boundary);
MEM_freeN(edge_mode); MEM_freeN(edge_mode);
return nullptr; return {};
} }
/* Allocate the data object. */ /* Allocate the data object. */
ShrinkwrapBoundaryData *data = MEM_cnew<ShrinkwrapBoundaryData>(__func__); std::unique_ptr<ShrinkwrapBoundaryData> data = std::make_unique<ShrinkwrapBoundaryData>();
data->edge_is_boundary = edge_is_boundary; data->edge_is_boundary = std::move(edge_is_boundary);
/* Build the boundary looptri bitmask. */ /* Build the boundary looptri bitmask. */
const blender::Span<MLoopTri> looptris = mesh->looptris(); const blender::Span<MLoopTri> looptris = mesh->looptris();
BLI_bitmap *looptri_has_boundary = BLI_BITMAP_NEW(looptris.size(), blender::BitVector<> looptri_has_boundary(looptris.size(), false);
"ShrinkwrapBoundaryData::looptri_is_boundary");
for (const int64_t i : looptris.index_range()) { for (const int64_t i : looptris.index_range()) {
const int3 real_edges = bke::mesh::looptri_get_real_edges( const int3 real_edges = bke::mesh::looptri_get_real_edges(
@@ -251,17 +238,16 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) { if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {
BLI_BITMAP_ENABLE(looptri_has_boundary, i); looptri_has_boundary[i].set();
break; break;
} }
} }
} }
data->looptri_has_boundary = looptri_has_boundary; data->looptri_has_boundary = std::move(looptri_has_boundary);
/* Find boundary vertices and build a mapping table for compact storage of data. */ /* Find boundary vertices and build a mapping table for compact storage of data. */
int *vert_boundary_id = static_cast<int *>( Array<int> vert_boundary_id(mesh->totvert, 0);
MEM_calloc_arrayN(size_t(mesh->totvert), sizeof(int), __func__));
for (int i = 0; i < mesh->totedge; i++) { for (int i = 0; i < mesh->totedge; i++) {
if (edge_mode[i]) { if (edge_mode[i]) {
@@ -279,11 +265,9 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
} }
data->vert_boundary_id = vert_boundary_id; data->vert_boundary_id = vert_boundary_id;
data->num_boundary_verts = num_boundary_verts;
/* Compute average directions. */ /* Compute average directions. */
ShrinkwrapBoundaryVertData *boundary_verts = static_cast<ShrinkwrapBoundaryVertData *>( Array<ShrinkwrapBoundaryVertData> boundary_verts(num_boundary_verts);
MEM_calloc_arrayN(num_boundary_verts, sizeof(*boundary_verts), __func__));
signed char *vert_status = static_cast<signed char *>( signed char *vert_status = static_cast<signed char *>(
MEM_calloc_arrayN(num_boundary_verts, sizeof(char), __func__)); MEM_calloc_arrayN(num_boundary_verts, sizeof(char), __func__));
@@ -296,8 +280,8 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
sub_v3_v3v3(dir, positions[edge[1]], positions[edge[0]]); sub_v3_v3v3(dir, positions[edge[1]], positions[edge[0]]);
normalize_v3(dir); normalize_v3(dir);
merge_vert_dir(boundary_verts, vert_status, vert_boundary_id[edge[0]], dir, 1); merge_vert_dir(boundary_verts.data(), vert_status, vert_boundary_id[edge[0]], dir, 1);
merge_vert_dir(boundary_verts, vert_status, vert_boundary_id[edge[1]], dir, 2); merge_vert_dir(boundary_verts.data(), vert_status, vert_boundary_id[edge[1]], dir, 2);
} }
} }
@@ -320,7 +304,7 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
} }
} }
data->boundary_verts = boundary_verts; data->boundary_verts = std::move(boundary_verts);
MEM_freeN(edge_mode); MEM_freeN(edge_mode);
return data; return data;
@@ -328,9 +312,6 @@ static ShrinkwrapBoundaryData *shrinkwrap_build_boundary_data(Mesh *mesh)
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh) void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh)
{ {
if (mesh->runtime->shrinkwrap_data) {
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
}
mesh->runtime->shrinkwrap_data = shrinkwrap_build_boundary_data(mesh); mesh->runtime->shrinkwrap_data = shrinkwrap_build_boundary_data(mesh);
} }
@@ -957,7 +938,7 @@ static void target_project_edge(const ShrinkwrapTreeData *tree,
#endif #endif
/* Retrieve boundary vertex IDs */ /* Retrieve boundary vertex IDs */
const int *vert_boundary_id = tree->boundary->vert_boundary_id; const int *vert_boundary_id = tree->boundary->vert_boundary_id.data();
int bid1 = vert_boundary_id[edge[0]], bid2 = vert_boundary_id[edge[1]]; int bid1 = vert_boundary_id[edge[0]], bid2 = vert_boundary_id[edge[1]];
if (bid1 < 0 || bid2 < 0) { if (bid1 < 0 || bid2 < 0) {
@@ -965,7 +946,7 @@ static void target_project_edge(const ShrinkwrapTreeData *tree,
} }
/* Retrieve boundary vertex normals and align them to direction. */ /* Retrieve boundary vertex normals and align them to direction. */
const ShrinkwrapBoundaryVertData *boundary_verts = tree->boundary->boundary_verts; const ShrinkwrapBoundaryVertData *boundary_verts = tree->boundary->boundary_verts.data();
float vedge_dir[2][3], dir[3]; float vedge_dir[2][3], dir[3];
copy_v3_v3(vedge_dir[0], boundary_verts[bid1].normal_plane); copy_v3_v3(vedge_dir[0], boundary_verts[bid1].normal_plane);
@@ -1060,13 +1041,13 @@ static void mesh_looptri_target_project(void *userdata,
update_hit(nearest, index, co, hit_co, hit_no); update_hit(nearest, index, co, hit_co, hit_no);
} }
/* Boundary edges */ /* Boundary edges */
else if (tree->boundary && BLI_BITMAP_TEST(tree->boundary->looptri_has_boundary, index)) { else if (tree->boundary && tree->boundary->looptri_has_boundary[index]) {
const BLI_bitmap *is_boundary = tree->boundary->edge_is_boundary; const BitSpan is_boundary = tree->boundary->edge_is_boundary;
const int3 edges = bke::mesh::looptri_get_real_edges( const int3 edges = bke::mesh::looptri_get_real_edges(
data->edges, data->corner_verts, tree->corner_edges, *lt); data->edges, data->corner_verts, tree->corner_edges, *lt);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
if (edges[i] >= 0 && BLI_BITMAP_TEST(is_boundary, edges[i])) { if (edges[i] >= 0 && is_boundary[edges[i]]) {
target_project_edge(tree, index, co, nearest, edges[i]); target_project_edge(tree, index, co, nearest, edges[i]);
} }
} }
@@ -489,7 +489,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
mr->bm = me->edit_mesh->bm; mr->bm = me->edit_mesh->bm;
mr->edit_bmesh = me->edit_mesh; mr->edit_bmesh = me->edit_mesh;
mr->me = (do_final) ? editmesh_eval_final : editmesh_eval_cage; mr->me = (do_final) ? editmesh_eval_final : editmesh_eval_cage;
mr->edit_data = is_mode_active ? mr->me->runtime->edit_data : nullptr; mr->edit_data = is_mode_active ? mr->me->runtime->edit_data.get() : nullptr;
/* If there is no distinct cage, hide unmapped edges that can't be selected. */ /* If there is no distinct cage, hide unmapped edges that can't be selected. */
mr->hide_unmapped_edges = !do_final || editmesh_eval_final == editmesh_eval_cage; mr->hide_unmapped_edges = !do_final || editmesh_eval_final == editmesh_eval_cage;
@@ -497,8 +497,8 @@ MeshRenderData *mesh_render_data_create(Object *object,
if (mr->edit_data) { if (mr->edit_data) {
blender::bke::EditMeshData *emd = mr->edit_data; blender::bke::EditMeshData *emd = mr->edit_data;
if (!emd->vertexCos.is_empty()) { if (!emd->vertexCos.is_empty()) {
BKE_editmesh_cache_ensure_vert_normals(mr->edit_bmesh, emd); BKE_editmesh_cache_ensure_vert_normals(*mr->edit_bmesh, *emd);
BKE_editmesh_cache_ensure_face_normals(mr->edit_bmesh, emd); BKE_editmesh_cache_ensure_face_normals(*mr->edit_bmesh, *emd);
} }
mr->bm_vert_coords = mr->edit_data->vertexCos; mr->bm_vert_coords = mr->edit_data->vertexCos;
@@ -397,7 +397,7 @@ static void statvis_calc_distort(const MeshRenderData &mr, float *r_distort)
BMFace *f; BMFace *f;
if (!mr.bm_vert_coords.is_empty()) { if (!mr.bm_vert_coords.is_empty()) {
BKE_editmesh_cache_ensure_face_normals(em, mr.edit_data); BKE_editmesh_cache_ensure_face_normals(*em, *mr.edit_data);
/* Most likely this is already valid, ensure just in case. /* Most likely this is already valid, ensure just in case.
* Needed for #BM_loop_calc_face_normal_safe_vcos. */ * Needed for #BM_loop_calc_face_normal_safe_vcos. */