Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-09-05 19:56:34 +0300
committerHans Goudey <h.goudey@me.com>2022-09-05 19:56:34 +0300
commit05952aa94d33eeb504fa63618ba35c2bcc8bd19b (patch)
treec9ec37adf20c3c37ccaab44869220dcbe8e987a3 /source/blender/editors/mesh
parent63cfc8f9f6d623f33b50c5c07976af2b22845713 (diff)
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes where possible. Mutable pointers like `Mesh.mvert` make that difficult by making ownership vague. They also make code more complex by adding redundancy. The simplest solution is just removing them and retrieving layers from `CustomData` as needed. Similar changes have already been applied to curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of the pointers generally makes code more obvious and more reusable. Mesh data is now accessed with a C++ API (`Mesh::edges()` or `Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`). The CoW changes this commit makes possible are described in T95845 and T95842, and started in D14139 and D14140. The change also simplifies the ongoing mesh struct-of-array refactors from T95965. **RNA/Python Access Performance** Theoretically, accessing mesh elements with the RNA API may become slower, since the layer needs to be found on every random access. However, overhead is already high enough that this doesn't make a noticible differenc, and performance is actually improved in some cases. Random access can be up to 10% faster, but other situations might be a bit slower. Generally using `foreach_get/set` are the best way to improve performance. See the differential revision for more discussion about Python performance. Cycles has been updated to use raw pointers and the internal Blender mesh types, mostly because there is no sense in having this overhead when it's already compiled with Blender. In my tests this roughly halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million face grid). Differential Revision: https://developer.blender.org/D15488
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r--source/blender/editors/mesh/editface.cc101
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c5
-rw-r--r--source/blender/editors/mesh/mesh_data.cc105
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c13
-rw-r--r--source/blender/editors/mesh/meshtools.cc68
5 files changed, 142 insertions, 150 deletions
diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc
index 054c01626f8..6313c01011e 100644
--- a/source/blender/editors/mesh/editface.cc
+++ b/source/blender/editors/mesh/editface.cc
@@ -44,9 +44,7 @@ void paintface_flush_flags(bContext *C,
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
- MPoly *polys, *mp_orig;
const int *index_array = nullptr;
- int totpoly;
BLI_assert(flush_selection || flush_hidden);
@@ -75,11 +73,13 @@ void paintface_flush_flags(bContext *C,
Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval;
bke::MutableAttributeAccessor attributes_eval = bke::mesh_attributes_for_write(*me_eval);
bool updated = false;
+ const Span<MPoly> me_polys = me->polygons();
if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) {
/* Update the COW copy of the mesh. */
+ MutableSpan<MPoly> orig_polys = me_orig->polygons_for_write();
for (int i = 0; i < me->totpoly; i++) {
- me_orig->mpoly[i].flag = me->mpoly[i].flag;
+ orig_polys[i].flag = me_polys[i].flag;
}
if (flush_hidden) {
const VArray<bool> hide_poly_me = attributes_me.lookup_or_default<bool>(
@@ -92,15 +92,12 @@ void paintface_flush_flags(bContext *C,
/* Mesh polys => Final derived polys */
if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
- polys = me_eval->mpoly;
- totpoly = me_eval->totpoly;
-
+ MutableSpan<MPoly> eval_polys = me_orig->polygons_for_write();
/* loop over final derived polys */
- for (int i = 0; i < totpoly; i++) {
+ for (const int i : eval_polys.index_range()) {
if (index_array[i] != ORIGINDEX_NONE) {
/* Copy flags onto the final derived poly from the original mesh poly */
- mp_orig = me->mpoly + index_array[i];
- polys[i].flag = mp_orig->flag;
+ eval_polys[i].flag = me_polys[index_array[i]].flag;
}
}
const VArray<bool> hide_poly_orig = attributes_orig.lookup_or_default<bool>(
@@ -144,12 +141,13 @@ void paintface_hide(bContext *C, Object *ob, const bool unselected)
return;
}
+ MutableSpan<MPoly> polys = me->polygons_for_write();
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
".hide_poly", ATTR_DOMAIN_FACE);
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mpoly = &me->mpoly[i];
+ MPoly *mpoly = &polys[i];
if (!hide_poly.span[i]) {
if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
hide_poly.span[i] = true;
@@ -176,13 +174,14 @@ void paintface_reveal(bContext *C, Object *ob, const bool select)
return;
}
+ MutableSpan<MPoly> polys = me->polygons_for_write();
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
if (select) {
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mpoly = &me->mpoly[i];
+ MPoly *mpoly = &polys[i];
if (hide_poly[i]) {
mpoly->flag |= ME_FACE_SEL;
}
@@ -207,25 +206,28 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
+ const Span<MEdge> edges = me->edges();
+ MutableSpan<MPoly> polys = me->polygons_for_write();
+ const Span<MLoop> loops = me->loops();
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (index != (uint)-1) {
/* only put face under cursor in array */
- MPoly *mp = &me->mpoly[index];
- BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+ const MPoly *mp = &polys[index];
+ BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, &loops[mp->loopstart]);
BLI_BITMAP_ENABLE(poly_tag, index);
}
else {
/* fill array by selection */
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mp = &me->mpoly[i];
+ MPoly *mp = &polys[i];
if (hide_poly[i]) {
/* pass */
}
else if (mp->flag & ME_FACE_SEL) {
- BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+ BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, &loops[mp->loopstart]);
BLI_BITMAP_ENABLE(poly_tag, i);
}
}
@@ -236,7 +238,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
/* expand selection */
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mp = &me->mpoly[i];
+ MPoly *mp = &polys[i];
if (hide_poly[i]) {
continue;
}
@@ -244,9 +246,9 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
if (!BLI_BITMAP_TEST(poly_tag, i)) {
mark = false;
- MLoop *ml = me->mloop + mp->loopstart;
+ const MLoop *ml = &loops[mp->loopstart];
for (int b = 0; b < mp->totloop; b++, ml++) {
- if ((me->medge[ml->e].flag & ME_SEAM) == 0) {
+ if ((edges[ml->e].flag & ME_SEAM) == 0) {
if (BLI_BITMAP_TEST(edge_tag, ml->e)) {
mark = true;
break;
@@ -256,7 +258,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
if (mark) {
BLI_BITMAP_ENABLE(poly_tag, i);
- BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+ BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, &loops[mp->loopstart]);
do_it = true;
}
}
@@ -266,7 +268,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
MEM_freeN(edge_tag);
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mp = &me->mpoly[i];
+ MPoly *mp = &polys[index];
if (BLI_BITMAP_TEST(poly_tag, i)) {
SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL);
}
@@ -303,6 +305,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
return false;
}
+ MutableSpan<MPoly> polys = me->polygons_for_write();
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
@@ -311,7 +314,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
action = SEL_SELECT;
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mpoly = &me->mpoly[i];
+ MPoly *mpoly = &polys[i];
if (!hide_poly[i] && mpoly->flag & ME_FACE_SEL) {
action = SEL_DESELECT;
break;
@@ -322,7 +325,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
bool changed = false;
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mpoly = &me->mpoly[i];
+ MPoly *mpoly = &polys[i];
if (!hide_poly[i]) {
switch (action) {
case SEL_SELECT:
@@ -360,26 +363,28 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
float vec[3], bmat[3][3];
const Mesh *me = BKE_mesh_from_object(ob);
- if (!me || !me->mloopuv) {
+ if (!me || !CustomData_has_layer(&me->ldata, CD_MLOOPUV)) {
return ok;
}
- const MVert *mvert = me->mvert;
copy_m3_m4(bmat, ob->obmat);
+ const Span<MVert> verts = me->vertices();
+ const Span<MPoly> polys = me->polygons();
+ const Span<MLoop> loops = me->loops();
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
for (int i = 0; i < me->totpoly; i++) {
- MPoly *mp = &me->mpoly[i];
+ const MPoly *mp = &polys[i];
if (hide_poly[i] || !(mp->flag & ME_FACE_SEL)) {
continue;
}
- const MLoop *ml = me->mloop + mp->loopstart;
+ const MLoop *ml = &loops[mp->loopstart];
for (int b = 0; b < mp->totloop; b++, ml++) {
- mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
+ mul_v3_m3v3(vec, bmat, verts[ml->v].co);
add_v3_v3v3(vec, vec, ob->obmat[3]);
minmax_v3v3_v3(r_min, r_max, vec);
}
@@ -404,13 +409,14 @@ bool paintface_mouse_select(bContext *C,
/* Get the face under the cursor */
Mesh *me = BKE_mesh_from_object(ob);
+ MutableSpan<MPoly> polys = me->polygons_for_write();
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
if (index < me->totpoly) {
- mpoly_sel = me->mpoly + index;
+ mpoly_sel = polys.data() + index;
if (!hide_poly[index]) {
found = true;
}
@@ -469,12 +475,10 @@ bool paintface_mouse_select(bContext *C,
void paintvert_flush_flags(Object *ob)
{
+ using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
- MVert *mvert_eval, *mv;
const int *index_array = nullptr;
- int totvert;
- int i;
if (me == nullptr) {
return;
@@ -490,23 +494,21 @@ void paintvert_flush_flags(Object *ob)
index_array = (const int *)CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
- mvert_eval = me_eval->mvert;
- totvert = me_eval->totvert;
-
- mv = mvert_eval;
+ const Span<MVert> vertices = me->vertices_for_write();
+ MutableSpan<MVert> vertices_eval = me_eval->vertices_for_write();
if (index_array) {
int orig_index;
- for (i = 0; i < totvert; i++, mv++) {
+ for (const int i : vertices_eval.index_range()) {
orig_index = index_array[i];
if (orig_index != ORIGINDEX_NONE) {
- mv->flag = me->mvert[index_array[i]].flag;
+ vertices_eval[i].flag = vertices[index_array[i]].flag;
}
}
}
else {
- for (i = 0; i < totvert; i++, mv++) {
- mv->flag = me->mvert[i].flag;
+ for (const int i : vertices_eval.index_range()) {
+ vertices_eval[i].flag = vertices[i].flag;
}
}
@@ -527,6 +529,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
return false;
}
+ MutableSpan<MVert> verts = me->vertices_for_write();
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
@@ -535,7 +538,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
action = SEL_SELECT;
for (int i = 0; i < me->totvert; i++) {
- MVert *mvert = &me->mvert[i];
+ MVert *mvert = &verts[i];
if (!hide_vert[i] && mvert->flag & SELECT) {
action = SEL_DESELECT;
break;
@@ -545,7 +548,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
bool changed = false;
for (int i = 0; i < me->totvert; i++) {
- MVert *mvert = &me->mvert[i];
+ MVert *mvert = &verts[i];
if (!hide_vert[i]) {
switch (action) {
case SEL_SELECT:
@@ -591,8 +594,11 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
{
using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
-
- if (me == nullptr || me->dvert == nullptr) {
+ if (me == nullptr) {
+ return;
+ }
+ const Span<MDeformVert> dverts = me->deform_verts();
+ if (dverts.is_empty()) {
return;
}
@@ -600,13 +606,14 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
}
+ MutableSpan<MVert> verts = me->vertices_for_write();
bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
for (int i = 0; i < me->totvert; i++) {
- MVert *mv = &me->mvert[i];
- MDeformVert *dv = &me->dvert[i];
+ MVert *mv = &verts[i];
+ const MDeformVert *dv = &dverts[i];
if (!hide_vert[i]) {
if (dv->dw == nullptr) {
/* if null weight then not grouped */
@@ -628,10 +635,10 @@ void paintvert_hide(bContext *C, Object *ob, const bool unselected)
return;
}
+ MutableSpan<MVert> verts = me->vertices_for_write();
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
".hide_vert", ATTR_DOMAIN_POINT);
- MutableSpan<MVert> verts(me->mvert, me->totvert);
for (const int i : verts.index_range()) {
MVert &vert = verts[i];
@@ -661,10 +668,10 @@ void paintvert_reveal(bContext *C, Object *ob, const bool select)
return;
}
+ MutableSpan<MVert> verts = me->vertices_for_write();
bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
".hide_vert", ATTR_DOMAIN_POINT, false);
- MutableSpan<MVert> verts(me->mvert, me->totvert);
for (const int i : verts.index_range()) {
MVert &vert = verts[i];
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 15e28381cb6..7bb1dc3723f 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -361,8 +361,6 @@ static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool
if (create) {
um_arraystore.users += 1;
}
-
- BKE_mesh_update_customdata_pointers(me, false);
}
/**
@@ -465,9 +463,6 @@ static void um_arraystore_expand(UndoMesh *um)
BLI_assert(me->totselect == (state_len / stride));
UNUSED_VARS_NDEBUG(stride);
}
-
- /* not essential, but prevents accidental dangling pointer access */
- BKE_mesh_update_customdata_pointers(me, false);
}
static void um_arraystore_free(UndoMesh *um)
diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc
index 1511da810cb..09673b3d7ad 100644
--- a/source/blender/editors/mesh/mesh_data.cc
+++ b/source/blender/editors/mesh/mesh_data.cc
@@ -18,6 +18,7 @@
#include "BLI_utildefines.h"
#include "BKE_attribute.h"
+#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
@@ -44,6 +45,8 @@
#include "mesh_intern.h" /* own include */
using blender::Array;
+using blender::MutableSpan;
+using blender::Span;
static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_tot)
{
@@ -128,7 +131,6 @@ static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
}
else {
CustomData_free_layer(data, type, tot, layer_index + n);
- BKE_mesh_update_customdata_pointers(me, true);
}
}
@@ -186,7 +188,7 @@ static void mesh_uv_reset_bmface(BMFace *f, const int cd_loop_uv_offset)
mesh_uv_reset_array(fuv.data(), f->len);
}
-static void mesh_uv_reset_mface(MPoly *mp, MLoopUV *mloopuv)
+static void mesh_uv_reset_mface(const MPoly *mp, MLoopUV *mloopuv)
{
Array<float *, BM_DEFAULT_NGON_STACK_SIZE> fuv(mp->totloop);
@@ -223,8 +225,9 @@ void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum)
BLI_assert(CustomData_has_layer(&me->ldata, CD_MLOOPUV));
MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, layernum);
+ const MPoly *polys = BKE_mesh_polygons(me);
for (int i = 0; i < me->totpoly; i++) {
- mesh_uv_reset_mface(&me->mpoly[i], mloopuv);
+ mesh_uv_reset_mface(&polys[i], mloopuv);
}
}
@@ -280,9 +283,13 @@ int ED_mesh_uv_add(
return -1;
}
- if (me->mloopuv && do_init) {
- CustomData_add_layer_named(
- &me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
+ if (CustomData_has_layer(&me->ldata, CD_MLOOPUV) && do_init) {
+ CustomData_add_layer_named(&me->ldata,
+ CD_MLOOPUV,
+ CD_DUPLICATE,
+ CustomData_get_layer(&me->ldata, CD_MLOOPUV),
+ me->totloop,
+ name);
is_init = true;
}
else {
@@ -293,8 +300,6 @@ int ED_mesh_uv_add(
if (active_set || layernum_dst == 0) {
CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst);
}
-
- BKE_mesh_update_customdata_pointers(me, true);
}
/* don't overwrite our copied coords */
@@ -399,9 +404,13 @@ int ED_mesh_color_add(Mesh *me,
else {
layernum = CustomData_number_of_layers(&me->ldata, CD_PROP_BYTE_COLOR);
- if (me->mloopcol && do_init) {
- CustomData_add_layer_named(
- &me->ldata, CD_PROP_BYTE_COLOR, CD_DUPLICATE, me->mloopcol, me->totloop, name);
+ if (CustomData_get_active_layer(&me->ldata, CD_PROP_BYTE_COLOR) != -1 && do_init) {
+ CustomData_add_layer_named(&me->ldata,
+ CD_PROP_BYTE_COLOR,
+ CD_DUPLICATE,
+ CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR),
+ me->totloop,
+ name);
}
else {
CustomData_add_layer_named(
@@ -412,7 +421,7 @@ int ED_mesh_color_add(Mesh *me,
CustomData_set_layer_active(&me->ldata, CD_PROP_BYTE_COLOR, layernum);
}
- BKE_mesh_update_customdata_pointers(me, true);
+ BKE_mesh_tessface_clear(me);
}
DEG_id_tag_update(&me->id, 0);
@@ -432,7 +441,7 @@ bool ED_mesh_color_ensure(Mesh *me, const char *name)
layer = me->ldata.layers + CustomData_get_layer_index(&me->ldata, CD_PROP_BYTE_COLOR);
BKE_id_attributes_active_color_set(&me->id, layer);
- BKE_mesh_update_customdata_pointers(me, true);
+ BKE_mesh_tessface_clear(me);
}
DEG_id_tag_update(&me->id, 0);
@@ -496,7 +505,7 @@ int ED_mesh_sculpt_color_add(Mesh *me,
CustomData_set_layer_active(&me->vdata, CD_PROP_COLOR, layernum);
}
- BKE_mesh_update_customdata_pointers(me, true);
+ BKE_mesh_tessface_clear(me);
}
DEG_id_tag_update(&me->id, 0);
@@ -767,15 +776,20 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
/* Tag edges as sharp according to smooth threshold if needed,
* to preserve autosmooth shading. */
if (me->flag & ME_AUTOSMOOTH) {
- BKE_edges_sharp_from_angle_set(me->mvert,
- me->totvert,
- me->medge,
- me->totedge,
- me->mloop,
- me->totloop,
- me->mpoly,
+ const Span<MVert> verts = me->vertices();
+ MutableSpan<MEdge> edges = me->edges_for_write();
+ const Span<MPoly> polys = me->polygons();
+ const Span<MLoop> loops = me->loops();
+
+ BKE_edges_sharp_from_angle_set(verts.data(),
+ verts.size(),
+ edges.data(),
+ edges.size(),
+ loops.data(),
+ loops.size(),
+ polys.data(),
BKE_mesh_poly_normals_ensure(me),
- me->totpoly,
+ polys.size(),
me->smoothresh);
}
@@ -873,27 +887,22 @@ static void mesh_add_verts(Mesh *mesh, int len)
CustomData_free(&mesh->vdata, mesh->totvert);
mesh->vdata = vdata;
- BKE_mesh_update_customdata_pointers(mesh, false);
BKE_mesh_runtime_clear_cache(mesh);
- /* scan the input list and insert the new vertices */
+ const int old_vertex_num = mesh->totvert;
+ mesh->totvert = totvert;
- /* set default flags */
- MVert *mvert = &mesh->mvert[mesh->totvert];
- for (int i = 0; i < len; i++, mvert++) {
- mvert->flag |= SELECT;
+ MutableSpan<MVert> verts = mesh->vertices_for_write();
+ for (MVert &vert : verts.drop_front(old_vertex_num)) {
+ vert.flag = SELECT;
}
-
- /* set final vertex list size */
- mesh->totvert = totvert;
}
static void mesh_add_edges(Mesh *mesh, int len)
{
CustomData edata;
- MEdge *medge;
- int i, totedge;
+ int totedge;
if (len == 0) {
return;
@@ -911,17 +920,16 @@ static void mesh_add_edges(Mesh *mesh, int len)
CustomData_free(&mesh->edata, mesh->totedge);
mesh->edata = edata;
- BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
BKE_mesh_runtime_clear_cache(mesh);
- /* set default flags */
- medge = &mesh->medge[mesh->totedge];
- for (i = 0; i < len; i++, medge++) {
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
- }
-
+ const int old_edges_num = mesh->totedge;
mesh->totedge = totedge;
+
+ MutableSpan<MEdge> edges = mesh->edges_for_write();
+ for (MEdge &edge : edges.drop_front(old_edges_num)) {
+ edge.flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
+ }
}
static void mesh_add_loops(Mesh *mesh, int len)
@@ -947,7 +955,6 @@ static void mesh_add_loops(Mesh *mesh, int len)
CustomData_free(&mesh->ldata, mesh->totloop);
mesh->ldata = ldata;
- BKE_mesh_update_customdata_pointers(mesh, true);
mesh->totloop = totloop;
}
@@ -955,8 +962,7 @@ static void mesh_add_loops(Mesh *mesh, int len)
static void mesh_add_polys(Mesh *mesh, int len)
{
CustomData pdata;
- MPoly *mpoly;
- int i, totpoly;
+ int totpoly;
if (len == 0) {
return;
@@ -974,17 +980,16 @@ static void mesh_add_polys(Mesh *mesh, int len)
CustomData_free(&mesh->pdata, mesh->totpoly);
mesh->pdata = pdata;
- BKE_mesh_update_customdata_pointers(mesh, true);
BKE_mesh_runtime_clear_cache(mesh);
- /* set default flags */
- mpoly = &mesh->mpoly[mesh->totpoly];
- for (i = 0; i < len; i++, mpoly++) {
- mpoly->flag = ME_FACE_SEL;
- }
-
+ const int old_polys_num = mesh->totpoly;
mesh->totpoly = totpoly;
+
+ MutableSpan<MPoly> polys = mesh->polygons_for_write();
+ for (MPoly &poly : polys.drop_front(old_polys_num)) {
+ poly.flag = ME_FACE_SEL;
+ }
}
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 82e77a88a57..905eb5d43e1 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -55,11 +55,9 @@ void ED_mesh_mirror_spatial_table_begin(Object *ob, BMEditMesh *em, Mesh *me_eva
}
}
else {
- MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
- int i;
-
- for (i = 0; i < totvert; i++, mvert++) {
- BLI_kdtree_3d_insert(MirrKdStore.tree, i, mvert->co);
+ const MVert *verts = BKE_mesh_vertices(me_eval ? me_eval : me);
+ for (int i = 0; i < totvert; i++) {
+ BLI_kdtree_3d_insert(MirrKdStore.tree, i, verts[i].co);
}
}
@@ -164,7 +162,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
BLI_assert(me == NULL);
}
const bool is_editmode = (em != NULL);
- MEdge *medge = NULL, *med;
+ const MEdge *medge = NULL, *med;
/* Edit-mode variables. */
BMEdge *eed;
@@ -210,8 +208,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
}
else {
totedge = me->totedge;
- medge = me->medge;
-
+ medge = BKE_mesh_edges(me);
for (a = 0, med = medge; a < totedge; a++, med++) {
const uint i1 = med->v1, i2 = med->v2;
topo_hash[i1]++;
diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc
index 330560be026..88c204b56e9 100644
--- a/source/blender/editors/mesh/meshtools.cc
+++ b/source/blender/editors/mesh/meshtools.cc
@@ -55,6 +55,9 @@
#include "WM_api.h"
#include "WM_types.h"
+using blender::MutableSpan;
+using blender::Span;
+
/* * ********************** no editmode!!! *********** */
/*********************** JOIN ***************************/
@@ -691,9 +694,6 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
me->ldata = ldata;
me->pdata = pdata;
- /* tessface data removed above, no need to update */
- BKE_mesh_update_customdata_pointers(me, false);
-
/* Tag normals dirty because vertex positions could be changed from the original. */
BKE_mesh_normals_tag_dirty(me);
@@ -906,13 +906,13 @@ static bool ed_mesh_mirror_topo_table_update(Object *ob, Mesh *me_eval)
static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *me_eval, int index)
{
Mesh *me = static_cast<Mesh *>(ob->data);
- MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
+ const Span<MVert> verts = me_eval ? me_eval->vertices() : me->vertices();
+
float vec[3];
- mvert = &mvert[index];
- vec[0] = -mvert->co[0];
- vec[1] = mvert->co[1];
- vec[2] = mvert->co[2];
+ vec[0] = -verts[index].co[0];
+ vec[1] = verts[index].co[1];
+ vec[2] = verts[index].co[2];
return ED_mesh_mirror_spatial_table_lookup(ob, nullptr, me_eval, vec);
}
@@ -1128,8 +1128,8 @@ static bool mirror_facecmp(const void *a, const void *b)
int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
{
Mesh *me = static_cast<Mesh *>(ob->data);
- MVert *mv, *mvert;
- MFace mirrormf, *mf, *hashmf, *mface;
+ const MVert *mv;
+ MFace mirrormf, *mf, *hashmf;
GHash *fhash;
int *mirrorverts, *mirrorfaces;
@@ -1143,12 +1143,12 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
mirrorverts = static_cast<int *>(MEM_callocN(sizeof(int) * totvert, "MirrorVerts"));
mirrorfaces = static_cast<int *>(MEM_callocN(sizeof(int[2]) * totface, "MirrorFaces"));
- mvert = me_eval ? me_eval->mvert : me->mvert;
- mface = me_eval ? me_eval->mface : me->mface;
+ const Span<MVert> verts = me_eval ? me_eval->vertices() : me->vertices();
+ MFace *mface = (MFace *)CustomData_get_layer(&(me_eval ? me_eval : me)->fdata, CD_MFACE);
ED_mesh_mirror_spatial_table_begin(ob, em, me_eval);
- for (a = 0, mv = mvert; a < totvert; a++, mv++) {
+ for (a = 0, mv = verts.data(); a < totvert; a++, mv++) {
mirrorverts[a] = mesh_get_x_mirror_vert(ob, me_eval, a, use_topology);
}
@@ -1275,42 +1275,28 @@ bool ED_mesh_pick_face_vert(
const float mval_f[2] = {(float)mval[0], (float)mval[1]};
float len_best = FLT_MAX;
- MPoly *me_eval_mpoly;
- MLoop *me_eval_mloop;
- MVert *me_eval_mvert;
- uint me_eval_mpoly_len;
-
- me_eval_mpoly = me_eval->mpoly;
- me_eval_mloop = me_eval->mloop;
- me_eval_mvert = me_eval->mvert;
-
- me_eval_mpoly_len = me_eval->totpoly;
+ const Span<MVert> verts = me_eval->vertices();
+ const Span<MPoly> polys = me_eval->polygons();
+ const Span<MLoop> loops = me_eval->loops();
const int *index_mp_to_orig = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
/* tag all verts using this face */
if (index_mp_to_orig) {
- uint i;
-
- for (i = 0; i < me_eval_mpoly_len; i++) {
+ for (const int i : polys.index_range()) {
if (index_mp_to_orig[i] == poly_index) {
- ed_mesh_pick_face_vert__mpoly_find(region,
- mval_f,
- &me_eval_mpoly[i],
- me_eval_mvert,
- me_eval_mloop,
- &len_best,
- &v_idx_best);
+ ed_mesh_pick_face_vert__mpoly_find(
+ region, mval_f, &polys[i], verts.data(), loops.data(), &len_best, &v_idx_best);
}
}
}
else {
- if (poly_index < me_eval_mpoly_len) {
+ if (poly_index < polys.size()) {
ed_mesh_pick_face_vert__mpoly_find(region,
mval_f,
- &me_eval_mpoly[poly_index],
- me_eval_mvert,
- me_eval_mloop,
+ &polys[poly_index],
+ verts.data(),
+ loops.data(),
&len_best,
&v_idx_best);
}
@@ -1425,7 +1411,8 @@ bool ED_mesh_pick_vert(
}
/* setup data */
- data.mvert = me->mvert;
+ const Span<MVert> verts = me->vertices();
+ data.mvert = verts.data();
data.region = region;
data.mval_f = mval_f;
data.len_best = FLT_MAX;
@@ -1479,10 +1466,11 @@ MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index)
if (r_index) {
*r_index = index;
}
- if (index == -1 || me->dvert == nullptr) {
+ if (index == -1 || me->deform_verts().is_empty()) {
return nullptr;
}
- return me->dvert + index;
+ MutableSpan<MDeformVert> dverts = me->deform_verts_for_write();
+ return &dverts[index];
}
MDeformVert *ED_mesh_active_dvert_get_only(Object *ob)