Fix #103562: preserve custom normals in BM_mesh_triangulate

`BM_mesh_triangulate` is used in exporters (when the "Triangulate"
option is ON), the `Triangulate` modifier and currently also in the
`Triangulate` geometry node (even though there are plans to change this,
see !112264)

So in practice, exporters (Alembic/FBX/OBJ/Collada) were breaking
custom normals for game pipelines (unless everything was triangulated
beforehand).

This change builds upon 93c8955a72 (uses the use
`BM_custom_loop_normals_to_vector_layer` /
`BM_custom_loop_normals_from_vector_layer` pair of calls).

In the case of the `Triangulate` modifier, this had its own try at
preserving custom normals in 7d0fcaa69a  -- doing very similar
things but as an option -- this is now removed (so it is always done,
which fits into "interpolate custom data if it's there" design that we have
nowadays).

NOTE: the "Triangulate Faces" operator already did the same
Pull Request: https://projects.blender.org/blender/blender/pulls/121871
This commit is contained in:
Philipp Oeser
2024-05-23 17:33:40 +02:00
committed by Philipp Oeser
parent f968c99850
commit f3c32a36bc
5 changed files with 6 additions and 33 deletions

View File

@@ -90,6 +90,8 @@ void BM_mesh_triangulate(BMesh *bm,
MemArena *pf_arena;
Heap *pf_heap;
BM_custom_loop_normals_to_vector_layer(bm);
pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
@@ -150,6 +152,8 @@ void BM_mesh_triangulate(BMesh *bm,
BLI_memarena_free(pf_arena);
BM_custom_loop_normals_from_vector_layer(bm, false);
if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
BLI_heap_free(pf_heap, nullptr);
}

View File

@@ -5500,8 +5500,6 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
BMOIter oiter;
BMFace *f;
BM_custom_loop_normals_to_vector_layer(em->bm);
EDBM_op_init(em,
&bmop,
op,
@@ -5526,8 +5524,6 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
continue;
}
BM_custom_loop_normals_from_vector_layer(em->bm, false);
EDBMUpdate_Params params{};
params.calc_looptris = true;
params.calc_normals = false;

View File

@@ -1898,12 +1898,11 @@ typedef struct TriangulateModifierData {
} TriangulateModifierData;
/** #TriangulateModifierData.flag */
enum {
#ifdef DNA_DEPRECATED_ALLOW
enum {
MOD_TRIANGULATE_BEAUTY = (1 << 0), /* deprecated */
#endif
MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS = 1 << 1,
};
#endif
/** #TriangulateModifierData.ngon_method triangulate method (N-gons). */
enum {

View File

@@ -6597,16 +6597,6 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
"Triangulate only polygons with vertex count greater than or equal to this number");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "keep_custom_normals", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS);
RNA_def_property_ui_text(
prop,
"Keep Normals",
"Try to preserve custom normals.\n"
"Warning: Depending on chosen triangulation method, "
"shading may not be fully preserved, \"Fixed\" method usually gives the best result here");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
RNA_define_lib_overridable(false);
}

View File

@@ -43,15 +43,6 @@ static Mesh *triangulate_mesh(Mesh *mesh,
cd_mask_extra.emask = CD_MASK_ORIGINDEX;
cd_mask_extra.pmask = CD_MASK_ORIGINDEX;
bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0;
if (keep_clnors) {
void *data = CustomData_add_layer(
&mesh->corner_data, CD_NORMAL, CD_CONSTRUCT, mesh->corners_num);
memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes());
cd_mask_extra.lmask |= CD_MASK_NORMAL;
}
BMeshCreateParams bmesh_create_params{};
BMeshFromMeshParams bmesh_from_mesh_params{};
bmesh_from_mesh_params.calc_face_normal = true;
@@ -66,13 +57,6 @@ static Mesh *triangulate_mesh(Mesh *mesh,
result = BKE_mesh_from_bmesh_for_eval_nomain(bm, &cd_mask_extra, mesh);
BM_mesh_free(bm);
if (keep_clnors) {
float(*corner_normals)[3] = static_cast<float(*)[3]>(
CustomData_get_layer_for_write(&result->corner_data, CD_NORMAL, result->corners_num));
BKE_mesh_set_custom_normals(result, corner_normals);
CustomData_free_layers(&result->corner_data, CD_NORMAL, result->corners_num);
}
return result;
}