Fix T75574: Instant crash: averaging custom normals on model.
Fairly critical code mistake actually, since it uses malloca, BLI_smallstack should *never* be declared inside a loop... Also optimized handling of the `loop_weight` heapsimple, we can also only create and use a single one for all edited objects... Found two other operators potentially affected by same issue (split normals, and weld edges into faces).
This commit is contained in:
parent
c7f74863dd
commit
2b5e301ea4
Notes:
blender-bot
2023-02-14 06:45:14 +01:00
Referenced by issue #75574, Instant crash: averaging custom normals on model with over 32k faces on windows
|
@ -704,6 +704,8 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
BMEdge *e;
|
||||
BMIter iter;
|
||||
|
||||
BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
|
||||
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
uint objects_len = 0;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
|
@ -717,8 +719,6 @@ static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
continue;
|
||||
}
|
||||
|
||||
BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
|
||||
|
||||
{
|
||||
BMVert *v;
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
|
|
|
@ -8312,6 +8312,8 @@ static void normals_merge(BMesh *bm, BMLoopNorEditDataArray *lnors_ed_arr)
|
|||
BM_normals_loops_edges_tag(bm, false);
|
||||
|
||||
for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
|
||||
BLI_assert(BLI_SMALLSTACK_IS_EMPTY(clnors));
|
||||
|
||||
if (BM_elem_flag_test(lnor_ed->loop, BM_ELEM_TAG)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -8354,8 +8356,12 @@ static void normals_split(BMesh *bm)
|
|||
|
||||
BM_normals_loops_edges_tag(bm, true);
|
||||
|
||||
BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
|
||||
|
||||
const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
|
||||
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
|
||||
BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
|
||||
|
||||
l_curr = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
|
||||
|
@ -8377,7 +8383,6 @@ static void normals_split(BMesh *bm)
|
|||
|
||||
lfan_pivot = l_curr;
|
||||
e_next = lfan_pivot->e;
|
||||
BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
|
||||
float avg_normal[3] = {0.0f};
|
||||
|
||||
while (true) {
|
||||
|
@ -8389,7 +8394,7 @@ static void normals_split(BMesh *bm)
|
|||
e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
|
||||
}
|
||||
|
||||
BLI_SMALLSTACK_PUSH(loops, lfan_pivot);
|
||||
BLI_SMALLSTACK_PUSH(loop_stack, lfan_pivot);
|
||||
add_v3_v3(avg_normal, lfan_pivot->f->no);
|
||||
|
||||
if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
|
||||
|
@ -8401,7 +8406,7 @@ static void normals_split(BMesh *bm)
|
|||
/* If avg normal is nearly 0, set clnor to default value. */
|
||||
zero_v3(avg_normal);
|
||||
}
|
||||
while ((l = BLI_SMALLSTACK_POP(loops))) {
|
||||
while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
|
||||
const int l_index = BM_elem_index_get(l);
|
||||
short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
|
||||
BKE_lnor_space_custom_normal_to_data(
|
||||
|
@ -8543,7 +8548,13 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
|
|||
const float absweight = (float)RNA_int_get(op->ptr, "weight");
|
||||
const float threshold = RNA_float_get(op->ptr, "threshold");
|
||||
|
||||
HeapSimple *loop_weight = BLI_heapsimple_new();
|
||||
BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
|
||||
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
|
||||
BLI_assert(BLI_heapsimple_is_empty(loop_weight));
|
||||
|
||||
Object *obedit = objects[ob_index];
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
BMesh *bm = em->bm;
|
||||
|
@ -8570,8 +8581,6 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
|
|||
|
||||
BM_normals_loops_edges_tag(bm, true);
|
||||
|
||||
HeapSimple *loop_weight = BLI_heapsimple_new();
|
||||
|
||||
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
|
||||
l_curr = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
|
@ -8621,7 +8630,6 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
|
|||
lfan_pivot = lfan_pivot_next;
|
||||
}
|
||||
|
||||
BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
|
||||
float wnor[3], avg_normal[3] = {0.0f}, count = 0;
|
||||
float val = BLI_heapsimple_top_value(loop_weight);
|
||||
|
||||
|
@ -8632,7 +8640,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
|
|||
val = cur_val;
|
||||
}
|
||||
l = BLI_heapsimple_pop_min(loop_weight);
|
||||
BLI_SMALLSTACK_PUSH(loops, l);
|
||||
BLI_SMALLSTACK_PUSH(loop_stack, l);
|
||||
|
||||
const float n_weight = pow(weight, count);
|
||||
|
||||
|
@ -8653,7 +8661,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
|
|||
/* If avg normal is nearly 0, set clnor to default value. */
|
||||
zero_v3(avg_normal);
|
||||
}
|
||||
while ((l = BLI_SMALLSTACK_POP(loops))) {
|
||||
while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
|
||||
const int l_index = BM_elem_index_get(l);
|
||||
short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
|
||||
BKE_lnor_space_custom_normal_to_data(
|
||||
|
@ -8664,10 +8672,11 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
|
|||
} while ((l_curr = l_curr->next) != l_first);
|
||||
}
|
||||
|
||||
BLI_heapsimple_free(loop_weight, NULL);
|
||||
EDBM_update_generic(obedit->data, true, false);
|
||||
}
|
||||
|
||||
BLI_heapsimple_free(loop_weight, NULL);
|
||||
|
||||
MEM_freeN(objects);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue