Edit Mesh: use partial updates editing vertices with number buttons

Use the same partial-update functions used by transform when
editing vertex locations with the number buttons.

This avoids unnecessary calculations for normals and tessellation.

This gives around 1.44x overall speedup on high poly meshes.
This commit is contained in:
Campbell Barton 2021-07-13 20:14:58 +10:00
parent 8839b4c32a
commit 25c2875e0f
2 changed files with 103 additions and 3 deletions

View File

@ -531,6 +531,7 @@ struct uiBlockInteraction_Params {
* (user clicking on a number button arrows or pasting a value for example).
*/
bool is_click;
/**
* Array of unique event ID's (values from #uiBut.retval).
* There may be more than one for multi-button editing (see #UI_BUT_DRAG_MULTI).

View File

@ -39,6 +39,8 @@
#include "BLT_translation.h"
#include "BLI_array_utils.h"
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@ -112,10 +114,94 @@ typedef struct {
float ob_dims[3];
/* Floats only (treated as an array). */
TransformMedian ve_median, median;
bool tag_for_update;
} TransformProperties;
#define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float))
static TransformProperties *v3d_transform_props_ensure(View3D *v3d);
/* -------------------------------------------------------------------- */
/** \name Edit Mesh Partial Updates
* \{ */
static void *editmesh_partial_update_begin_fn(struct bContext *UNUSED(C),
const struct uiBlockInteraction_Params *params,
void *arg1)
{
const int retval_test = B_TRANSFORM_PANEL_MEDIAN;
if (BLI_array_findindex(
params->unique_retval_ids, params->unique_retval_ids_len, &retval_test) == -1) {
return NULL;
}
BMEditMesh *em = arg1;
int verts_mask_count = 0;
BMIter iter;
BMVert *eve;
int i;
BLI_bitmap *verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
continue;
}
BLI_BITMAP_ENABLE(verts_mask, i);
verts_mask_count += 1;
}
BMPartialUpdate *bmpinfo = BM_mesh_partial_create_from_verts_group_single(
em->bm,
&(BMPartialUpdate_Params){
.do_tessellate = true,
.do_normals = true,
},
verts_mask,
verts_mask_count);
MEM_freeN(verts_mask);
return bmpinfo;
}
static void editmesh_partial_update_end_fn(struct bContext *UNUSED(C),
const struct uiBlockInteraction_Params *UNUSED(params),
void *UNUSED(arg1),
void *user_data)
{
BMPartialUpdate *bmpinfo = user_data;
if (bmpinfo == NULL) {
return;
}
BM_mesh_partial_destroy(bmpinfo);
}
static void editmesh_partial_update_update_fn(
struct bContext *C,
const struct uiBlockInteraction_Params *UNUSED(params),
void *arg1,
void *user_data)
{
BMPartialUpdate *bmpinfo = user_data;
if (bmpinfo == NULL) {
return;
}
View3D *v3d = CTX_wm_view3d(C);
TransformProperties *tfp = v3d_transform_props_ensure(v3d);
if (tfp->tag_for_update == false) {
return;
}
tfp->tag_for_update = false;
BMEditMesh *em = arg1;
BKE_editmesh_looptri_and_normals_calc_with_partial(em, bmpinfo);
}
/** \} */
/* Helper function to compute a median changed value,
* when the value should be clamped in [0.0, 1.0].
* Returns either 0.0, 1.0 (both can be applied directly), a positive scale factor
@ -840,6 +926,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
UI_block_align_end(block);
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
BMEditMesh *em = me->edit_mesh;
if (em != NULL) {
UI_block_interaction_set(block,
&(uiBlockInteraction_CallbackData){
.begin_fn = editmesh_partial_update_begin_fn,
.end_fn = editmesh_partial_update_end_fn,
.update_fn = editmesh_partial_update_update_fn,
.arg1 = em,
});
}
}
}
else { /* apply */
memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median));
@ -927,9 +1027,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
if (apply_vcos) {
/* TODO: use the #BKE_editmesh_looptri_and_normals_calc_with_partial
* This requires begin/end states for UI interaction (which currently aren't supported). */
BKE_editmesh_looptri_and_normals_calc(em);
/* Tell the update callback to run. */
tfp->tag_for_update = true;
}
/* Edges */