From 172a976273f0e7144eed60c19c3e72357c74b0f6 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 11 Nov 2022 18:44:37 -0600 Subject: [PATCH 01/85] Mesh: Start refactor of lazy face corner normals --- source/blender/blenkernel/BKE_mesh.h | 7 +- source/blender/blenkernel/BKE_mesh_types.h | 2 + .../blender/blenkernel/intern/DerivedMesh.cc | 17 +--- .../blender/blenkernel/intern/data_transfer.c | 64 +-------------- source/blender/blenkernel/intern/mesh.cc | 18 ---- .../blenkernel/intern/mesh_iterators.cc | 6 +- .../blender/blenkernel/intern/mesh_normals.cc | 82 +++++++++++++++++++ source/blender/blenkernel/intern/mesh_remap.c | 42 ++-------- .../blender/blenkernel/intern/mesh_tangent.cc | 12 +-- .../blender/blenkernel/intern/mesh_wrapper.cc | 9 +- .../blender/blenkernel/intern/shrinkwrap.cc | 2 +- .../extract_mesh_vbo_pos_nor.cc | 4 +- .../editors/sculpt_paint/curves_sculpt_add.cc | 9 +- .../sculpt_paint/curves_sculpt_density.cc | 6 +- .../sculpt_paint/curves_sculpt_puff.cc | 5 +- .../sculpt_paint/curves_sculpt_slide.cc | 5 +- .../blender_interface/BlenderFileLoader.cpp | 8 +- .../io/alembic/exporter/abc_writer_mesh.cc | 4 +- .../blender/io/collada/GeometryExporter.cpp | 11 +-- .../blender/io/usd/intern/usd_writer_mesh.cc | 3 +- .../wavefront_obj/exporter/obj_export_mesh.cc | 9 +- .../wavefront_obj/exporter/obj_export_mesh.hh | 1 - .../wavefront_obj/tests/obj_importer_tests.cc | 2 +- source/blender/makesrna/intern/rna_mesh.c | 44 +++------- source/blender/makesrna/intern/rna_mesh_api.c | 15 +--- .../blender/modifiers/intern/MOD_displace.c | 6 +- .../blender/modifiers/intern/MOD_multires.cc | 13 ++- .../blender/modifiers/intern/MOD_subsurf.cc | 13 ++- .../modifiers/intern/MOD_triangulate.c | 18 ++-- .../node_geo_deform_curves_on_surface.cc | 15 ++-- source/blender/render/intern/bake.c | 4 +- source/blender/render/intern/multires_bake.c | 3 +- 32 files changed, 168 insertions(+), 291 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 8f6786d4113..30e39749df4 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -372,6 +372,8 @@ const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]; */ const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]; +const float (*BKE_mesh_corner_normals_ensure(const struct Mesh *mesh))[3]; + /** * Tag mesh vertex and face normals to be recalculated when/if they are needed later. * @@ -434,6 +436,8 @@ void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh); */ void BKE_mesh_poly_normals_clear_dirty(struct Mesh *mesh); +void BKE_mesh_corner_normals_clear_dirty(struct Mesh *mesh); + /** * Return true if the mesh vertex normals either are not stored or are dirty. * This can be used to help decide whether to transfer them when copying a mesh. @@ -446,6 +450,8 @@ bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh); */ bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh); +bool BKE_mesh_corner_normals_are_dirty(const struct Mesh *mesh); + /** * Calculate face normals directly into a result array. * @@ -690,7 +696,6 @@ void BKE_mesh_normals_loop_to_vertex(int numVerts, */ bool BKE_mesh_has_custom_loop_normals(struct Mesh *me); -void BKE_mesh_calc_normals_split(struct Mesh *mesh); /** * Compute 'split' (aka loop, or per face corner's) normals. * diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index 80f61086052..65d1e0fcb13 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -141,8 +141,10 @@ struct MeshRuntime { */ bool vert_normals_dirty = false; bool poly_normals_dirty = false; + bool corner_normals_dirty = false; float (*vert_normals)[3] = nullptr; float (*poly_normals)[3] = nullptr; + float (*corner_normals)[3] = nullptr; /** * A #BLI_bitmap containing tags for the center vertices of subdivided polygons, set by the diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index bfdfc447baf..a7e398adcfa 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -547,7 +547,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, /* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case * of deferred CPU subdivision, this will be computed when the wrapper is generated. */ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { - BKE_mesh_calc_normals_split(mesh_final); + BKE_mesh_corner_normals_ensure(mesh_final); } } else { @@ -560,12 +560,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, BKE_mesh_ensure_normals_for_display(mesh_final); } - /* Some modifiers, like data-transfer, may generate those data as temp layer, - * we do not want to keep them, as they are used by display code when available - * (i.e. even if auto-smooth is disabled). */ - if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) { - CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop); - } + } } @@ -1216,18 +1211,12 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, /* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the * wrapper is generated. */ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { - BKE_mesh_calc_normals_split(mesh_final); + BKE_mesh_corner_normals_ensure(mesh_final); } } else { /* Same as mesh_calc_modifiers. If using loop normals, poly nors have already been computed. */ BKE_mesh_ensure_normals_for_display(mesh_final); - - /* Some modifiers, like data-transfer, may generate those data, we do not want to keep them, - * as they are used by display code when available (i.e. even if autosmooth is disabled). */ - if (CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)) { - CustomData_free_layers(&mesh_final->ldata, CD_NORMAL, mesh_final->totloop); - } } } diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index e6afca11b40..b5ad92c2705 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -247,65 +247,6 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type) /* ********** */ -/* Generic pre/post processing, only used by custom loop normals currently. */ - -static void data_transfer_dtdata_type_preprocess(Mesh *me_src, - Mesh *me_dst, - const int dtdata_type, - const bool dirty_nors_dst) -{ - if (dtdata_type == DT_TYPE_LNOR) { - /* Compute custom normals into regular loop normals, which will be used for the transfer. */ - - const MVert *verts_dst = BKE_mesh_verts(me_dst); - const int num_verts_dst = me_dst->totvert; - const MEdge *edges_dst = BKE_mesh_edges(me_dst); - const int num_edges_dst = me_dst->totedge; - const MPoly *polys_dst = BKE_mesh_polys(me_dst); - const int num_polys_dst = me_dst->totpoly; - const MLoop *loops_dst = BKE_mesh_loops(me_dst); - const int num_loops_dst = me_dst->totloop; - CustomData *ldata_dst = &me_dst->ldata; - - const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0; - const float split_angle_dst = me_dst->smoothresh; - - /* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */ - BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != NULL); - (void)me_src; - - float(*loop_nors_dst)[3]; - short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); - - /* Cache loop nors into a temp CDLayer. */ - loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL); - const bool do_loop_nors_dst = (loop_nors_dst == NULL); - if (do_loop_nors_dst) { - loop_nors_dst = CustomData_add_layer( - ldata_dst, CD_NORMAL, CD_SET_DEFAULT, NULL, num_loops_dst); - CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); - } - if (dirty_nors_dst || do_loop_nors_dst) { - BKE_mesh_normals_loop_split(verts_dst, - BKE_mesh_vertex_normals_ensure(me_dst), - num_verts_dst, - edges_dst, - num_edges_dst, - loops_dst, - loop_nors_dst, - num_loops_dst, - polys_dst, - BKE_mesh_poly_normals_ensure(me_dst), - num_polys_dst, - use_split_nors_dst, - split_angle_dst, - NULL, - custom_nors_dst, - NULL); - } - } -} - static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src), Object *UNUSED(ob_dst), Mesh *UNUSED(me_src), @@ -330,7 +271,6 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src), CustomData *ldata_dst = &me_dst->ldata; const float(*poly_nors_dst)[3] = BKE_mesh_poly_normals_ensure(me_dst); - float(*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL); short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); if (!custom_nors_dst) { @@ -345,7 +285,7 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src), edges_dst, num_edges_dst, loops_dst, - loop_nors_dst, + BKE_mesh_corner_normals_ensure(me_dst), num_loops_dst, polys_dst, poly_nors_dst, @@ -1323,8 +1263,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, continue; } - data_transfer_dtdata_type_preprocess(me_src, me_dst, dtdata_type, dirty_nors_dst); - cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 2d613f24a0a..5b5d504a743 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1567,20 +1567,6 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys) } } - /* don't update normals, caller can do this explicitly. - * We do update loop normals though, those may not be auto-generated - * (see e.g. STL import script)! */ - float(*lnors)[3] = (float(*)[3])CustomData_duplicate_referenced_layer( - &me->ldata, CD_NORMAL, me->totloop); - if (lnors) { - float m3[3][3]; - - copy_m3_m4(m3, mat); - normalize_m3(m3); - for (int i = 0; i < me->totloop; i++, lnors++) { - mul_m3_v3(m3, *lnors); - } - } BKE_mesh_tag_coords_changed(me); } @@ -1836,10 +1822,6 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, BKE_mesh_assert_normals_dirty_or_calculated(mesh); } -void BKE_mesh_calc_normals_split(Mesh *mesh) -{ - BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh)); -} /* Split faces helper functions. */ diff --git a/source/blender/blenkernel/intern/mesh_iterators.cc b/source/blender/blenkernel/intern/mesh_iterators.cc index a99e9b2348d..4ec97caaa29 100644 --- a/source/blender/blenkernel/intern/mesh_iterators.cc +++ b/source/blender/blenkernel/intern/mesh_iterators.cc @@ -164,8 +164,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, /* XXX: investigate using EditMesh data. */ const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? - static_cast( - CustomData_get_layer(&mesh->ldata, CD_NORMAL)) : + BKE_mesh_corner_normals_ensure(mesh) : nullptr; int f_idx; @@ -186,8 +185,7 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, } else { const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? - static_cast( - CustomData_get_layer(&mesh->ldata, CD_NORMAL)) : + BKE_mesh_corner_normals_ensure(mesh) : nullptr; const MVert *mv = BKE_mesh_verts(mesh); diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index ebb5a72d137..4f4cf4a5d99 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -123,6 +123,18 @@ float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3] return mesh->runtime->poly_normals; } +float (*BKE_mesh_corner_normals_for_write(Mesh *mesh))[3] +{ + if (mesh->runtime->corner_normals == nullptr) { + mesh->runtime->corner_normals = (float(*)[3])MEM_malloc_arrayN( + mesh->totloop, sizeof(float[3]), __func__); + } + + BLI_assert(MEM_allocN_len(mesh->runtime->corner_normals) >= sizeof(float[3]) * mesh->totloop); + + return mesh->runtime->corner_normals; +} + void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh) { mesh->runtime->vert_normals_dirty = false; @@ -135,6 +147,12 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh) BKE_mesh_assert_normals_dirty_or_calculated(mesh); } +void BKE_mesh_corner_normals_clear_dirty(Mesh *mesh) +{ + mesh->runtime->corner_normals_dirty = false; + BKE_mesh_assert_normals_dirty_or_calculated(mesh); +} + bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh) { return mesh->runtime->vert_normals_dirty; @@ -145,13 +163,20 @@ bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh) return mesh->runtime->poly_normals_dirty; } +bool BKE_mesh_corner_normals_are_dirty(const Mesh *mesh) +{ + return mesh->runtime->corner_normals_dirty; +} + void BKE_mesh_clear_derived_normals(Mesh *mesh) { MEM_SAFE_FREE(mesh->runtime->vert_normals); MEM_SAFE_FREE(mesh->runtime->poly_normals); + MEM_SAFE_FREE(mesh->runtime->corner_normals); mesh->runtime->vert_normals_dirty = true; mesh->runtime->poly_normals_dirty = true; + mesh->runtime->corner_normals_dirty = true; } void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh) @@ -162,6 +187,9 @@ void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh) if (!mesh->runtime->poly_normals_dirty) { BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0); } + if (!mesh->runtime->corner_normals_dirty) { + BLI_assert(mesh->runtime->corner_normals || mesh->totloop == 0); + } } /** \} */ @@ -433,6 +461,60 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3] return poly_normals; } +const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] +{ + if (!BKE_mesh_corner_normals_are_dirty(mesh)) { + BLI_assert(mesh->runtime->corner_normals != nullptr || mesh->totcorner == 0); + return mesh->runtime->corner_normals; + } + + if (mesh->totpoly == 0) { + return nullptr; + } + + const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh); + const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(mesh); + + std::lock_guard lock{mesh->runtime->normals_mutex}; + if (!BKE_mesh_corner_normals_are_dirty(mesh)) { + BLI_assert(mesh->runtime->corner_normals != nullptr); + return mesh->runtime->corner_normals; + } + + float(*corner_normals)[3]; + + /* Isolate task because a mutex is locked and computing normals is multi-threaded. */ + blender::threading::isolate_task([&]() { + Mesh &mesh_mutable = *const_cast(mesh); + const Span verts = mesh_mutable.verts(); + const Span edges = mesh_mutable.edges(); + const Span polys = mesh_mutable.polys(); + const Span loops = mesh_mutable.loops(); + + corner_normals = BKE_mesh_corner_normals_for_write(&mesh_mutable); + const short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); + + BKE_mesh_normals_loop_split(verts.data(), + vert_normals, + verts.size(), + edges.data(), + edges.size(), + loops.data(), + corner_normals, + loops.size(), + polys.data(), + poly_normals, + polys.size(), + use_split_normals, + split_angle, + r_lnors_spacearr, + clnors, + nullptr); + + BKE_mesh_corner_normals_clear_dirty(&mesh_mutable); + }); +} + void BKE_mesh_ensure_normals_for_display(Mesh *mesh) { switch (mesh->runtime->wrapper_type) { diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index 90798ea593d..6bf5151c59d 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1347,43 +1347,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, poly_nors_dst = BKE_mesh_poly_normals_ensure(mesh_dst); } if (need_lnors_dst) { - short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); - - /* Cache loop normals into a temporary custom data layer. */ - loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL); - const bool do_loop_nors_dst = (loop_nors_dst == NULL); - if (!loop_nors_dst) { - loop_nors_dst = CustomData_add_layer( - ldata_dst, CD_NORMAL, CD_SET_DEFAULT, NULL, numloops_dst); - CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); - } - if (dirty_nors_dst || do_loop_nors_dst) { - BKE_mesh_normals_loop_split(verts_dst, - BKE_mesh_vertex_normals_ensure(mesh_dst), - numverts_dst, - edges_dst, - numedges_dst, - loops_dst, - loop_nors_dst, - numloops_dst, - polys_dst, - poly_nors_dst, - numpolys_dst, - use_split_nors_dst, - split_angle_dst, - NULL, - custom_nors_dst, - NULL); - } + loop_nors_dst = BKE_mesh_corner_normals_ensure(mesh_dst); } - if (need_pnors_src || need_lnors_src) { - if (need_pnors_src) { - poly_nors_src = BKE_mesh_poly_normals_ensure(me_src); - } - if (need_lnors_src) { - loop_nors_src = CustomData_get_layer(&me_src->ldata, CD_NORMAL); - BLI_assert(loop_nors_src != NULL); - } + if (need_pnors_src) { + poly_nors_src = BKE_mesh_poly_normals_ensure(me_src); + } + if (need_lnors_src) { + loop_nors_src = BKE_mesh_corner_normals_ensure(me_src); } } diff --git a/source/blender/blenkernel/intern/mesh_tangent.cc b/source/blender/blenkernel/intern/mesh_tangent.cc index 49ea23a1552..2c80ff1e2d5 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.cc +++ b/source/blender/blenkernel/intern/mesh_tangent.cc @@ -133,19 +133,11 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, return; } - const float(*loopnors)[3] = static_cast( - CustomData_get_layer(&mesh->ldata, CD_NORMAL)); - if (!loopnors) { - BKE_report( - reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting"); - return; - } - BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_verts(mesh), mesh->totvert, BKE_mesh_loops(mesh), r_looptangents, - loopnors, + BKE_mesh_corner_normals_ensure(mesh), loopuvs, mesh->totloop, BKE_mesh_polys(mesh), @@ -585,7 +577,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval, tangent_names_len, BKE_mesh_vertex_normals_ensure(me_eval), BKE_mesh_poly_normals_ensure(me_eval), - static_cast(CustomData_get_layer(&me_eval->ldata, CD_NORMAL)), + BKE_mesh_corner_normals_ensure(me_eval), /* may be nullptr */ static_cast(CustomData_get_layer(&me_eval->vdata, CD_ORCO)), /* result */ diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index 61a95fb4d0e..feb883fb866 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -331,22 +331,17 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me) if (use_clnors) { /* If custom normals are present and the option is turned on calculate the split * normals and clear flag so the normals get interpolated to the result mesh. */ - BKE_mesh_calc_normals_split(me); CustomData_clear_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me); if (use_clnors) { - float(*lnors)[3] = static_cast( - CustomData_get_layer(&subdiv_mesh->ldata, CD_NORMAL)); - BLI_assert(lnors != nullptr); + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(subdiv_mesh); BKE_mesh_set_custom_normals(subdiv_mesh, lnors); - CustomData_set_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - CustomData_set_layer_flag(&subdiv_mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } else if (runtime_data->calc_loop_normals) { - BKE_mesh_calc_normals_split(subdiv_mesh); + BKE_mesh_corner_normals_ensure(subdiv_mesh); } if (subdiv != runtime_data->subdiv) { diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index 65226a5db9d..568e5b305ba 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -135,7 +135,7 @@ bool BKE_shrinkwrap_init_tree( if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) { data->pnors = BKE_mesh_poly_normals_ensure(mesh); if ((mesh->flag & ME_AUTOSMOOTH) != 0) { - data->clnors = static_cast(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); + data->clnors = BKE_mesh_corner_normals_ensure(mesh); } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index 30b4f808487..01660df18e4 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -235,9 +235,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache, if (subdiv_cache->use_custom_loop_normals) { Mesh *coarse_mesh = subdiv_cache->mesh; - const float(*lnors)[3] = static_cast( - CustomData_get_layer(&coarse_mesh->ldata, CD_NORMAL)); - BLI_assert(lnors != nullptr); + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(coarse_mesh); GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc(); GPU_vertbuf_init_with_format(src_custom_normals, get_custom_normals_format()); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index 0d2c2d3f0c9..e2c916e3783 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -127,7 +127,7 @@ struct AddOperationExecutor { transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface); Object &surface_ob_orig = *curves_id_orig_->surface; - Mesh &surface_orig = *static_cast(surface_ob_orig.data); + const Mesh &surface_orig = *static_cast(surface_ob_orig.data); if (surface_orig.totpoly == 0) { report_empty_original_surface(stroke_extension.reports); return; @@ -206,13 +206,8 @@ struct AddOperationExecutor { } const Span surface_looptris_orig = surface_orig.looptris(); - - /* Find normals. */ - if (!CustomData_has_layer(&surface_orig.ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(&surface_orig); - } const Span corner_normals_su = { - reinterpret_cast(CustomData_get_layer(&surface_orig.ldata, CD_NORMAL)), + reinterpret_cast(BKE_mesh_corner_normals_ensure(&surface_orig)), surface_orig.totloop}; const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig}; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc index 78e2d55e6b9..ddaa5408f40 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc @@ -256,12 +256,8 @@ struct DensityAddOperationExecutor { } self_->new_deformed_root_positions_.extend(new_positions_cu); - /* Find normals. */ - if (!CustomData_has_layer(&surface_orig_->ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(surface_orig_); - } const Span corner_normals_su = { - reinterpret_cast(CustomData_get_layer(&surface_orig_->ldata, CD_NORMAL)), + reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_orig_)), surface_orig_->totloop}; const Span surface_looptris_orig = surface_orig_->looptris(); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index b4e949106e7..cab42edba7f 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -112,11 +112,8 @@ struct PuffOperationExecutor { transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_); - if (!CustomData_has_layer(&surface_->ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(surface_); - } corner_normals_su_ = { - reinterpret_cast(CustomData_get_layer(&surface_->ldata, CD_NORMAL)), + reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_)), surface_->totloop}; surface_verts_ = surface_->verts(); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc index ae89bc1c58b..95af6b61609 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc @@ -177,11 +177,8 @@ struct SlideOperationExecutor { report_missing_uv_map_on_original_surface(stroke_extension.reports); return; } - if (!CustomData_has_layer(&surface_orig_->ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(surface_orig_); - } corner_normals_orig_su_ = { - reinterpret_cast(CustomData_get_layer(&surface_orig_->ldata, CD_NORMAL)), + reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_orig_)), surface_orig_->totloop}; surface_ob_eval_ = DEG_get_evaluated_object(ctx_.depsgraph, surface_ob_orig_); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 53c2b1d235b..2664a0c05a0 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -412,12 +412,8 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) mesh_loops.data(), mesh_polys.data(), mesh_verts.data(), me->totloop, me->totpoly, mlooptri); // Compute loop normals - BKE_mesh_calc_normals_split(me); - const float(*lnors)[3] = nullptr; - - if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { - lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); - } + /* TODO: Only retrieve loop normals when necessary. */ + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me); // Get other mesh data const FreestyleEdge *fed = (FreestyleEdge *)CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE); diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 084d26198bc..35538a7b8a8 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -534,9 +534,7 @@ static void get_loop_normals(struct Mesh *mesh, return; } - BKE_mesh_calc_normals_split(mesh); - const float(*lnors)[3] = static_cast(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); - BLI_assert_msg(lnors != nullptr, "BKE_mesh_calc_normals_split() should have computed CD_NORMAL"); + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh); normals.resize(mesh->totloop); diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index f6f9026481c..0cc96dca51a 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -619,14 +619,9 @@ void GeometryExporter::create_normals(std::vector &normals, const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me); const Span polys = me->polys(); const Span loops = me->loops(); - const float(*lnors)[3] = nullptr; - bool use_custom_normals = false; - - BKE_mesh_calc_normals_split(me); - if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { - lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); - use_custom_normals = true; - } + /* TODO: Only retrieve when necessary. */ + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me); + bool use_custom_normals = true; for (const int poly_index : polys.index_range()) { const MPoly *mpoly = &polys[poly_index]; diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index e7d79e888e4..3bba59dfb81 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -398,7 +398,8 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context, void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh) { pxr::UsdTimeCode timecode = get_export_time_code(); - const float(*lnors)[3] = static_cast(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); + /* TODO: Only when necessary. */ + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh); const Span polys = mesh->polys(); const Span loops = mesh->loops(); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index a95f917869b..32357edad28 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -176,11 +176,6 @@ int OBJMesh::ith_smooth_group(const int poly_index) const return poly_smooth_groups_[poly_index]; } -void OBJMesh::ensure_mesh_normals() const -{ - BKE_mesh_calc_normals_split(export_mesh_eval_); -} - void OBJMesh::ensure_mesh_edges() const { BKE_mesh_calc_edges_loose(export_mesh_eval_); @@ -397,8 +392,8 @@ void OBJMesh::store_normal_coords_and_indices() normal_to_index.reserve(export_mesh_eval_->totpoly); loop_to_normal_index_.resize(export_mesh_eval_->totloop); loop_to_normal_index_.fill(-1); - const float(*lnors)[3] = static_cast( - CustomData_get_layer(&export_mesh_eval_->ldata, CD_NORMAL)); + /* TODO: Only get loop normals when they're necessary. */ + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(export_mesh_eval_); for (int poly_index = 0; poly_index < export_mesh_eval_->totpoly; ++poly_index) { const MPoly &mpoly = polys[poly_index]; bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh index 89ee6f4dea2..eca711e7373 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh @@ -131,7 +131,6 @@ class OBJMesh : NonCopyable { */ const Material *get_object_material(int16_t mat_nr) const; - void ensure_mesh_normals() const; void ensure_mesh_edges() const; /** diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index f459e1ab1bd..2225fb6b9bb 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -104,7 +104,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest { const Span verts = mesh->verts(); EXPECT_V3_NEAR(verts.first().co, exp.vert_first, 0.0001f); EXPECT_V3_NEAR(verts.last().co, exp.vert_last, 0.0001f); - const float3 *lnors = (const float3 *)CustomData_get_layer(&mesh->ldata, CD_NORMAL); + const float3 *lnors = (const float3 *)BKE_mesh_corner_normals_ensure(mesh); float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0); EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f); const MLoopUV *mloopuv = static_cast( diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index f13132b5b7c..a508e351aef 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -554,25 +554,8 @@ static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); - const float(*vec)[3] = CustomData_get(&me->ldata, index, CD_NORMAL); - - if (!vec) { - zero_v3(values); - } - else { - copy_v3_v3(values, (const float *)vec); - } -} - -static void rna_MeshLoop_normal_set(PointerRNA *ptr, const float *values) -{ - Mesh *me = rna_mesh(ptr); - const int index = rna_MeshLoop_index_get(ptr); - float(*vec)[3] = CustomData_get(&me->ldata, index, CD_NORMAL); - - if (vec) { - normalize_v3_v3(*vec, values); - } + const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); + copy_v3_v3(values, loop_normals[index]); } static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values) @@ -602,7 +585,8 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); - const float(*nor)[3] = CustomData_get(&me->ldata, index, CD_NORMAL); + const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); + const float(*nor)[3] = loop_normals[index]; const float(*vec)[4] = CustomData_get(&me->ldata, index, CD_MLOOPTANGENT); if (nor && vec) { @@ -745,19 +729,11 @@ static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values) static void rna_MeshLoopTriangle_split_normals_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); - const float(*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL); - - if (!lnors) { - zero_v3(values + 0); - zero_v3(values + 3); - zero_v3(values + 6); - } - else { - MLoopTri *lt = (MLoopTri *)ptr->data; - copy_v3_v3(values + 0, lnors[lt->tri[0]]); - copy_v3_v3(values + 3, lnors[lt->tri[1]]); - copy_v3_v3(values + 6, lnors[lt->tri[2]]); - } + const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); + const MLoopTri *lt = (const MLoopTri *)ptr->data; + copy_v3_v3(values + 0, loop_normals[lt->tri[0]]); + copy_v3_v3(values + 3, loop_normals[lt->tri[1]]); + copy_v3_v3(values + 6, loop_normals[lt->tri[2]]); } static float rna_MeshLoopTriangle_area_get(PointerRNA *ptr) @@ -2453,7 +2429,7 @@ static void rna_def_mloop(BlenderRNA *brna) prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", "rna_MeshLoop_normal_set", NULL); + RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", NULL, NULL); RNA_def_property_ui_text( prop, "Normal", diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 6b1df3fc4d4..fb1a3fa4296 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -44,15 +44,13 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, static void rna_Mesh_create_normals_split(Mesh *mesh) { - if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { - CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_SET_DEFAULT, NULL, mesh->totloop); - CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - } + /* TODO: Proper deprecation. */ } static void rna_Mesh_free_normals_split(Mesh *mesh) { - CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop); + /* TODO: Deprecation? */ + BKE_mesh_clear_derived_normals(mesh); } static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap) @@ -69,11 +67,6 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char * CustomData_set_layer_flag(&mesh->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY); } - /* Compute loop normals if needed. */ - if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(mesh); - } - BKE_mesh_calc_loop_tangent_single(mesh, uvmap, r_looptangents, reports); } @@ -226,7 +219,7 @@ void RNA_api_mesh(StructRNA *srna) func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split"); RNA_def_function_ui_description(func, "Empty split vertex normals"); - func = RNA_def_function(srna, "calc_normals_split", "BKE_mesh_calc_normals_split"); + func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_create_normals_split"); RNA_def_function_ui_description(func, "Calculate split vertex normals, which preserve sharp edges"); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index fc12a9c2aad..a8d10d6ccb4 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -307,11 +307,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, CustomData *ldata = &mesh->ldata; if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) { - if (!CustomData_has_layer(ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(mesh); - } - - float(*clnors)[3] = CustomData_get_layer(ldata, CD_NORMAL); + const float(*clnors)[3] = BKE_mesh_corner_normals_ensure(mesh); vert_clnors = MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__); BKE_mesh_normals_loop_to_vertex( verts_num, BKE_mesh_loops(mesh), mesh->totloop, (const float(*)[3])clnors, vert_clnors); diff --git a/source/blender/modifiers/intern/MOD_multires.cc b/source/blender/modifiers/intern/MOD_multires.cc index 2bc3763c46b..a56598d67c6 100644 --- a/source/blender/modifiers/intern/MOD_multires.cc +++ b/source/blender/modifiers/intern/MOD_multires.cc @@ -252,20 +252,19 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } else { if (use_clnors) { - /* If custom normals are present and the option is turned on calculate the split - * normals and clear flag so the normals get interpolated to the result mesh. */ - BKE_mesh_calc_normals_split(mesh); - CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + CustomData_add_layer(&mesh->ldata, + CD_NORMAL, + CD_DUPLICATE, + const_cast(BKE_mesh_corner_normals_ensure(mesh)), + mesh->totloop); } result = multires_as_mesh(mmd, ctx, mesh, subdiv); if (use_clnors) { float(*lnors)[3] = static_cast(CustomData_get_layer(&result->ldata, CD_NORMAL)); - BLI_assert(lnors != nullptr); BKE_mesh_set_custom_normals(result, lnors); - CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop); } // BKE_subdiv_stats_print(&subdiv->stats); if (subdiv != runtime_data->subdiv) { diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index 5e77f0ffa9e..70efb407fbb 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -250,10 +250,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh); if (use_clnors) { - /* If custom normals are present and the option is turned on calculate the split - * normals and clear flag so the normals get interpolated to the result mesh. */ - BKE_mesh_calc_normals_split(mesh); - CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + CustomData_add_layer(&mesh->ldata, + CD_NORMAL, + CD_DUPLICATE, + const_cast(BKE_mesh_corner_normals_ensure(mesh)), + mesh->totloop); } /* TODO(sergey): Decide whether we ever want to use CCG for subsurf, * maybe when it is a last modifier in the stack? */ @@ -266,10 +267,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (use_clnors) { float(*lnors)[3] = static_cast(CustomData_get_layer(&result->ldata, CD_NORMAL)); - BLI_assert(lnors != nullptr); BKE_mesh_set_custom_normals(result, lnors); - CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop); } // BKE_subdiv_stats_print(&subdiv->stats); if (subdiv != runtime_data->subdiv) { diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 5bae6090758..9ac9a7d86da 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -51,9 +51,11 @@ static Mesh *triangulate_mesh(Mesh *mesh, bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0; if (keep_clnors) { - BKE_mesh_calc_normals_split(mesh); - /* We need that one to 'survive' to/from BMesh conversions. */ - CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + CustomData_add_layer(&mesh->ldata, + CD_NORMAL, + CD_DUPLICATE, + (float(*)[3])BKE_mesh_corner_normals_ensure(mesh), + mesh->totloop); cd_mask_extra.lmask |= CD_MASK_NORMAL; } @@ -71,14 +73,8 @@ static Mesh *triangulate_mesh(Mesh *mesh, BM_mesh_free(bm); if (keep_clnors) { - float(*lnors)[3] = CustomData_get_layer(&result->ldata, CD_NORMAL); - BLI_assert(lnors != NULL); - - BKE_mesh_set_custom_normals(result, lnors); - - /* Do some cleanup, we do not want those temp data to stay around. */ - CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + BKE_mesh_set_custom_normals(result, CustomData_get_layer(&result->ldata, CD_NORMAL)); + CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop); } edges_num = result->totedge; diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc index dabd2a1a9f2..14594625c8d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc @@ -320,14 +320,13 @@ static void node_geo_exec(GeoNodeExecParams params) /* Retrieve face corner normals from each mesh. It's necessary to use face corner normals * because face normals or vertex normals may lose information (custom normals, auto smooth) in - * some cases. It isn't yet possible to retrieve lazily calculated face corner normals from a - * const mesh, so they are calculated here every time. */ - Array corner_normals_orig(surface_mesh_orig->totloop); - Array corner_normals_eval(surface_mesh_eval->totloop); - BKE_mesh_calc_normals_split_ex( - surface_mesh_orig, nullptr, reinterpret_cast(corner_normals_orig.data())); - BKE_mesh_calc_normals_split_ex( - surface_mesh_eval, nullptr, reinterpret_cast(corner_normals_eval.data())); + * some cases. */ + const Span corner_normals_orig( + reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_mesh_orig)), + surface_mesh_orig->totloop); + const Span corner_normals_eval( + reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_mesh_eval)), + surface_mesh_eval->totloop); std::atomic invalid_uv_count = 0; diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c index d9f7f9fa0af..082a5f18e41 100644 --- a/source/blender/render/intern/bake.c +++ b/source/blender/render/intern/bake.c @@ -482,14 +482,12 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval const TSpace *tspace = NULL; const float(*loop_normals)[3] = NULL; if (tangent) { - BKE_mesh_ensure_normals_for_display(me_eval); - BKE_mesh_calc_normals_split(me_eval); BKE_mesh_calc_loop_tangents(me_eval, true, NULL, 0); tspace = CustomData_get_layer(&me_eval->ldata, CD_TANGENT); BLI_assert(tspace); - loop_normals = CustomData_get_layer(&me_eval->ldata, CD_NORMAL); + loop_normals = BKE_mesh_corner_normals_ensure(me_eval); } const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me); diff --git a/source/blender/render/intern/multires_bake.c b/source/blender/render/intern/multires_bake.c index cfb91e86ad9..2cde17f46fa 100644 --- a/source/blender/render/intern/multires_bake.c +++ b/source/blender/render/intern/multires_bake.c @@ -499,6 +499,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, temp_mesh->totloop * sizeof(MLoop)); const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(temp_mesh); const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(temp_mesh); + const float(*corner_normals)[3] = BKE_mesh_corner_normals_ensure(temp_mesh); if (require_tangent) { if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { @@ -515,7 +516,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, 0, vert_normals, poly_normals, - (const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL), + corner_normals, (const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */ /* result */ &dm->loopData, -- 2.30.2 From a15351c338427336b8618d5efb2d5df1b27d4e3f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 29 Nov 2022 12:55:32 -0600 Subject: [PATCH 02/85] A few compilation fixes --- source/blender/blenkernel/intern/mesh_remap.cc | 2 +- source/blender/makesrna/intern/rna_mesh_api.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index 8b11ac7bff5..bd2ced3eef1 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -1291,7 +1291,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const float(*poly_nors_src)[3] = nullptr; const float(*loop_nors_src)[3] = nullptr; const float(*poly_nors_dst)[3] = nullptr; - float(*loop_nors_dst)[3] = nullptr; + const float(*loop_nors_dst)[3] = nullptr; float(*poly_cents_src)[3] = nullptr; diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 4ad4819c526..99e6f1257b8 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -44,13 +44,14 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, static void rna_Mesh_create_normals_split(Mesh *mesh) { - /* TODO: Proper deprecation. */ + /* TODO: Deprecation? */ + BKE_mesh_corner_normals_ensure(mesh); } static void rna_Mesh_free_normals_split(Mesh *mesh) { /* TODO: Deprecation? */ - BKE_mesh_clear_derived_normals(mesh); + BKE_mesh_normals_tag_dirty(mesh); } static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap) -- 2.30.2 From ba7052caa949449e78252a363f7e673ed189328c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 29 Nov 2022 13:06:49 -0600 Subject: [PATCH 03/85] Cleanup: Make function, remove function --- source/blender/blenkernel/BKE_mesh.h | 13 ++------- source/blender/blenkernel/intern/mesh.cc | 35 ++++-------------------- 2 files changed, 8 insertions(+), 40 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 3f2d9f14436..950b48f0ad4 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -418,6 +418,8 @@ float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3]; */ float (*BKE_mesh_poly_normals_for_write(struct Mesh *mesh))[3]; +float (*BKE_mesh_corner_normals_for_write(struct Mesh *mesh))[3]; + /** * Mark the mesh's vertex normals non-dirty, for when they are calculated or assigned manually. */ @@ -684,17 +686,6 @@ void BKE_mesh_normals_loop_to_vertex(int numVerts, */ bool BKE_mesh_has_custom_loop_normals(struct Mesh *me); -/** - * Compute 'split' (aka loop, or per face corner's) normals. - * - * \param r_lnors_spacearr: Allows to get computed loop normal space array. - * That data, among other things, contains 'smooth fan' info, useful e.g. - * to split geometry along sharp edges. - */ -void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh, - struct MLoopNorSpaceArray *r_lnors_spacearr, - float (*r_corner_normals)[3]); - /** * Higher level functions hiding most of the code needed around call to * #BKE_mesh_normals_loop_custom_set(). diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index ccf3b688424..808e751209e 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1753,36 +1753,14 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, BKE_mesh_tag_coords_changed(mesh); } -static float (*ensure_corner_normal_layer(Mesh &mesh))[3] +static void calc_normals_split(Mesh *mesh, + MLoopNorSpaceArray *r_lnors_spacearr, + float (*r_corner_normals)[3]) { - float(*r_loopnors)[3]; - if (CustomData_has_layer(&mesh.ldata, CD_NORMAL)) { - r_loopnors = (float(*)[3])CustomData_get_layer(&mesh.ldata, CD_NORMAL); - memset(r_loopnors, 0, sizeof(float[3]) * mesh.totloop); - } - else { - r_loopnors = (float(*)[3])CustomData_add_layer( - &mesh.ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, mesh.totloop); - CustomData_set_layer_flag(&mesh.ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - } - return r_loopnors; -} - -void BKE_mesh_calc_normals_split_ex(Mesh *mesh, - MLoopNorSpaceArray *r_lnors_spacearr, - float (*r_corner_normals)[3]) -{ - short(*clnors)[2] = nullptr; - - /* Note that we enforce computing clnors when the clnor space array is requested by caller here. - * However, we obviously only use the auto-smooth angle threshold - * only in case auto-smooth is enabled. */ - const bool use_split_normals = (r_lnors_spacearr != nullptr) || - ((mesh->flag & ME_AUTOSMOOTH) != 0); const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI); /* may be nullptr */ - clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + short(*clnors)[2] = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); const Span verts = mesh->verts(); const Span edges = mesh->edges(); @@ -1800,14 +1778,13 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, polys.data(), BKE_mesh_poly_normals_ensure(mesh), polys.size(), - use_split_normals, + true, split_angle, nullptr, r_lnors_spacearr, clnors); } - /* Split faces helper functions. */ struct SplitFaceNewVert { @@ -2018,7 +1995,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) MLoopNorSpaceArray lnors_spacearr = {nullptr}; /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */ - BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr, ensure_corner_normal_layer(*mesh)); + calc_normals_split(mesh, &lnors_spacearr, BKE_mesh_corner_normals_for_write(mesh)); /* Stealing memarena from loop normals space array. */ MemArena *memarena = lnors_spacearr.mem; -- 2.30.2 From d6c4ef758603210caf0bdda9dd5bc98597f8babe Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 29 Nov 2022 14:02:32 -0600 Subject: [PATCH 04/85] Fix one build error --- source/blender/io/wavefront_obj/exporter/obj_exporter.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc index f3d379c620c..120765dc227 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc @@ -157,9 +157,6 @@ static void write_mesh_objects(Vector> exportable_as_me if (mtl_writer) { mtlindices.append(mtl_writer->add_materials(obj)); } - if (export_params.export_normals) { - obj.ensure_mesh_normals(); - } } /* Parallel over meshes: store normal coords & indices, uv coords and indices. */ -- 2.30.2 From cf9f4952830b56266b5a772ca22bc8db0b447457 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 1 Dec 2022 19:47:15 +0100 Subject: [PATCH 05/85] fix some compilation errors --- source/blender/blenkernel/intern/mesh_normals.cc | 2 +- source/blender/makesrna/intern/rna_mesh.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index cb1ba9efafd..9364918ddb3 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -525,7 +525,7 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3] const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] { if (!BKE_mesh_corner_normals_are_dirty(mesh)) { - BLI_assert(mesh->runtime->corner_normals != nullptr || mesh->totcorner == 0); + BLI_assert(mesh->runtime->corner_normals != nullptr || mesh->totloop == 0); return mesh->runtime->corner_normals; } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 8d0460d8578..f30beb5736d 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2434,6 +2434,7 @@ static void rna_def_mloop(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Index", "Index of this loop"); prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", NULL, NULL); -- 2.30.2 From 55e1ef2c232f0c1a19ee4b659004f61f80ff0b14 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 14 Dec 2022 09:40:41 -0600 Subject: [PATCH 06/85] More progress, reverting unnecessary changes --- source/blender/blenkernel/BKE_mesh.h | 2 - .../blender/blenkernel/intern/DerivedMesh.cc | 2 - .../blenkernel/intern/data_transfer.cc | 159 ++++++++++-------- source/blender/blenkernel/intern/mesh.cc | 37 ---- .../blender/blenkernel/intern/mesh_normals.cc | 30 ++-- .../blender/blenkernel/intern/mesh_wrapper.cc | 3 - .../draw_cache_extract_mesh_render_data.cc | 30 +--- .../intern/mesh_extractors/extract_mesh.hh | 3 +- .../wavefront_obj/exporter/obj_export_mesh.cc | 8 +- .../blender/modifiers/intern/MOD_displace.cc | 85 +++++----- .../modifiers/intern/MOD_triangulate.cc | 81 +++++---- source/blender/render/intern/multires_bake.cc | 91 +++++----- 12 files changed, 239 insertions(+), 292 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 846250bd098..c75fac7452f 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -410,8 +410,6 @@ float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3]; */ float (*BKE_mesh_poly_normals_for_write(struct Mesh *mesh))[3]; -float (*BKE_mesh_corner_normals_for_write(struct Mesh *mesh))[3]; - /** * Mark the mesh's vertex normals non-dirty, for when they are calculated or assigned manually. */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index d13f30b1898..88cdbdce963 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -559,8 +559,6 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, * which deals with drawing differently. */ BKE_mesh_ensure_normals_for_display(mesh_final); } - - } } diff --git a/source/blender/blenkernel/intern/data_transfer.cc b/source/blender/blenkernel/intern/data_transfer.cc index cc914599005..382736ae502 100644 --- a/source/blender/blenkernel/intern/data_transfer.cc +++ b/source/blender/blenkernel/intern/data_transfer.cc @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2014 Blender Foundation. All rights reserved. */ /** \file * \ingroup bke @@ -269,18 +271,19 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src, const float split_angle_dst = me_dst->smoothresh; /* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */ - BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != NULL); + BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != nullptr); (void)me_src; float(*loop_nors_dst)[3]; - short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); + short(*custom_nors_dst)[2] = static_cast( + CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL)); /* Cache loop nors into a temp CDLayer. */ - loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL); - const bool do_loop_nors_dst = (loop_nors_dst == NULL); + loop_nors_dst = static_cast(CustomData_get_layer(ldata_dst, CD_NORMAL)); + const bool do_loop_nors_dst = (loop_nors_dst == nullptr); if (do_loop_nors_dst) { - loop_nors_dst = CustomData_add_layer( - ldata_dst, CD_NORMAL, CD_SET_DEFAULT, NULL, num_loops_dst); + loop_nors_dst = static_cast( + CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, num_loops_dst)); CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); } if (dirty_nors_dst || do_loop_nors_dst) { @@ -297,8 +300,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src, num_polys_dst, use_split_nors_dst, split_angle_dst, - NULL, - NULL, + nullptr, + nullptr, custom_nors_dst); } } @@ -328,12 +331,14 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src), CustomData *ldata_dst = &me_dst->ldata; const float(*poly_nors_dst)[3] = BKE_mesh_poly_normals_ensure(me_dst); - float(*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL); - short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL); + float(*loop_nors_dst)[3] = static_cast( + CustomData_get_layer(ldata_dst, CD_NORMAL)); + short(*custom_nors_dst)[2] = static_cast( + CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL)); if (!custom_nors_dst) { - custom_nors_dst = CustomData_add_layer( - ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, NULL, num_loops_dst); + custom_nors_dst = static_cast(CustomData_add_layer( + ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, num_loops_dst)); } /* Note loop_nors_dst contains our custom normals as transferred from source... */ @@ -362,7 +367,7 @@ static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int c default: break; } - return NULL; + return nullptr; } float data_transfer_interp_float_do(const int mix_mode, @@ -420,9 +425,9 @@ void data_transfer_layersmapping_add_item(ListBase *r_map, cd_datatransfer_interp interp, void *interp_data) { - CustomDataTransferLayerMap *item = MEM_mallocN(sizeof(*item), __func__); + CustomDataTransferLayerMap *item = MEM_new(__func__); - BLI_assert(data_dst != NULL); + BLI_assert(data_dst != nullptr); item->data_type = cddata_type; item->mix_mode = mix_mode; @@ -485,7 +490,7 @@ static void data_transfer_layersmapping_add_item_cd(ListBase *r_map, * \note * All those layer mapping handlers return false *only* if they were given invalid parameters. * This means that even if they do nothing, they will return true if all given parameters were OK. - * Also, r_map may be NULL, in which case they will 'only' create/delete destination layers + * Also, r_map may be nullptr, in which case they will 'only' create/delete destination layers * according to given parameters. */ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map, @@ -506,10 +511,10 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map void *interp_data) { const void *data_src; - void *data_dst = NULL; + void *data_dst = nullptr; int idx_src = num_layers_src; int idx_dst, tot_dst = CustomData_number_of_layers(cd_dst, cddata_type); - bool *data_dst_to_delete = NULL; + bool *data_dst_to_delete = nullptr; if (!use_layers_src) { /* No source at all, we can only delete all dest if requested... */ @@ -536,7 +541,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map if (use_create) { /* Create as much data layers as necessary! */ for (; idx_dst < idx_src; idx_dst++) { - CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, NULL, num_elem_dst); + CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst); } } else { @@ -579,9 +584,9 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map case DT_LAYERS_NAME_DST: if (use_delete) { if (tot_dst) { - data_dst_to_delete = MEM_mallocN(sizeof(*data_dst_to_delete) * (size_t)tot_dst, - __func__); - memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * (size_t)tot_dst); + data_dst_to_delete = static_cast( + MEM_mallocN(sizeof(*data_dst_to_delete) * size_t(tot_dst), __func__)); + memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * size_t(tot_dst)); } } @@ -598,7 +603,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) { if (use_create) { CustomData_add_layer_named( - cd_dst, cddata_type, CD_SET_DEFAULT, NULL, num_elem_dst, name); + cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst, name); idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); } else { @@ -671,7 +676,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, { int idx_src, idx_dst; const void *data_src; - void *data_dst = NULL; + void *data_dst = nullptr; if (CustomData_layertype_is_singleton(cddata_type)) { if (!(data_src = CustomData_get_layer(cd_src, cddata_type))) { @@ -686,7 +691,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, if (!use_create) { return true; } - data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, NULL, num_elem_dst); + data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst); } else if (use_dupref_dst && r_map) { /* If dest is a evaluated mesh (from modifier), @@ -739,7 +744,8 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, if (!use_create) { return true; } - data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, NULL, num_elem_dst); + data_dst = CustomData_add_layer( + cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst); } else { /* If dest is a evaluated mesh (from modifier), @@ -762,7 +768,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, } /* Create as much data layers as necessary! */ for (; num <= idx_dst; num++) { - CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, NULL, num_elem_dst); + CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst); } } /* If dest is a evaluated mesh (from modifier), @@ -781,7 +787,8 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, if (!use_create) { return true; } - CustomData_add_layer_named(cd_dst, cddata_type, CD_SET_DEFAULT, NULL, num_elem_dst, name); + CustomData_add_layer_named( + cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst, name); idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name); } /* If dest is a evaluated mesh (from modifier), @@ -816,9 +823,9 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, } else if (fromlayers == DT_LAYERS_ALL_SRC) { int num_src = CustomData_number_of_layers(cd_src, cddata_type); - bool *use_layers_src = num_src ? - MEM_mallocN(sizeof(*use_layers_src) * (size_t)num_src, __func__) : - NULL; + bool *use_layers_src = num_src ? static_cast(MEM_mallocN( + sizeof(*use_layers_src) * size_t(num_src), __func__)) : + nullptr; bool ret; if (use_layers_src) { @@ -873,8 +880,8 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, { CustomData *cd_src, *cd_dst; - cd_datatransfer_interp interp = NULL; - void *interp_data = NULL; + cd_datatransfer_interp interp = nullptr; + void *interp_data = nullptr; if (elem_type == ME_VERT) { if (!(cddata_type & CD_FAKE)) { @@ -955,8 +962,8 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, return true; } if (r_map && ELEM(cddata_type, CD_FAKE_SHARP, CD_FAKE_SEAM)) { - const size_t elem_size = sizeof(*((MEdge *)NULL)); - const size_t data_size = sizeof(((MEdge *)NULL)->flag); + const size_t elem_size = sizeof(*((MEdge *)nullptr)); + const size_t data_size = sizeof(((MEdge *)nullptr)->flag); const size_t data_offset = offsetof(MEdge, flag); const uint64_t data_flag = (cddata_type == CD_FAKE_SHARP) ? ME_SHARP : ME_SEAM; @@ -973,7 +980,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, data_size, data_offset, data_flag, - NULL, + nullptr, interp_data); return true; } @@ -1049,8 +1056,8 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, return true; } if (r_map && cddata_type == CD_FAKE_SHARP) { - const size_t elem_size = sizeof(*((MPoly *)NULL)); - const size_t data_size = sizeof(((MPoly *)NULL)->flag); + const size_t elem_size = sizeof(*((MPoly *)nullptr)); + const size_t data_size = sizeof(((MPoly *)nullptr)->flag); const size_t data_offset = offsetof(MPoly, flag); const uint64_t data_flag = ME_SMOOTH; @@ -1067,7 +1074,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, data_size, data_offset, data_flag, - NULL, + nullptr, interp_data); return true; } @@ -1096,7 +1103,7 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH)); - me_dst = ob_dst->data; + me_dst = static_cast(ob_dst->data); /* Get source evaluated mesh. */ BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); @@ -1130,7 +1137,7 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, if (DT_DATATYPE_IS_VERT(dtdata_type)) { const int num_elem_dst = me_dst->totvert; - data_transfer_layersmapping_generate(NULL, + data_transfer_layersmapping_generate(nullptr, ob_src, ob_dst, me_src, @@ -1139,18 +1146,18 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, cddata_type, 0, 0.0f, - NULL, + nullptr, num_elem_dst, use_create, use_delete, fromlayers, tolayers, - NULL); + nullptr); } if (DT_DATATYPE_IS_EDGE(dtdata_type)) { const int num_elem_dst = me_dst->totedge; - data_transfer_layersmapping_generate(NULL, + data_transfer_layersmapping_generate(nullptr, ob_src, ob_dst, me_src, @@ -1159,18 +1166,18 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, cddata_type, 0, 0.0f, - NULL, + nullptr, num_elem_dst, use_create, use_delete, fromlayers, tolayers, - NULL); + nullptr); } if (DT_DATATYPE_IS_LOOP(dtdata_type)) { const int num_elem_dst = me_dst->totloop; - data_transfer_layersmapping_generate(NULL, + data_transfer_layersmapping_generate(nullptr, ob_src, ob_dst, me_src, @@ -1179,18 +1186,18 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, cddata_type, 0, 0.0f, - NULL, + nullptr, num_elem_dst, use_create, use_delete, fromlayers, tolayers, - NULL); + nullptr); } if (DT_DATATYPE_IS_POLY(dtdata_type)) { const int num_elem_dst = me_dst->totpoly; - data_transfer_layersmapping_generate(NULL, + data_transfer_layersmapping_generate(nullptr, ob_src, ob_dst, me_src, @@ -1199,13 +1206,13 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph, cddata_type, 0, 0.0f, - NULL, + nullptr, num_elem_dst, use_create, use_delete, fromlayers, tolayers, - NULL); + nullptr); } } } @@ -1246,13 +1253,13 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, /* Assumed always true if not using an evaluated mesh as destination. */ bool dirty_nors_dst = true; - const MDeformVert *mdef = NULL; + const MDeformVert *mdef = nullptr; int vg_idx = -1; - float *weights[DATAMAX] = {NULL}; + float *weights[DATAMAX] = {nullptr}; MeshPairRemap geom_map[DATAMAX] = {{0}}; bool geom_map_init[DATAMAX] = {0}; - ListBase lay_map = {NULL}; + ListBase lay_map = {nullptr}; bool changed = false; bool is_modifier = false; @@ -1270,11 +1277,11 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, is_modifier = true; } else { - me_dst = ob_dst->data; + me_dst = static_cast(ob_dst->data); } if (vgroup_name) { - mdef = CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT); + mdef = static_cast(CustomData_get_layer(&me_dst->vdata, CD_MDEFORMVERT)); if (mdef) { vg_idx = BKE_id_defgroup_name_index(&me_dst->id, vgroup_name); } @@ -1287,7 +1294,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (is_modifier) { me_src = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_src); - if (me_src == NULL || + if (me_src == nullptr || !CustomData_MeshMasks_are_matching(&ob_src->runtime.last_data_mask, &me_src_mask)) { CLOG_WARN(&LOG, "Data Transfer: source mesh data is not ready - dependency cycle?"); return changed; @@ -1302,7 +1309,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, BKE_mesh_wrapper_ensure_mdata(me_src); if (auto_transform) { - if (space_transform == NULL) { + if (space_transform == nullptr) { space_transform = &auto_space_transform; } @@ -1384,7 +1391,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, } if (mdef && vg_idx != -1 && !weights[VDATA]) { - weights[VDATA] = MEM_mallocN(sizeof(*(weights[VDATA])) * (size_t)num_verts_dst, __func__); + weights[VDATA] = static_cast( + MEM_mallocN(sizeof(*(weights[VDATA])) * size_t(num_verts_dst), __func__)); BKE_defvert_extract_vgroup_to_vertweights( mdef, vg_idx, num_verts_dst, invert_vgroup, weights[VDATA]); } @@ -1407,9 +1415,10 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed |= (lay_map.first != NULL); + changed |= (lay_map.first != nullptr); - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + for (lay_mapit = static_cast(lay_map.first); lay_mapit; + lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[VDATA], lay_mapit); } @@ -1463,7 +1472,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, } if (mdef && vg_idx != -1 && !weights[EDATA]) { - weights[EDATA] = MEM_mallocN(sizeof(*weights[EDATA]) * (size_t)num_edges_dst, __func__); + weights[EDATA] = static_cast( + MEM_mallocN(sizeof(*weights[EDATA]) * size_t(num_edges_dst), __func__)); BKE_defvert_extract_vgroup_to_edgeweights( mdef, vg_idx, num_verts_dst, edges_dst, num_edges_dst, invert_vgroup, weights[EDATA]); } @@ -1486,9 +1496,10 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed |= (lay_map.first != NULL); + changed |= (lay_map.first != nullptr); - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + for (lay_mapit = static_cast(lay_map.first); lay_mapit; + lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[EDATA], lay_mapit); } @@ -1558,7 +1569,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, } if (mdef && vg_idx != -1 && !weights[LDATA]) { - weights[LDATA] = MEM_mallocN(sizeof(*weights[LDATA]) * (size_t)num_loops_dst, __func__); + weights[LDATA] = static_cast( + MEM_mallocN(sizeof(*weights[LDATA]) * size_t(num_loops_dst), __func__)); BKE_defvert_extract_vgroup_to_loopweights( mdef, vg_idx, num_verts_dst, loops_dst, num_loops_dst, invert_vgroup, weights[LDATA]); } @@ -1581,9 +1593,10 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed |= (lay_map.first != NULL); + changed |= (lay_map.first != nullptr); - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + for (lay_mapit = static_cast(lay_map.first); lay_mapit; + lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[LDATA], lay_mapit); } @@ -1638,7 +1651,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, } if (mdef && vg_idx != -1 && !weights[PDATA]) { - weights[PDATA] = MEM_mallocN(sizeof(*weights[PDATA]) * (size_t)num_polys_dst, __func__); + weights[PDATA] = static_cast( + MEM_mallocN(sizeof(*weights[PDATA]) * size_t(num_polys_dst), __func__)); BKE_defvert_extract_vgroup_to_polyweights(mdef, vg_idx, num_verts_dst, @@ -1668,9 +1682,10 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, space_transform)) { CustomDataTransferLayerMap *lay_mapit; - changed |= (lay_map.first != NULL); + changed |= (lay_map.first != nullptr); - for (lay_mapit = lay_map.first; lay_mapit; lay_mapit = lay_mapit->next) { + for (lay_mapit = static_cast(lay_map.first); lay_mapit; + lay_mapit = lay_mapit->next) { CustomData_data_transfer(&geom_map[PDATA], lay_mapit); } @@ -1722,7 +1737,7 @@ bool BKE_object_data_transfer_mesh(struct Depsgraph *depsgraph, scene, ob_src, ob_dst, - NULL, + nullptr, data_types, use_create, map_vert_mode, diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 3edf71ed397..b19a81438d3 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1763,43 +1763,6 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh, BKE_mesh_tag_coords_changed(mesh); } -static void calc_normals_split(Mesh *mesh, - MLoopNorSpaceArray *r_lnors_spacearr, - float (*r_corner_normals)[3]) -{ - const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI); - - /* may be nullptr */ - short(*clnors)[2] = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); - - const Span verts = mesh->verts(); - const Span edges = mesh->edges(); - const Span polys = mesh->polys(); - const Span loops = mesh->loops(); - - BKE_mesh_normals_loop_split(verts.data(), - BKE_mesh_vertex_normals_ensure(mesh), - verts.size(), - edges.data(), - edges.size(), - loops.data(), - r_corner_normals, - loops.size(), - polys.data(), - BKE_mesh_poly_normals_ensure(mesh), - polys.size(), - true, - split_angle, - nullptr, - r_lnors_spacearr, - clnors); -} - -void BKE_mesh_calc_normals_split(Mesh *mesh) -{ - BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh)); -} - /* **** Depsgraph evaluation **** */ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index b8191657045..e32d8b6ca8d 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -128,18 +128,6 @@ float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3] return mesh->runtime->poly_normals; } -float (*BKE_mesh_corner_normals_for_write(Mesh *mesh))[3] -{ - if (mesh->runtime->corner_normals == nullptr) { - mesh->runtime->corner_normals = (float(*)[3])MEM_malloc_arrayN( - mesh->totloop, sizeof(float[3]), __func__); - } - - BLI_assert(MEM_allocN_len(mesh->runtime->corner_normals) >= sizeof(float[3]) * mesh->totloop); - - return mesh->runtime->corner_normals; -} - void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh) { mesh->runtime->vert_normals_dirty = false; @@ -554,9 +542,13 @@ const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] const Span polys = mesh_mutable.polys(); const Span loops = mesh_mutable.loops(); - corner_normals = BKE_mesh_corner_normals_for_write(&mesh_mutable); - const short(*custom_nors_dst)[2] = (const short(*)[2])CustomData_get_layer( - &mesh->ldata, CD_CUSTOMLOOPNORMAL); + if (mesh_mutable.runtime->corner_normals == nullptr) { + mesh_mutable.runtime->corner_normals = (float(*)[3])MEM_malloc_arrayN( + mesh_mutable.totloop, sizeof(float[3]), __func__); + } + + const short(*custom_normals)[2] = (const short(*)[2])CustomData_get_layer(&mesh->ldata, + CD_CUSTOMLOOPNORMAL); BKE_mesh_normals_loop_split(verts.data(), vert_normals, @@ -569,10 +561,10 @@ const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] polys.data(), poly_normals, polys.size(), - use_split_normals, - split_angle, - r_lnors_spacearr, - clnors, + true, + mesh->smoothresh, + nullptr, + custom_normals, nullptr); BKE_mesh_corner_normals_clear_dirty(&mesh_mutable); diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index feb883fb866..aca0afb71a2 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -340,9 +340,6 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me) const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(subdiv_mesh); BKE_mesh_set_custom_normals(subdiv_mesh, lnors); } - else if (runtime_data->calc_loop_normals) { - BKE_mesh_corner_normals_ensure(subdiv_mesh); - } if (subdiv != runtime_data->subdiv) { BKE_subdiv_free(subdiv); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index bfec7cd6f7b..366bc499842 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -364,26 +364,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ mr->poly_normals = BKE_mesh_poly_normals_ensure(mr->me); } if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { - mr->loop_normals = static_cast( - MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__)); - short(*clnors)[2] = static_cast( - CustomData_get_layer(&mr->me->ldata, CD_CUSTOMLOOPNORMAL)); - BKE_mesh_normals_loop_split(mr->mvert, - mr->vert_normals, - mr->vert_len, - mr->medge, - mr->edge_len, - mr->mloop, - mr->loop_normals, - mr->loop_len, - mr->mpoly, - mr->poly_normals, - mr->poly_len, - is_auto_smooth, - split_angle, - nullptr, - nullptr, - clnors); + mr->loop_normals = BKE_mesh_corner_normals_ensure(mr->me); } } else { @@ -403,8 +384,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ poly_normals = mr->bm_poly_normals; } - mr->loop_normals = static_cast( - MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__)); + mr->bm_loop_normals = static_cast( + MEM_mallocN(sizeof(*mr->bm_loop_normals) * mr->loop_len, __func__)); const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); BM_loops_calc_normal_vcos(mr->bm, vert_coords, @@ -412,11 +393,12 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ poly_normals, is_auto_smooth, split_angle, - mr->loop_normals, + mr->bm_loop_normals, nullptr, nullptr, clnors_offset, false); + mr->loop_normals = mr->bm_loop_normals; } } } @@ -601,7 +583,7 @@ MeshRenderData *mesh_render_data_create(Object *object, void mesh_render_data_free(MeshRenderData *mr) { - MEM_SAFE_FREE(mr->loop_normals); + MEM_SAFE_FREE(mr->bm_loop_normals); /* Loose geometry are owned by #MeshBufferCache. */ mr->ledges = nullptr; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index c6230e2695e..a6d09ac6076 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -91,7 +91,8 @@ struct MeshRenderData { const bool *select_vert; const bool *select_edge; const bool *select_poly; - float (*loop_normals)[3]; + const float (*loop_normals)[3]; + float (*bm_loop_normals)[3]; int *lverts, *ledges; const char *active_color_name; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 3b2d70f9d4f..dbf84d84957 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -379,10 +379,10 @@ void OBJMesh::store_normal_coords_and_indices() normal_to_index.reserve(export_mesh_->totpoly); loop_to_normal_index_.resize(export_mesh_->totloop); loop_to_normal_index_.fill(-1); - const float(*lnors)[3] = static_cast( - CustomData_get_layer(&export_mesh_eval_->ldata, CD_NORMAL)); - for (int poly_index = 0; poly_index < export_mesh_eval_->totpoly; ++poly_index) { - const MPoly &mpoly = polys[poly_index]; + /* TODO: Only retrieve when necessary. */ + const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(export_mesh_); + for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) { + const MPoly &mpoly = mesh_polys_[poly_index]; bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH); if (need_per_loop_normals) { for (int loop_of_poly = 0; loop_of_poly < mpoly.totloop; ++loop_of_poly) { diff --git a/source/blender/modifiers/intern/MOD_displace.cc b/source/blender/modifiers/intern/MOD_displace.cc index fc12a9c2aad..ce90b229ad4 100644 --- a/source/blender/modifiers/intern/MOD_displace.cc +++ b/source/blender/modifiers/intern/MOD_displace.cc @@ -126,10 +126,10 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte need_transform_relation = true; } - if (dmd->texture != NULL) { + if (dmd->texture != nullptr) { DEG_add_generic_id_relation(ctx->node, &dmd->texture->id, "Displace Modifier"); - if (dmd->map_object != NULL && dmd->texmapping == MOD_DISP_MAP_OBJECT) { + if (dmd->map_object != nullptr && dmd->texmapping == MOD_DISP_MAP_OBJECT) { MOD_depsgraph_update_object_bone_relation( ctx->node, dmd->map_object, dmd->map_bone, "Displace Modifier"); need_transform_relation = true; @@ -273,11 +273,11 @@ static void displaceModifier_do(DisplaceModifierData *dmd, int defgrp_index; float(*tex_co)[3]; float weight = 1.0f; /* init value unused but some compilers may complain */ - float(*vert_clnors)[3] = NULL; + float(*vert_clnors)[3] = nullptr; float local_mat[4][4] = {{0}}; const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL; - if (dmd->texture == NULL && dmd->direction == MOD_DISP_DIR_RGB_XYZ) { + if (dmd->texture == nullptr && dmd->direction == MOD_DISP_DIR_RGB_XYZ) { return; } if (dmd->strength == 0.0f) { @@ -287,34 +287,32 @@ static void displaceModifier_do(DisplaceModifierData *dmd, mvert = BKE_mesh_verts_for_write(mesh); MOD_get_vgroup(ob, mesh, dmd->defgrp_name, &dvert, &defgrp_index); - if (defgrp_index >= 0 && dvert == NULL) { + if (defgrp_index >= 0 && dvert == nullptr) { /* There is a vertex group, but it has no vertices. */ return; } Tex *tex_target = dmd->texture; - if (tex_target != NULL) { - tex_co = MEM_calloc_arrayN((size_t)verts_num, sizeof(*tex_co), "displaceModifier_do tex_co"); + if (tex_target != nullptr) { + tex_co = static_cast( + MEM_calloc_arrayN(size_t(verts_num), sizeof(*tex_co), "displaceModifier_do tex_co")); MOD_get_texture_coords((MappingInfoModifierData *)dmd, ctx, ob, mesh, vertexCos, tex_co); MOD_init_texture((MappingInfoModifierData *)dmd, ctx); } else { - tex_co = NULL; + tex_co = nullptr; } if (direction == MOD_DISP_DIR_CLNOR) { - CustomData *ldata = &mesh->ldata; - - if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) { - if (!CustomData_has_layer(ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(mesh); - } - - float(*clnors)[3] = CustomData_get_layer(ldata, CD_NORMAL); - vert_clnors = MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__); - BKE_mesh_normals_loop_to_vertex( - verts_num, BKE_mesh_loops(mesh), mesh->totloop, (const float(*)[3])clnors, vert_clnors); + if (CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)) { + vert_clnors = static_cast( + MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__)); + BKE_mesh_normals_loop_to_vertex(verts_num, + BKE_mesh_loops(mesh), + mesh->totloop, + BKE_mesh_corner_normals_ensure(mesh), + vert_clnors); } else { direction = MOD_DISP_DIR_NOR; @@ -325,7 +323,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, copy_m4_m4(local_mat, ob->object_to_world); } - DisplaceUserdata data = {NULL}; + DisplaceUserdata data = {nullptr}; data.scene = DEG_get_evaluated_scene(ctx->depsgraph); data.dmd = dmd; data.dvert = dvert; @@ -342,7 +340,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, data.vert_normals = BKE_mesh_vertex_normals_ensure(mesh); } data.vert_clnors = vert_clnors; - if (tex_target != NULL) { + if (tex_target != nullptr) { data.pool = BKE_image_pool_new(); BKE_texture_fetch_images_for_pool(tex_target, data.pool); } @@ -351,7 +349,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, settings.use_threading = (verts_num > 512); BLI_task_parallel_range(0, verts_num, &data, displaceModifier_do_task, &settings); - if (data.pool != NULL) { + if (data.pool != nullptr) { BKE_image_pool_free(data.pool); } @@ -370,12 +368,12 @@ static void deformVerts(ModifierData *md, float (*vertexCos)[3], int verts_num) { - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, nullptr, mesh, nullptr, verts_num, false); displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, verts_num); - if (!ELEM(mesh_src, NULL, mesh)) { - BKE_id_free(NULL, mesh_src); + if (!ELEM(mesh_src, nullptr, mesh)) { + BKE_id_free(nullptr, mesh_src); } } @@ -386,17 +384,18 @@ static void deformVertsEM(ModifierData *md, float (*vertexCos)[3], int verts_num) { - Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, verts_num, false); + Mesh *mesh_src = MOD_deform_mesh_eval_get( + ctx->object, editData, mesh, nullptr, verts_num, false); /* TODO(@campbellbarton): use edit-mode data only (remove this line). */ - if (mesh_src != NULL) { + if (mesh_src != nullptr) { BKE_mesh_wrapper_ensure_mdata(mesh_src); } displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, verts_num); - if (!ELEM(mesh_src, NULL, mesh)) { - BKE_id_free(NULL, mesh_src); + if (!ELEM(mesh_src, nullptr, mesh)) { + BKE_id_free(nullptr, mesh_src); } } @@ -416,7 +415,7 @@ static void panel_draw(const bContext *C, Panel *panel) uiLayoutSetPropSep(layout, true); - uiTemplateID(layout, C, ptr, "texture", "texture.new", NULL, NULL, 0, ICON_NONE, NULL); + uiTemplateID(layout, C, ptr, "texture", "texture.new", nullptr, nullptr, 0, ICON_NONE, nullptr); col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, has_texture); @@ -437,7 +436,7 @@ static void panel_draw(const bContext *C, Panel *panel) } } else if (texture_coords == MOD_DISP_MAP_UV && RNA_enum_get(&ob_ptr, "type") == OB_MESH) { - uiItemPointerR(col, ptr, "uv_layer", &obj_data_ptr, "uv_layers", NULL, ICON_NONE); + uiItemPointerR(col, ptr, "uv_layer", &obj_data_ptr, "uv_layers", nullptr, ICON_NONE); } uiItemS(layout); @@ -449,16 +448,16 @@ static void panel_draw(const bContext *C, Panel *panel) MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ)) { - uiItemR(col, ptr, "space", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "space", 0, nullptr, ICON_NONE); } uiItemS(layout); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "strength", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "mid_level", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "strength", 0, nullptr, ICON_NONE); + uiItemR(col, ptr, "mid_level", 0, nullptr, ICON_NONE); - modifier_vgroup_ui(col, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL); + modifier_vgroup_ui(col, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr); modifier_panel_end(layout, ptr); } @@ -480,23 +479,23 @@ ModifierTypeInfo modifierType_Displace = { /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, - /* deformMatrices */ NULL, + /* deformMatrices */ nullptr, /* deformVertsEM */ deformVertsEM, - /* deformMatricesEM */ NULL, - /* modifyMesh */ NULL, - /* modifyGeometrySet */ NULL, + /* deformMatricesEM */ nullptr, + /* modifyMesh */ nullptr, + /* modifyGeometrySet */ nullptr, /* initData */ initData, /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, + /* freeData */ nullptr, /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ dependsOnNormals, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, - /* freeRuntimeData */ NULL, + /* freeRuntimeData */ nullptr, /* panelRegister */ panelRegister, - /* blendWrite */ NULL, - /* blendRead */ NULL, + /* blendWrite */ nullptr, + /* blendRead */ nullptr, }; diff --git a/source/blender/modifiers/intern/MOD_triangulate.cc b/source/blender/modifiers/intern/MOD_triangulate.cc index 5bae6090758..f09c1316e97 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.cc +++ b/source/blender/modifiers/intern/MOD_triangulate.cc @@ -45,40 +45,39 @@ static Mesh *triangulate_mesh(Mesh *mesh, BMesh *bm; int edges_num, i; MEdge *me; - CustomData_MeshMasks cd_mask_extra = { - .vmask = CD_MASK_ORIGINDEX, .emask = CD_MASK_ORIGINDEX, .pmask = CD_MASK_ORIGINDEX}; + CustomData_MeshMasks cd_mask_extra{}; + cd_mask_extra.vmask = CD_MASK_ORIGINDEX; + 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) { - BKE_mesh_calc_normals_split(mesh); - /* We need that one to 'survive' to/from BMesh conversions. */ - CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - cd_mask_extra.lmask |= CD_MASK_NORMAL; + CustomData_add_layer(&mesh->ldata, + CD_NORMAL, + CD_DUPLICATE, + const_cast(BKE_mesh_corner_normals_ensure(mesh)), + mesh->totloop); } - bm = BKE_mesh_to_bmesh_ex(mesh, - &((struct BMeshCreateParams){0}), - &((struct BMeshFromMeshParams){ - .calc_face_normal = true, - .calc_vert_normal = false, - .cd_mask_extra = cd_mask_extra, - })); + BMeshCreateParams bmesh_create_params{}; + BMeshFromMeshParams bmesh_from_mesh_params{}; + bmesh_from_mesh_params.calc_face_normal = true; + bmesh_from_mesh_params.calc_vert_normal = false; + bmesh_from_mesh_params.cd_mask_extra = cd_mask_extra; - BM_mesh_triangulate(bm, quad_method, ngon_method, min_vertices, false, NULL, NULL, NULL); + bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); + + BM_mesh_triangulate( + bm, quad_method, ngon_method, min_vertices, false, nullptr, nullptr, nullptr); result = BKE_mesh_from_bmesh_for_eval_nomain(bm, &cd_mask_extra, mesh); BM_mesh_free(bm); if (keep_clnors) { - float(*lnors)[3] = CustomData_get_layer(&result->ldata, CD_NORMAL); - BLI_assert(lnors != NULL); - + float(*lnors)[3] = static_cast(CustomData_get_layer(&result->ldata, CD_NORMAL)); BKE_mesh_set_custom_normals(result, lnors); - - /* Do some cleanup, we do not want those temp data to stay around. */ - CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); - CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop); } edges_num = result->totedge; @@ -125,10 +124,10 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); - uiItemR(layout, ptr, "quad_method", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "ngon_method", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "min_vertices", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "keep_custom_normals", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "quad_method", 0, nullptr, ICON_NONE); + uiItemR(layout, ptr, "ngon_method", 0, nullptr, ICON_NONE); + uiItemR(layout, ptr, "min_vertices", 0, nullptr, ICON_NONE); + uiItemR(layout, ptr, "keep_custom_normals", 0, nullptr, ICON_NONE); modifier_panel_end(layout, ptr); } @@ -151,24 +150,24 @@ ModifierTypeInfo modifierType_Triangulate = { /* copyData */ BKE_modifier_copydata_generic, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyGeometrySet */ NULL, + /* modifyGeometrySet */ nullptr, /* initData */ initData, - /* requiredDataMask */ NULL, // requiredDataMask, - /* freeData */ NULL, - /* isDisabled */ NULL, - /* updateDepsgraph */ NULL, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, - /* freeRuntimeData */ NULL, + /* requiredDataMask */ nullptr, // requiredDataMask, + /* freeData */ nullptr, + /* isDisabled */ nullptr, + /* updateDepsgraph */ nullptr, + /* dependsOnTime */ nullptr, + /* dependsOnNormals */ nullptr, + /* foreachIDLink */ nullptr, + /* foreachTexLink */ nullptr, + /* freeRuntimeData */ nullptr, /* panelRegister */ panelRegister, - /* blendWrite */ NULL, - /* blendRead */ NULL, + /* blendWrite */ nullptr, + /* blendRead */ nullptr, }; diff --git a/source/blender/render/intern/multires_bake.cc b/source/blender/render/intern/multires_bake.cc index df0d5756cf0..600b7118e1e 100644 --- a/source/blender/render/intern/multires_bake.cc +++ b/source/blender/render/intern/multires_bake.cc @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2012 Blender Foundation. All rights reserved. */ /** \file * \ingroup render @@ -381,14 +383,14 @@ static void *do_multires_bake_thread(void *data_v) while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) { const MLoopTri *lt = &data->mlooptri[tri_index]; - const short mat_nr = data->material_indices == NULL ? 0 : data->material_indices[lt->poly]; + const short mat_nr = data->material_indices == nullptr ? 0 : data->material_indices[lt->poly]; const MLoopUV *mloopuv = data->mloopuv; if (multiresbake_test_break(bkr)) { break; } - Image *tri_image = mat_nr < bkr->ob_image.len ? bkr->ob_image.array[mat_nr] : NULL; + Image *tri_image = mat_nr < bkr->ob_image.len ? bkr->ob_image.array[mat_nr] : nullptr; if (tri_image != handle->image) { continue; } @@ -418,14 +420,14 @@ static void *do_multires_bake_thread(void *data_v) } if (bkr->progress) { - *bkr->progress = ((float)bkr->baked_objects + - (float)bkr->baked_faces / handle->queue->tot_tri) / + *bkr->progress = (float(bkr->baked_objects) + + float(bkr->baked_faces) / handle->queue->tot_tri) / bkr->tot_obj; } BLI_spin_unlock(&handle->queue->spin); } - return NULL; + return nullptr; } /* some of arrays inside ccgdm are lazy-initialized, which will generally @@ -473,13 +475,13 @@ static void do_multires_bake(MultiresBakeRender *bkr, MVert *mvert = dm->getVertArray(dm); MPoly *mpoly = dm->getPolyArray(dm); MLoop *mloop = dm->getLoopArray(dm); - MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV); - float *pvtangent = NULL; + MLoopUV *mloopuv = static_cast(dm->getLoopDataArray(dm, CD_MLOOPUV)); + float *pvtangent = nullptr; ListBase threads; int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count(); - void *bake_data = NULL; + void *bake_data = nullptr; Mesh *temp_mesh = BKE_mesh_new_nomain( dm->getNumVerts(dm), dm->getNumEdges(dm), 0, dm->getNumLoops(dm), dm->getNumPolys(dm)); @@ -509,19 +511,19 @@ static void do_multires_bake(MultiresBakeRender *bkr, dm->getNumLoopTri(dm), &dm->loopData, true, - NULL, + nullptr, 0, vert_normals, poly_normals, - (const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL), - (const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */ + BKE_mesh_corner_normals_ensure(temp_mesh), + (const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* May be nullptr. */ /* result */ &dm->loopData, dm->getNumLoops(dm), &dm->tangent_mask); } - pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT); + pvtangent = static_cast(DM_get_loop_data_layer(dm, CD_TANGENT)); } /* all threads shares the same custom bake data */ @@ -533,7 +535,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, BLI_threadpool_init(&threads, do_multires_bake_thread, tot_thread); } - handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles"); + handles = MEM_cnew_array(tot_thread, "do_multires_bake handles"); init_ccgdm_arrays(bkr->hires_dm); @@ -551,8 +553,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, handle->queue = &queue; handle->data.mpoly = mpoly; - handle->data.material_indices = CustomData_get_layer_named( - &dm->polyData, CD_PROP_INT32, "material_index"); + handle->data.material_indices = static_cast( + CustomData_get_layer_named(&dm->polyData, CD_PROP_INT32, "material_index")); handle->data.mvert = mvert; handle->data.vert_normals = vert_normals; handle->data.mloopuv = mloopuv; @@ -607,7 +609,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, MEM_freeN(handles); - BKE_id_free(NULL, temp_mesh); + BKE_id_free(nullptr, temp_mesh); } /* mode = 0: interpolate normals, @@ -619,10 +621,10 @@ static void interp_bilinear_grid( float u, v; float data[4][3]; - x0 = (int)crn_x; + x0 = int(crn_x); x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1); - y0 = (int)crn_y; + y0 = int(crn_y); y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1); u = crn_x - x0; @@ -702,11 +704,11 @@ static void get_ccgdm_data(DerivedMesh *lodm, CLAMP(crn_x, 0.0f, grid_size); CLAMP(crn_y, 0.0f, grid_size); - if (n != NULL) { + if (n != nullptr) { interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n); } - if (co != NULL) { + if (co != nullptr) { interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co); } } @@ -770,19 +772,19 @@ static void *init_heights_data(MultiresBakeRender *bkr, ImBuf *ibuf) { MHeightBakeData *height_data; DerivedMesh *lodm = bkr->lores_dm; - BakeImBufuserData *userdata = ibuf->userdata; + BakeImBufuserData *userdata = static_cast(ibuf->userdata); - if (userdata->displacement_buffer == NULL) { - userdata->displacement_buffer = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, - "MultiresBake heights"); + if (userdata->displacement_buffer == nullptr) { + userdata->displacement_buffer = MEM_cnew_array(ibuf->x * ibuf->y, + "MultiresBake heights"); } - height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); + height_data = MEM_cnew("MultiresBake heightData"); height_data->heights = userdata->displacement_buffer; if (!bkr->use_lores_mesh) { - SubsurfModifierData smd = {{NULL}}; + SubsurfModifierData smd = {{nullptr}}; int ss_lvl = bkr->tot_lvl - bkr->lvl; CLAMP(ss_lvl, 0, 6); @@ -793,12 +795,13 @@ static void *init_heights_data(MultiresBakeRender *bkr, ImBuf *ibuf) smd.quality = 3; height_data->ssdm = subsurf_make_derived_from_derived( - bkr->lores_dm, &smd, bkr->scene, NULL, 0); + bkr->lores_dm, &smd, bkr->scene, nullptr, SubsurfFlags(0)); init_ccgdm_arrays(height_data->ssdm); } } - height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); + height_data->orig_index_mp_to_orig = static_cast( + lodm->getPolyDataArray(lodm, CD_ORIGINDEX)); return (void *)height_data; } @@ -835,7 +838,7 @@ static void apply_heights_callback(DerivedMesh *lores_dm, const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; MLoop *mloop = lores_dm->getLoopArray(lores_dm); MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly; - MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV); + MLoopUV *mloopuv = static_cast(lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV)); MHeightBakeData *height_data = (MHeightBakeData *)bake_data; MultiresBakeThread *thread_data = (MultiresBakeThread *)thread_data_v; float uv[2], *st0, *st1, *st2, *st3; @@ -861,7 +864,7 @@ static void apply_heights_callback(DerivedMesh *lores_dm, clamp_v2(uv, 0.0f, 1.0f); get_ccgdm_data( - lores_dm, hires_dm, height_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], p1, NULL); + lores_dm, hires_dm, height_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], p1, nullptr); if (height_data->ssdm) { get_ccgdm_data(lores_dm, @@ -912,9 +915,10 @@ static void *init_normal_data(MultiresBakeRender *bkr, ImBuf *UNUSED(ibuf)) MNormalBakeData *normal_data; DerivedMesh *lodm = bkr->lores_dm; - normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData"); + normal_data = MEM_cnew("MultiresBake normalData"); - normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); + normal_data->orig_index_mp_to_orig = static_cast( + lodm->getPolyDataArray(lodm, CD_ORIGINDEX)); return (void *)normal_data; } @@ -948,7 +952,7 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, { const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index; MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly; - MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV); + MLoopUV *mloopuv = static_cast(lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV)); MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; @@ -973,7 +977,7 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, clamp_v2(uv, 0.0f, 1.0f); get_ccgdm_data( - lores_dm, hires_dm, normal_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], NULL, n); + lores_dm, hires_dm, normal_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], nullptr, n); mul_v3_m3v3(vec, tangmat, n); normalize_v3_length(vec, 0.5); @@ -1433,7 +1437,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) { LinkData *link; - for (link = bkr->image.first; link; link = link->next) { + for (link = static_cast(bkr->image.first); link; link = link->next) { Image *ima = (Image *)link->data; LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { @@ -1441,12 +1445,11 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) BKE_imageuser_default(&iuser); iuser.tile = tile->tile_number; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr); if (ibuf->x > 0 && ibuf->y > 0) { - BakeImBufuserData *userdata = MEM_callocN(sizeof(BakeImBufuserData), - "MultiresBake userdata"); - userdata->mask_buffer = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask"); + BakeImBufuserData *userdata = MEM_cnew("MultiresBake userdata"); + userdata->mask_buffer = MEM_cnew_array(ibuf->y * ibuf->x, "MultiresBake imbuf mask"); ibuf->userdata = userdata; switch (bkr->mode) { @@ -1481,7 +1484,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) } } - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_release_ibuf(ima, ibuf, nullptr); } ima->id.tag |= LIB_TAG_DOIT; @@ -1493,7 +1496,7 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) LinkData *link; bool use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT; - for (link = bkr->image.first; link; link = link->next) { + for (link = static_cast(bkr->image.first); link; link = link->next) { Image *ima = (Image *)link->data; LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { @@ -1501,7 +1504,7 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) BKE_imageuser_default(&iuser); iuser.tile = tile->tile_number; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr); BakeImBufuserData *userdata = (BakeImBufuserData *)ibuf->userdata; if (ibuf->x <= 0 || ibuf->y <= 0) { @@ -1545,10 +1548,10 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) MEM_freeN(userdata->mask_buffer); MEM_freeN(userdata); - ibuf->userdata = NULL; + ibuf->userdata = nullptr; } - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_release_ibuf(ima, ibuf, nullptr); DEG_id_tag_update(&ima->id, 0); } } -- 2.30.2 From f44e13579a2a4936568eb50c1ab9fcaef9744af2 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 5 Apr 2023 08:58:51 -0400 Subject: [PATCH 07/85] Progress removing auto smooth This needs to wait until 4.0 --- source/blender/blenkernel/BKE_editmesh.h | 4 - source/blender/blenkernel/BKE_mesh.h | 8 +- source/blender/blenkernel/BKE_mesh.hh | 14 +- source/blender/blenkernel/BKE_mesh_remap.h | 16 +- source/blender/blenkernel/BKE_mesh_runtime.h | 3 +- .../blender/blenkernel/intern/DerivedMesh.cc | 26 +- .../intern/curve_to_mesh_convert.cc | 2 - .../blenkernel/intern/data_transfer.cc | 76 +--- source/blender/blenkernel/intern/editmesh.cc | 26 +- source/blender/blenkernel/intern/key.cc | 18 +- source/blender/blenkernel/intern/mesh.cc | 27 +- .../blender/blenkernel/intern/mesh_convert.cc | 1 - .../blenkernel/intern/mesh_iterators.cc | 31 +- .../blender/blenkernel/intern/mesh_mirror.cc | 16 +- .../blender/blenkernel/intern/mesh_normals.cc | 342 ++++++++++++------ .../blender/blenkernel/intern/mesh_remap.cc | 31 +- .../blender/blenkernel/intern/mesh_tangent.cc | 21 +- .../blender/blenkernel/intern/mesh_wrapper.cc | 4 +- .../blender/blenkernel/intern/shrinkwrap.cc | 4 +- .../blenkernel/intern/subdiv_modifier.cc | 14 +- .../bmesh/intern/bmesh_mesh_normals.cc | 62 +--- .../blender/bmesh/intern/bmesh_mesh_normals.h | 1 - .../intern/builder/deg_builder_relations.cc | 3 +- .../draw_cache_extract_mesh_render_data.cc | 11 +- .../intern/draw_cache_impl_subdivision.cc | 4 +- .../intern/mesh_extractors/extract_mesh.hh | 3 +- .../mesh_extractors/extract_mesh_vbo_lnor.cc | 17 +- .../extract_mesh_vbo_pos_nor.cc | 5 +- .../mesh_extractors/extract_mesh_vbo_tan.cc | 23 +- source/blender/editors/include/ED_screen.h | 1 - source/blender/editors/mesh/editmesh_bevel.c | 5 - source/blender/editors/mesh/editmesh_tools.cc | 6 - source/blender/editors/mesh/mesh_data.cc | 41 +-- .../blender/editors/object/object_bake_api.cc | 3 +- .../editors/object/object_data_transfer.c | 3 - source/blender/editors/object/object_edit.cc | 12 +- source/blender/editors/screen/screen_ops.c | 9 - .../editors/sculpt_paint/curves_sculpt_add.cc | 5 +- .../sculpt_paint/curves_sculpt_density.cc | 5 +- .../sculpt_paint/curves_sculpt_puff.cc | 5 +- .../sculpt_paint/curves_sculpt_slide.cc | 5 +- source/blender/editors/transform/transform.c | 42 +-- .../transform_mode_edge_rotate_normal.c | 1 - .../blender_interface/BlenderFileLoader.cpp | 11 +- .../geometry/intern/add_curves_on_mesh.cc | 32 +- .../intern/MOD_gpencilshrinkwrap.c | 2 +- .../intern/lineart/lineart_cpu.cc | 4 - .../io/alembic/exporter/abc_writer_mesh.cc | 81 +++-- .../io/alembic/intern/abc_reader_mesh.cc | 2 - .../blender/io/collada/GeometryExporter.cpp | 12 +- source/blender/io/collada/MeshImporter.cpp | 1 - .../io/stl/importer/stl_import_mesh.cc | 1 - .../blender/io/usd/intern/usd_reader_mesh.cc | 3 - .../blender/io/usd/intern/usd_writer_mesh.cc | 52 ++- .../wavefront_obj/exporter/obj_export_mesh.cc | 8 +- .../wavefront_obj/importer/obj_import_mesh.cc | 2 +- .../wavefront_obj/tests/obj_importer_tests.cc | 2 +- source/blender/makesdna/DNA_mesh_types.h | 21 +- source/blender/makesrna/intern/rna_mesh.c | 25 +- source/blender/modifiers/intern/MOD_bevel.c | 5 - .../modifiers/intern/MOD_datatransfer.cc | 6 - .../blender/modifiers/intern/MOD_displace.cc | 11 +- .../blender/modifiers/intern/MOD_multires.cc | 11 +- .../modifiers/intern/MOD_normal_edit.cc | 37 +- .../blender/modifiers/intern/MOD_shrinkwrap.c | 3 +- .../blender/modifiers/intern/MOD_subsurf.cc | 8 +- .../modifiers/intern/MOD_triangulate.cc | 7 +- .../modifiers/intern/MOD_weighted_normal.cc | 36 +- .../node_geo_deform_curves_on_surface.cc | 8 +- .../node_geo_distribute_points_on_faces.cc | 50 ++- source/blender/render/intern/bake.cc | 14 +- source/blender/render/intern/multires_bake.cc | 3 +- 72 files changed, 589 insertions(+), 825 deletions(-) diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index dbfc9fd0799..439aa472d13 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -119,10 +119,6 @@ const float (*BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph bool *r_is_alloc))[3]; void BKE_editmesh_lnorspace_update(BMEditMesh *em, struct Mesh *me); -/** - * If auto-smooth not already set, set it. - */ -void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, struct Mesh *me); struct BoundBox *BKE_editmesh_cage_boundbox_get(struct Object *object, BMEditMesh *em); #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 38dc4280acc..de71ec0e02d 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -208,7 +208,7 @@ bool BKE_mesh_material_index_used(struct Mesh *me, short index); void BKE_mesh_material_index_clear(struct Mesh *me); void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len); void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth); -void BKE_mesh_auto_smooth_flag_set(struct Mesh *me, bool use_auto_smooth, float auto_smooth_angle); +void BKE_mesh_sharp_edges_set_from_angle(struct Mesh *me, float auto_smooth_angle); /** * Used for unit testing; compares two meshes, checking only @@ -321,6 +321,10 @@ const float (*BKE_mesh_vert_normals_ensure(const struct Mesh *mesh))[3]; */ const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]; +/** + * See #Mesh::corner_normals(). + * \warning May return null if the mesh is empty or has no polygons. + */ const float (*BKE_mesh_corner_normals_ensure(const struct Mesh *mesh))[3]; /** @@ -342,8 +346,6 @@ float (*BKE_mesh_vert_normals_for_write(struct Mesh *mesh))[3]; */ void BKE_mesh_vert_normals_clear_dirty(struct Mesh *mesh); -void BKE_mesh_corner_normals_clear_dirty(struct Mesh *mesh); - /** * Return true if the mesh vertex normals either are not stored or are dirty. * This can be used to help decide whether to transfer them when copying a mesh. diff --git a/source/blender/blenkernel/BKE_mesh.hh b/source/blender/blenkernel/BKE_mesh.hh index f6fa5adcc93..2e2381cf274 100644 --- a/source/blender/blenkernel/BKE_mesh.hh +++ b/source/blender/blenkernel/BKE_mesh.hh @@ -6,6 +6,8 @@ * \ingroup bke */ +#include "BLI_virtual_array.hh" + #include "BKE_mesh.h" namespace blender::bke::mesh { @@ -94,10 +96,8 @@ void normals_calc_loop(Span vert_positions, Span loop_to_poly_map, Span vert_normals, Span poly_normals, - const bool *sharp_edges, - const bool *sharp_faces, - bool use_split_normals, - float split_angle, + const VArray &sharp_edges, + const VArray &sharp_faces, short (*clnors_data)[2], MLoopNorSpaceArray *r_lnors_spacearr, MutableSpan r_loop_normals); @@ -109,7 +109,7 @@ void normals_loop_custom_set(Span vert_positions, Span corner_edges, Span vert_normals, Span poly_normals, - const bool *sharp_faces, + const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_loop_normals, short (*r_clnors_data)[2]); @@ -121,7 +121,7 @@ void normals_loop_custom_set_from_verts(Span vert_positions, Span corner_edges, Span vert_normals, Span poly_normals, - const bool *sharp_faces, + const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_vert_normals, short (*r_clnors_data)[2]); @@ -138,7 +138,7 @@ void edges_sharp_from_angle_set(OffsetIndices polys, Span corner_verts, Span corner_edges, Span poly_normals, - const bool *sharp_faces, + const VArray &sharp_faces, const float split_angle, MutableSpan sharp_edges); diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index b7041f62f68..c9a2c9fc860 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -143,13 +143,6 @@ enum { MREMAP_MODE_TOPOLOGY = MREMAP_MODE_VERT | MREMAP_MODE_EDGE | MREMAP_MODE_LOOP | MREMAP_MODE_POLY, }; -void BKE_mesh_remap_calc_source_cddata_masks_from_map_modes( - int vert_mode, - int edge_mode, - int loop_mode, - int poly_mode, - struct CustomData_MeshMasks *cddata_mask); - /** * Compute a value of the difference between both given meshes. * The smaller the result, the better the match. @@ -179,7 +172,6 @@ void BKE_mesh_remap_calc_verts_from_mesh(int mode, float ray_radius, const float (*vert_positions_dst)[3], int numverts_dst, - bool dirty_nors_dst, const struct Mesh *me_src, struct Mesh *me_dst, MeshPairRemap *r_map); @@ -192,7 +184,6 @@ void BKE_mesh_remap_calc_edges_from_mesh(int mode, int numverts_dst, const struct MEdge *edges_dst, int numedges_dst, - bool dirty_nors_dst, const struct Mesh *me_src, struct Mesh *me_dst, MeshPairRemap *r_map); @@ -207,19 +198,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode, const struct SpaceTransform *space_transform, float max_dist, float ray_radius, - struct Mesh *mesh_dst, + const struct Mesh *mesh_dst, const float (*vert_positions_dst)[3], int numverts_dst, const struct MEdge *edges_dst, int numedges_dst, const int *corner_verts_dst, - const int *corner_edges_dst, int numloops_dst, const blender::OffsetIndices polys_dst, - struct CustomData *ldata_dst, - bool use_split_nors_dst, - float split_angle_dst, - bool dirty_nors_dst, const struct Mesh *me_src, MeshRemapIslandsCalc gen_islands_src, float islands_precision_src, diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 48907c21bc8..043ea3c31da 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -45,8 +45,7 @@ void BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh); * For "smaller" changes to meshes like updating positions, consider calling a more specific update * function like #BKE_mesh_tag_positions_changed. * - * Also note that some derived caches like #CD_NORMAL and #CD_TANGENT are stored directly in - * #CustomData. + * Also note that some derived caches like #CD_TANGENT are stored directly in #CustomData. */ void BKE_mesh_runtime_clear_geometry(struct Mesh *mesh); diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index b52468bd70b..00443529c7a 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -440,27 +440,13 @@ static void add_orco_mesh( } } -static bool mesh_has_modifier_final_normals(const Mesh *mesh_input, - const CustomData_MeshMasks *final_datamask, - Mesh *mesh_final) -{ - /* Test if mesh has the required loop normals, in case an additional modifier - * evaluation from another instance or from an operator requests it but the - * initial normals were not loop normals. */ - const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); - - return (!calc_loop_normals || CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)); -} - static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, const CustomData_MeshMasks *final_datamask, const bool sculpt_dyntopo, Mesh *mesh_final) { /* Compute normals. */ - const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = mesh_final->normal_domain_all_info() == ATTR_DOMAIN_CORNER; /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; @@ -1007,13 +993,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, mesh_final = runtime->mesh_eval; } } - else if (!mesh_has_modifier_final_normals(mesh_input, &final_datamask, runtime->mesh_eval)) { - /* Modifier stack was (re-)evaluated with a request for additional normals - * different than the instanced mesh, can't instance anymore now. */ - mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); - mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); - mesh_calc_finalize(mesh_input, mesh_final); - } else { /* Already finalized by another instance, reuse. */ mesh_final = runtime->mesh_eval; @@ -1071,8 +1050,7 @@ bool editbmesh_modifier_is_enabled(const Scene *scene, static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, const CustomData_MeshMasks *final_datamask) { - const bool calc_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = mesh_final->normal_domain_all_info() == ATTR_DOMAIN_CORNER; SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; if (subsurf_runtime_data) { diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 012237db5b4..6edd008735c 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -692,8 +692,6 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, Mesh *mesh = BKE_mesh_new_nomain( offsets.vert.last(), offsets.edge.last(), offsets.loop.last(), offsets.poly.last()); - mesh->flag |= ME_AUTOSMOOTH; - mesh->smoothresh = DEG2RADF(180.0f); MutableSpan positions = mesh->vert_positions_for_write(); MutableSpan edges = mesh->edges_for_write(); MutableSpan poly_offsets = mesh->poly_offsets_for_write(); diff --git a/source/blender/blenkernel/intern/data_transfer.cc b/source/blender/blenkernel/intern/data_transfer.cc index f8d5f783772..483d2313783 100644 --- a/source/blender/blenkernel/intern/data_transfer.cc +++ b/source/blender/blenkernel/intern/data_transfer.cc @@ -71,7 +71,7 @@ void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types, r_data_masks->lmask |= CD_MASK_PROP_FLOAT2; } else if (cddata_type == CD_FAKE_LNOR) { - r_data_masks->lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; + r_data_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL; } } } @@ -347,60 +347,6 @@ static void data_transfer_mesh_attributes_transfer_default_color_string( /* ********** */ -/* Generic pre/post processing, only used by custom loop normals currently. */ - -static void data_transfer_dtdata_type_preprocess(const Mesh *me_src, - Mesh *me_dst, - const int dtdata_type, - const bool dirty_nors_dst) -{ - if (dtdata_type == DT_TYPE_LNOR) { - /* Compute custom normals into regular loop normals, which will be used for the transfer. */ - CustomData *ldata_dst = &me_dst->ldata; - - const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0; - const float split_angle_dst = me_dst->smoothresh; - - /* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */ - BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != nullptr); - (void)me_src; - - short(*custom_nors_dst)[2] = static_cast( - CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop)); - - /* Cache loop nors into a temp CDLayer. */ - blender::float3 *loop_nors_dst = static_cast( - CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->totloop)); - const bool do_loop_nors_dst = (loop_nors_dst == nullptr); - if (do_loop_nors_dst) { - loop_nors_dst = static_cast( - CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, me_dst->totloop)); - CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); - } - if (dirty_nors_dst || do_loop_nors_dst) { - const bool *sharp_edges = static_cast( - CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge")); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face")); - blender::bke::mesh::normals_calc_loop(me_dst->vert_positions(), - me_dst->edges(), - me_dst->polys(), - me_dst->corner_verts(), - me_dst->corner_edges(), - {}, - me_dst->vert_normals(), - me_dst->poly_normals(), - sharp_edges, - sharp_faces, - use_split_nors_dst, - split_angle_dst, - custom_nors_dst, - nullptr, - {loop_nors_dst, me_dst->totloop}); - } - } -} - static void data_transfer_dtdata_type_postprocess(Mesh *me_dst, const int dtdata_type, const bool changed) @@ -426,8 +372,8 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst, bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write(); bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face")); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); /* Note loop_nors_dst contains our custom normals as transferred from source... */ blender::bke::mesh::normals_loop_custom_set(me_dst->vert_positions(), me_dst->edges(), @@ -1303,8 +1249,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, SpaceTransform auto_space_transform; const Mesh *me_src; - /* Assumed always true if not using an evaluated mesh as destination. */ - bool dirty_nors_dst = true; const MDeformVert *mdef = nullptr; int vg_idx = -1; @@ -1323,7 +1267,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH)); if (me_dst) { - dirty_nors_dst = BKE_mesh_vert_normals_are_dirty(me_dst); /* Never create needed custom layers on passed destination mesh * (assumed to *not* be ob_dst->data, aka modifier case). */ use_create = false; @@ -1342,8 +1285,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, /* Get source evaluated mesh. */ BKE_object_data_transfer_dttypes_to_cdmask(data_types, &me_src_mask); - BKE_mesh_remap_calc_source_cddata_masks_from_map_modes( - map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, &me_src_mask); if (is_modifier) { me_src = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_src); @@ -1381,8 +1322,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, continue; } - data_transfer_dtdata_type_preprocess(me_src, me_dst, dtdata_type, dirty_nors_dst); - cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type); fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type); @@ -1436,7 +1375,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, ray_radius, positions_dst, num_verts_dst, - dirty_nors_dst, me_src, me_dst, &geom_map[VDATA]); @@ -1516,7 +1454,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, num_verts_dst, edges_dst.data(), edges_dst.size(), - dirty_nors_dst, me_src, me_dst, &geom_map[EDATA]); @@ -1569,8 +1506,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, const blender::Span edges_dst = me_dst->edges(); const blender::OffsetIndices polys_dst = me_dst->polys(); const blender::Span corner_verts_dst = me_dst->corner_verts(); - const blender::Span corner_edges_dst = me_dst->corner_edges(); - CustomData *ldata_dst = &me_dst->ldata; MeshRemapIslandsCalc island_callback = data_transfer_get_loop_islands_generator(cddata_type); @@ -1610,13 +1545,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, edges_dst.data(), edges_dst.size(), corner_verts_dst.data(), - corner_edges_dst.data(), corner_verts_dst.size(), polys_dst, - ldata_dst, - (me_dst->flag & ME_AUTOSMOOTH) != 0, - me_dst->smoothresh, - dirty_nors_dst, me_src, island_callback, islands_handling_precision, diff --git a/source/blender/blenkernel/intern/editmesh.cc b/source/blender/blenkernel/intern/editmesh.cc index 98a4eac6698..5a7fca101c1 100644 --- a/source/blender/blenkernel/intern/editmesh.cc +++ b/source/blender/blenkernel/intern/editmesh.cc @@ -263,31 +263,7 @@ float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3] void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me) { - BMesh *bm = em->bm; - - /* We need to create custom-loop-normals (CLNORS) data if none exist yet, - * otherwise there is no way to edit them. - * Similar code to #MESH_OT_customdata_custom_splitnormals_add operator, - * we want to keep same shading in case we were using auto-smooth so far. - * NOTE: there is a problem here, which is that if someone starts a normal editing operation on - * previously auto-smooth-ed mesh, and cancel that operation, generated CLNORS data remain, - * with related sharp edges (and hence auto-smooth is 'lost'). - * Not sure how critical this is, and how to fix that issue? */ - if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) { - if (me->flag & ME_AUTOSMOOTH) { - BM_edges_sharp_from_angle_set(bm, me->smoothresh); - } - } - - BM_lnorspace_update(bm); -} - -void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, Mesh *me) -{ - if (!(me->flag & ME_AUTOSMOOTH)) { - me->flag |= ME_AUTOSMOOTH; - BKE_editmesh_lnorspace_update(em, me); - } + BM_lnorspace_update(em->bm); } BoundBox *BKE_editmesh_cage_boundbox_get(Object *object, BMEditMesh * /*em*/) diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index f5d53b3514d..fedc2e3247a 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -32,6 +32,7 @@ #include "DNA_scene_types.h" #include "BKE_anim_data.h" +#include "BKE_attribute.hh" #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -2274,12 +2275,13 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, {reinterpret_cast(vert_normals), mesh->totvert}); } if (loop_normals_needed) { - short(*clnors)[2] = static_cast(CustomData_get_layer_for_write( - &mesh->ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); /* May be nullptr. */ - const bool *sharp_edges = static_cast( - CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge")); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); + const blender::bke::AttributeAccessor attributes = mesh->attributes(); + const blender::VArray sharp_edges = attributes.lookup_or_default( + "sharp_edge", ATTR_DOMAIN_EDGE, false); + const blender::VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); + const short(*custom_normals)[2] = static_cast( + CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)); blender::bke::mesh::normals_calc_loop( {reinterpret_cast(positions), mesh->totvert}, edges, @@ -2291,9 +2293,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, {reinterpret_cast(poly_normals), polys.size()}, sharp_edges, sharp_faces, - (mesh->flag & ME_AUTOSMOOTH) != 0, - mesh->smoothresh, - clnors, + custom_normals, nullptr, {reinterpret_cast(r_loop_normals), corner_verts.size()}); } diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 240acd28d38..aaf6171201b 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1035,7 +1035,6 @@ void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src) /* Copy general settings. */ me_dst->editflag = me_src->editflag; me_dst->flag = me_src->flag; - me_dst->smoothresh = me_src->smoothresh; me_dst->remesh_voxel_size = me_src->remesh_voxel_size; me_dst->remesh_voxel_adaptivity = me_src->remesh_voxel_adaptivity; me_dst->remesh_mode = me_src->remesh_mode; @@ -1521,17 +1520,23 @@ void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth) } } -void BKE_mesh_auto_smooth_flag_set(Mesh *me, - const bool use_auto_smooth, - const float auto_smooth_angle) +void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float auto_smooth_angle) { - if (use_auto_smooth) { - me->flag |= ME_AUTOSMOOTH; - me->smoothresh = auto_smooth_angle; - } - else { - me->flag &= ~ME_AUTOSMOOTH; - } + using namespace blender; + using namespace blender::bke; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( + "sharp_edge", ATTR_DOMAIN_EDGE); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); + bke::mesh::edges_sharp_from_angle_set(me->polys(), + me->corner_verts(), + me->corner_edges(), + me->poly_normals(), + sharp_faces, + auto_smooth_angle, + sharp_edges.span); + sharp_edges.finish(); } void BKE_mesh_looptri_get_real_edges(const MEdge *edges, diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 3b1906f3bb7..06318021d0b 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -1029,7 +1029,6 @@ Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain, mesh_in_bmain->mat = mesh->mat; mesh_in_bmain->totcol = mesh->totcol; mesh_in_bmain->flag = mesh->flag; - mesh_in_bmain->smoothresh = mesh->smoothresh; mesh->mat = nullptr; BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, nullptr); diff --git a/source/blender/blenkernel/intern/mesh_iterators.cc b/source/blender/blenkernel/intern/mesh_iterators.cc index 7f3fe18f3d0..5a3255146b8 100644 --- a/source/blender/blenkernel/intern/mesh_iterators.cc +++ b/source/blender/blenkernel/intern/mesh_iterators.cc @@ -165,9 +165,10 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos; /* XXX: investigate using EditMesh data. */ - const float(*loop_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? - BKE_mesh_corner_normals_ensure(mesh) : - nullptr; + blender::Span corner_normals; + if (flag & MESH_FOREACH_USE_NORMAL) { + corner_normals = mesh->corner_normals(); + } int f_idx; @@ -180,15 +181,17 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, do { const BMVert *eve = l_iter->v; const int v_idx = BM_elem_index_get(eve); - const float *no = loop_normals ? *loop_normals++ : nullptr; + const float *no = corner_normals.is_empty() ? nullptr : + &corner_normals[BM_elem_index_get(l_iter)].x; func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no); } while ((l_iter = l_iter->next) != l_first); } } else { - const float(*loop_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? - BKE_mesh_corner_normals_ensure(mesh) : - nullptr; + blender::Span corner_normals; + if (flag & MESH_FOREACH_USE_NORMAL) { + corner_normals = mesh->corner_normals(); + } const float(*positions)[3] = BKE_mesh_vert_positions(mesh); const blender::OffsetIndices polys = mesh->polys(); @@ -200,10 +203,11 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, if (v_index || f_index) { for (const int poly_i : polys.index_range()) { - for (const int vert : corner_verts.slice(polys[poly_i])) { + for (const int corner : polys[poly_i]) { + const int vert = corner_verts[corner]; const int v_idx = v_index ? v_index[vert] : vert; const int f_idx = f_index ? f_index[poly_i] : poly_i; - const float *no = loop_normals ? *loop_normals++ : nullptr; + const float *no = corner_normals.is_empty() ? nullptr : &corner_normals[corner].x; if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) { continue; } @@ -213,11 +217,10 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, } else { for (const int poly_i : polys.index_range()) { - for (const int vert : corner_verts.slice(polys[poly_i])) { - const int v_idx = vert; - const int f_idx = poly_i; - const float *no = loop_normals ? *loop_normals++ : nullptr; - func(userData, v_idx, f_idx, positions[vert], no); + for (const int corner : polys[poly_i]) { + const int vert = corner_verts[corner]; + const float *no = corner_normals.is_empty() ? nullptr : &corner_normals[corner].x; + func(userData, vert, poly_i, positions[vert], no); } } } diff --git a/source/blender/blenkernel/intern/mesh_mirror.cc b/source/blender/blenkernel/intern/mesh_mirror.cc index 566b2c1fbd2..86278e58559 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.cc +++ b/source/blender/blenkernel/intern/mesh_mirror.cc @@ -12,6 +12,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "BKE_attribute.hh" #include "BKE_deform.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" @@ -375,8 +376,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, } /* handle custom split normals */ - if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) && - CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->totpoly > 0) { + if (ob->type == OB_MESH && CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && + result->totpoly > 0) { blender::Array loop_normals(result_corner_verts.size()); CustomData *ldata = &result->ldata; short(*clnors)[2] = static_cast( @@ -391,10 +392,11 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, /* calculate custom normals into loop_normals, then mirror first half into second half */ - const bool *sharp_edges = static_cast( - CustomData_get_layer_named(&result->edata, CD_PROP_BOOL, "sharp_edge")); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&result->pdata, CD_PROP_BOOL, "sharp_face")); + const blender::bke::AttributeAccessor attributes = result->attributes(); + const blender::VArray sharp_edges = attributes.lookup_or_default( + "sharp_edge", ATTR_DOMAIN_EDGE, false); + const blender::VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_calc_loop(result->vert_positions(), result_edges, result_polys, @@ -405,8 +407,6 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, result->poly_normals(), sharp_edges, sharp_faces, - true, - result->smoothresh, clnors, &lnors_spacearr, loop_normals); diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 4875adb8897..361bc9d346e 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -313,6 +313,103 @@ void normals_calc_poly_vert(const Span positions, /** \name Mesh Normal Calculation * \{ */ +enum class BoolArrayMix { + None, + AllFalse, + AllTrue, + Mixed, +}; +BoolArrayMix bool_array_mix_calc(const VArray &varray, + const blender::IndexRange range_to_check) +{ + using namespace blender; + if (varray.is_empty()) { + return BoolArrayMix::None; + } + const CommonVArrayInfo info = varray.common_info(); + if (info.type == CommonVArrayInfo::Type::Single) { + return *static_cast(info.data) ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + } + if (info.type == CommonVArrayInfo::Type::Span) { + const Span span(static_cast(info.data), varray.size()); + return threading::parallel_reduce( + range_to_check, + 4096, + BoolArrayMix::None, + [&](const IndexRange range, const BoolArrayMix init) { + if (init == BoolArrayMix::Mixed) { + return init; + } + + const Span slice = span.slice(range); + const bool first = slice.first(); + for (const bool value : slice.drop_front(1)) { + if (value != first) { + return BoolArrayMix::Mixed; + } + } + return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + }, + [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); + } + return threading::parallel_reduce( + range_to_check, + 2048, + BoolArrayMix::None, + [&](const IndexRange range, const BoolArrayMix init) { + if (init == BoolArrayMix::Mixed) { + return init; + } + /* Alternatively, this could use #materialize to retrieve many values at once. */ + const bool first = varray[range.first()]; + for (const int64_t i : range.drop_front(1)) { + if (varray[i] != first) { + return BoolArrayMix::Mixed; + } + } + return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + }, + [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); +} + +BoolArrayMix bool_array_mix_calc(const VArray &varray) +{ + return bool_array_mix_calc(varray, varray.index_range()); +} + +eAttrDomain Mesh::normal_domain_all_info() const +{ + using namespace blender; + using namespace blender::bke; + const short(*custom_normals)[2] = static_cast( + CustomData_get_layer(&this->ldata, CD_CUSTOMLOOPNORMAL)); + if (custom_normals) { + return ATTR_DOMAIN_CORNER; + } + + const AttributeAccessor attributes = this->attributes(); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); + + const BoolArrayMix face_mix = bool_array_mix_calc(sharp_faces); + if (face_mix == BoolArrayMix::AllTrue) { + return ATTR_DOMAIN_FACE; + } + + const VArray sharp_edges = attributes.lookup_or_default( + "sharp_edge", ATTR_DOMAIN_EDGE, false); + const BoolArrayMix edge_mix = bool_array_mix_calc(sharp_edges); + if (edge_mix == BoolArrayMix::AllTrue) { + return ATTR_DOMAIN_FACE; + } + + if (edge_mix == BoolArrayMix::AllFalse && face_mix == BoolArrayMix::AllFalse) { + return ATTR_DOMAIN_POINT; + } + + return ATTR_DOMAIN_CORNER; +} + blender::Span Mesh::vert_normals() const { if (!this->runtime->vert_normals_dirty) { @@ -383,63 +480,77 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3] return reinterpret_cast(mesh->vert_normals().data()); } -const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] +blender::Span Mesh::corner_normals() const { - if (!BKE_mesh_corner_normals_are_dirty(mesh)) { - BLI_assert(mesh->runtime->corner_normals != nullptr || mesh->totloop == 0); - return mesh->runtime->corner_normals; + using namespace blender; + using namespace blender::bke; + if (!this->runtime->corner_normals_dirty) { + BLI_assert(this->runtime->corner_normals.size() == this->totloop); + return this->runtime->corner_normals; } - if (mesh->totpoly == 0) { - return nullptr; + std::lock_guard lock{this->runtime->normals_mutex}; + if (!this->runtime->corner_normals_dirty) { + BLI_assert(this->runtime->corner_normals.size() == this->totloop); + return this->runtime->corner_normals; } - const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh); - const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(mesh); - - std::lock_guard lock{mesh->runtime->normals_mutex}; - if (!BKE_mesh_corner_normals_are_dirty(mesh)) { - BLI_assert(mesh->runtime->corner_normals != nullptr); - return mesh->runtime->corner_normals; - } - - float(*corner_normals)[3]; - /* Isolate task because a mutex is locked and computing normals is multi-threaded. */ - blender::threading::isolate_task([&]() { - Mesh &mesh_mutable = *const_cast(mesh); - const Span verts = mesh_mutable.verts(); - const Span edges = mesh_mutable.edges(); - const Span polys = mesh_mutable.polys(); - const Span loops = mesh_mutable.loops(); + threading::isolate_task([&]() { + const OffsetIndices polys = this->polys(); + this->runtime->corner_normals.reinitialize(this->totloop); + MutableSpan corner_normals = this->runtime->corner_normals; + switch (this->normal_domain_all_info()) { + case ATTR_DOMAIN_POINT: { + array_utils::gather(this->vert_normals(), this->corner_verts(), corner_normals); + break; + } + case ATTR_DOMAIN_FACE: { + const Span poly_normals = this->poly_normals(); + threading::parallel_for(poly_normals.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + corner_normals.slice(polys[i]).fill(poly_normals[i]); + } + }); + break; + } + case ATTR_DOMAIN_CORNER: { + const AttributeAccessor attributes = this->attributes(); + const VArray sharp_edges = attributes.lookup_or_default( + "sharp_edge", ATTR_DOMAIN_EDGE, false); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); + const short(*custom_normals)[2] = static_cast( + CustomData_get_layer(&this->ldata, CD_CUSTOMLOOPNORMAL)); - if (mesh_mutable.runtime->corner_normals == nullptr) { - mesh_mutable.runtime->corner_normals = (float(*)[3])MEM_malloc_arrayN( - mesh_mutable.totloop, sizeof(float[3]), __func__); + bke::mesh::normals_calc_loop(this->vert_positions(), + this->edges(), + this->polys(), + this->corner_verts(), + this->corner_edges(), + {}, + this->vert_normals(), + this->poly_normals(), + sharp_edges, + sharp_faces, + custom_normals, + nullptr, + this->runtime->corner_normals); + break; + } + default: + BLI_assert_unreachable(); } - const short(*custom_normals)[2] = (const short(*)[2])CustomData_get_layer(&mesh->ldata, - CD_CUSTOMLOOPNORMAL); - - BKE_mesh_normals_loop_split(verts.data(), - vert_normals, - verts.size(), - edges.data(), - edges.size(), - loops.data(), - corner_normals, - loops.size(), - polys.data(), - poly_normals, - polys.size(), - true, - mesh->smoothresh, - nullptr, - custom_normals, - nullptr); - - BKE_mesh_corner_normals_clear_dirty(&mesh_mutable); + this->runtime->corner_normals_dirty = false; }); + + return this->runtime->corner_normals; +} + +const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] +{ + return reinterpret_cast(mesh->corner_normals().data()); } void BKE_mesh_ensure_normals_for_display(Mesh *mesh) @@ -782,17 +893,14 @@ static void mesh_edges_sharp_tag(const OffsetIndices polys, const Span corner_edges, const Span loop_to_poly_map, const Span poly_normals, - const Span sharp_faces, - const Span sharp_edges, + const VArray &sharp_faces, + const VArray &sharp_edges, const bool check_angle, const float split_angle, MutableSpan edge_to_loops, MutableSpan r_sharp_edges) { const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; - auto poly_is_smooth = [&](const int poly_i) { - return sharp_faces.is_empty() || !sharp_faces[poly_i]; - }; for (const int poly_i : polys.index_range()) { for (const int loop_index : polys[poly_i]) { @@ -806,7 +914,7 @@ static void mesh_edges_sharp_tag(const OffsetIndices polys, /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */ e2l[0] = loop_index; /* We have to check this here too, else we might miss some flat faces!!! */ - e2l[1] = (poly_is_smooth(poly_i)) ? INDEX_UNSET : INDEX_INVALID; + e2l[1] = sharp_faces[poly_i] ? INDEX_INVALID : INDEX_UNSET; } else if (e2l[1] == INDEX_UNSET) { const bool is_angle_sharp = (check_angle && @@ -818,14 +926,14 @@ static void mesh_edges_sharp_tag(const OffsetIndices polys, * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the * same vertex, or angle between both its polys' normals is above split_angle value. */ - if (!poly_is_smooth(poly_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) || - vert_i == corner_verts[e2l[0]] || is_angle_sharp) { + if (sharp_faces[poly_i] || sharp_edges[edge_i] || vert_i == corner_verts[e2l[0]] || + is_angle_sharp) { /* NOTE: we are sure that loop != 0 here ;). */ e2l[1] = INDEX_INVALID; /* We want to avoid tagging edges as sharp when it is already defined as such by * other causes than angle threshold. */ - if (!r_sharp_edges.is_empty() && is_angle_sharp) { + if (is_angle_sharp) { r_sharp_edges[edge_i] = true; } } @@ -839,9 +947,52 @@ static void mesh_edges_sharp_tag(const OffsetIndices polys, /* We want to avoid tagging edges as sharp when it is already defined as such by * other causes than angle threshold. */ - if (!r_sharp_edges.is_empty()) { - r_sharp_edges[edge_i] = false; + r_sharp_edges[edge_i] = false; + } + /* Else, edge is already 'disqualified' (i.e. sharp)! */ + } + } +} + +static void build_edge_to_loop_map(const OffsetIndices polys, + const Span corner_verts, + const Span corner_edges, + const VArray &sharp_faces, + const VArray &sharp_edges, + MutableSpan edge_to_loops) +{ + + for (const int poly_i : polys.index_range()) { + for (const int loop_index : polys[poly_i]) { + const int vert_i = corner_verts[loop_index]; + const int edge_i = corner_edges[loop_index]; + + int2 &e2l = edge_to_loops[edge_i]; + + /* Check whether current edge might be smooth or sharp */ + if ((e2l[0] | e2l[1]) == 0) { + /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */ + e2l[0] = loop_index; + /* We have to check this here too, else we might miss some flat faces!!! */ + e2l[1] = sharp_faces[poly_i] ? INDEX_INVALID : INDEX_UNSET; + } + else if (e2l[1] == INDEX_UNSET) { + /* Second loop using this edge, time to test its sharpness. + * An edge is sharp if it is tagged as such, or its face is not smooth, + * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the + * same vertex, or angle between both its polys' normals is above split_angle value. + */ + if (sharp_faces[poly_i] || sharp_edges[edge_i] || vert_i == corner_verts[e2l[0]]) { + /* NOTE: we are sure that loop != 0 here ;). */ + e2l[1] = INDEX_INVALID; } + else { + e2l[1] = loop_index; + } + } + else if (!IS_EDGE_SHARP(e2l)) { + /* More than two loops using this edge, tag as sharp if not yet done. */ + e2l[1] = INDEX_INVALID; } /* Else, edge is already 'disqualified' (i.e. sharp)! */ } @@ -852,7 +1003,7 @@ void edges_sharp_from_angle_set(const OffsetIndices polys, const Span corner_verts, const Span corner_edges, const Span poly_normals, - const bool *sharp_faces, + const VArray &sharp_faces, const float split_angle, MutableSpan sharp_edges) { @@ -872,8 +1023,8 @@ void edges_sharp_from_angle_set(const OffsetIndices polys, corner_edges, loop_to_poly, poly_normals, - Span(sharp_faces, sharp_faces ? polys.size() : 0), - sharp_edges, + sharp_faces, + VArray::ForSpan(sharp_edges), true, split_angle, edge_to_loops, @@ -1436,39 +1587,12 @@ void normals_calc_loop(const Span vert_positions, const Span loop_to_poly_map, const Span vert_normals, const Span poly_normals, - const bool *sharp_edges, - const bool *sharp_faces, - bool use_split_normals, - float split_angle, + const VArray &sharp_edges, + const VArray &sharp_faces, short (*clnors_data)[2], MLoopNorSpaceArray *r_lnors_spacearr, MutableSpan r_loop_normals) { - /* For now this is not supported. - * If we do not use split normals, we do not generate anything fancy! */ - BLI_assert(use_split_normals || !(r_lnors_spacearr)); - - if (!use_split_normals) { - /* In this case, simply fill `r_loop_normals` with `vert_normals` - * (or `poly_normals` for flat faces), quite simple! - * Note this is done here to keep some logic and consistency in this quite complex code, - * since we may want to use loop_normals even when mesh's 'autosmooth' is disabled - * (see e.g. mesh mapping code). As usual, we could handle that on case-by-case basis, - * but simpler to keep it well confined here. */ - for (const int poly_index : polys.index_range()) { - const bool is_poly_flat = sharp_faces && sharp_faces[poly_index]; - for (const int corner : polys[poly_index]) { - if (is_poly_flat) { - copy_v3_v3(r_loop_normals[corner], poly_normals[poly_index]); - } - else { - copy_v3_v3(r_loop_normals[corner], vert_normals[corner_verts[corner]]); - } - } - } - return; - } - /** * Mapping edge -> loops. * If that edge is used by more than two loops (polys), @@ -1496,9 +1620,6 @@ void normals_calc_loop(const Span vert_positions, loop_to_poly = loop_to_poly_map; } - /* When using custom loop normals, disable the angle feature! */ - const bool check_angle = (split_angle < float(M_PI)) && (clnors_data == nullptr); - MLoopNorSpaceArray _lnors_spacearr = {nullptr}; #ifdef DEBUG_TIME @@ -1534,17 +1655,8 @@ void normals_calc_loop(const Span vert_positions, array_utils::gather(vert_normals, corner_verts, r_loop_normals, 1024); /* This first loop check which edges are actually smooth, and compute edge vectors. */ - mesh_edges_sharp_tag(polys, - corner_verts, - corner_edges, - loop_to_poly, - poly_normals, - Span(sharp_faces, sharp_faces ? polys.size() : 0), - Span(sharp_edges, sharp_edges ? edges.size() : 0), - check_angle, - split_angle, - edge_to_loops, - {}); + build_edge_to_loop_map( + polys, corner_verts, corner_edges, sharp_faces, sharp_edges, edge_to_loops); if (corner_verts.size() < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { /* Not enough loops to be worth the whole threading overhead. */ @@ -1588,7 +1700,7 @@ static void mesh_normals_loop_custom_set(Span positions, Span corner_edges, Span vert_normals, Span poly_normals, - const bool *sharp_faces, + const VArray &sharp_faces, const bool use_vertices, MutableSpan r_custom_loop_normals, MutableSpan sharp_edges, @@ -1603,10 +1715,6 @@ static void mesh_normals_loop_custom_set(Span positions, BitVector<> done_loops(corner_verts.size(), false); Array loop_normals(corner_verts.size()); const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys); - /* In this case we always consider split nors as ON, - * and do not want to use angle to define smooth fans! */ - const bool use_split_normals = true; - const float split_angle = float(M_PI); BLI_SMALLSTACK_DECLARE(clnors_data, short *); @@ -1619,10 +1727,8 @@ static void mesh_normals_loop_custom_set(Span positions, loop_to_poly, vert_normals, poly_normals, - sharp_edges.data(), + VArray::ForSpan(sharp_edges), sharp_faces, - use_split_normals, - split_angle, r_clnors_data, &lnors_spacearr, loop_normals); @@ -1745,10 +1851,8 @@ static void mesh_normals_loop_custom_set(Span positions, loop_to_poly, vert_normals, poly_normals, - sharp_edges.data(), + VArray::ForSpan(sharp_edges), sharp_faces, - use_split_normals, - split_angle, r_clnors_data, &lnors_spacearr, loop_normals); @@ -1819,7 +1923,7 @@ void normals_loop_custom_set(const Span vert_positions, const Span corner_edges, const Span vert_normals, const Span poly_normals, - const bool *sharp_faces, + const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_loop_normals, short (*r_clnors_data)[2]) @@ -1845,7 +1949,7 @@ void normals_loop_custom_set_from_verts(const Span vert_positions, const Span corner_edges, const Span vert_normals, const Span poly_normals, - const bool *sharp_faces, + const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_vert_normals, short (*r_clnors_data)[2]) @@ -1881,8 +1985,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const MutableAttributeAccessor attributes = mesh->attributes_for_write(); SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); mesh_normals_loop_custom_set(mesh->vert_positions(), mesh->edges(), diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index 2af40536e65..da485a22929 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -296,20 +296,6 @@ void BKE_mesh_remap_find_best_match_from_mesh(const float (*vert_positions_dst)[ /** \name Mesh to Mesh Mapping * \{ */ -void BKE_mesh_remap_calc_source_cddata_masks_from_map_modes(const int /*vert_mode*/, - const int /*edge_mode*/, - const int loop_mode, - const int /*poly_mode*/, - CustomData_MeshMasks *r_cddata_mask) -{ - /* vert, edge and poly mapping modes never need extra cddata from source object. */ - const bool need_lnors_src = (loop_mode & MREMAP_USE_LOOP) && (loop_mode & MREMAP_USE_NORMAL); - - if (need_lnors_src) { - r_cddata_mask->lmask |= CD_MASK_NORMAL; - } -} - void BKE_mesh_remap_init(MeshPairRemap *map, const int items_num) { MemArena *mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); @@ -462,7 +448,6 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, const float ray_radius, const float (*vert_positions_dst)[3], const int numverts_dst, - const bool /*dirty_nors_dst*/, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map) @@ -685,7 +670,6 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const int numverts_dst, const MEdge *edges_dst, const int numedges_dst, - const bool /*dirty_nors_dst*/, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map) @@ -1219,19 +1203,14 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const SpaceTransform *space_transform, const float max_dist, const float ray_radius, - Mesh *mesh_dst, + const Mesh *mesh_dst, const float (*vert_positions_dst)[3], const int numverts_dst, const MEdge *edges_dst, const int numedges_dst, const int *corner_verts_dst, - const int *corner_edges_dst, const int numloops_dst, const blender::OffsetIndices polys_dst, - CustomData *ldata_dst, - const bool use_split_nors_dst, - const float split_angle_dst, - const bool dirty_nors_dst, const Mesh *me_src, MeshRemapIslandsCalc gen_islands_src, const float islands_precision_src, @@ -1276,7 +1255,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, blender::Span loop_normals_src; blender::Span poly_normals_dst; - blender::float3 *loop_normals_dst; + blender::Span loop_normals_dst; blender::Array poly_cents_src; @@ -1333,13 +1312,13 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, poly_normals_dst = mesh_dst->poly_normals(); } if (need_lnors_dst) { - loop_normals_dst = BKE_mesh_corner_normals_ensure(mesh_dst); + loop_normals_dst = mesh_dst->corner_normals(); } if (need_pnors_src) { - poly_normals_src = BKE_mesh_poly_normals_ensure(me_src); + poly_normals_src = me_src->poly_normals(); } if (need_lnors_src) { - loop_normals_src = BKE_mesh_corner_normals_ensure(me_src); + loop_normals_src = me_src->corner_normals(); } } diff --git a/source/blender/blenkernel/intern/mesh_tangent.cc b/source/blender/blenkernel/intern/mesh_tangent.cc index 4df0a57d071..2088a7eafec 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.cc +++ b/source/blender/blenkernel/intern/mesh_tangent.cc @@ -135,15 +135,16 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, return; } - BKE_mesh_calc_loop_tangent_single_ex(BKE_mesh_vert_positions(mesh), - mesh->totvert, - mesh->corner_verts().data(), - r_looptangents, - BKE_mesh_corner_normals_ensure(mesh), - reinterpret_cast(uv_map.data()), - mesh->totloop, - mesh->polys(), - reports); + BKE_mesh_calc_loop_tangent_single_ex( + BKE_mesh_vert_positions(mesh), + mesh->totvert, + mesh->corner_verts().data(), + r_looptangents, + reinterpret_cast(mesh->corner_normals().data()), + reinterpret_cast(uv_map.data()), + mesh->totloop, + mesh->polys(), + reports); } /** \} */ @@ -579,7 +580,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval, tangent_names_len, reinterpret_cast(me_eval->vert_normals().data()), reinterpret_cast(me_eval->poly_normals().data()), - BKE_mesh_corner_normals_ensure(me_eval), + reinterpret_cast(me_eval->corner_normals().data()), /* may be nullptr */ static_cast(CustomData_get_layer(&me_eval->vdata, CD_ORCO)), /* result */ diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index f274e483d31..36add44ba59 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -338,8 +338,8 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me) Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me); if (use_clnors) { - const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(subdiv_mesh); - BKE_mesh_set_custom_normals(subdiv_mesh, lnors); + BKE_mesh_set_custom_normals( + subdiv_mesh, reinterpret_cast(subdiv_mesh->corner_normals().data())); } if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) { diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index 763d6ab673d..7114841b98c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -138,8 +138,8 @@ bool BKE_shrinkwrap_init_tree( if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) { data->poly_normals = reinterpret_cast(mesh->poly_normals().data()); - if ((mesh->flag & ME_AUTOSMOOTH) != 0) { - data->clnors = BKE_mesh_corner_normals_ensure(mesh); + if (mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + data->clnors = reinterpret_cast(mesh->corner_normals().data()); } } diff --git a/source/blender/blenkernel/intern/subdiv_modifier.cc b/source/blender/blenkernel/intern/subdiv_modifier.cc index 1b135b71114..4301d9887a6 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.cc +++ b/source/blender/blenkernel/intern/subdiv_modifier.cc @@ -84,14 +84,8 @@ static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene, bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh) { - return (smd->flags & eSubsurfModifierFlag_UseCustomNormals) && (mesh->flag & ME_AUTOSMOOTH) && - CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); -} - -static bool subsurf_modifier_use_autosmooth_or_split_normals(const SubsurfModifierData *smd, - const Mesh *mesh) -{ - return (mesh->flag & ME_AUTOSMOOTH) || BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh); + return smd->flags & eSubsurfModifierFlag_UseCustomNormals && + mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER; } static bool is_subdivision_evaluation_possible_on_gpu() @@ -125,7 +119,7 @@ bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(const SubsurfMod return false; } - return subsurf_modifier_use_autosmooth_or_split_normals(smd, mesh); + return BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh); } bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene, @@ -140,7 +134,7 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene, /* Deactivate GPU subdivision if autosmooth or custom split normals are used as those are * complicated to support on GPU, and should really be separate workflows. */ - if (subsurf_modifier_use_autosmooth_or_split_normals(smd, mesh)) { + if (BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh)) { return false; } diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.cc b/source/blender/bmesh/intern/bmesh_mesh_normals.cc index 6f0f7af7a6b..4e5c844c1d9 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.cc @@ -989,7 +989,6 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( const float (*fnos)[3], float (*r_lnos)[3], const bool do_rebuild, - const float split_angle_cos, /* TLS */ MLoopNorSpaceArray *r_lnors_spacearr, BLI_Stack *edge_vectors, @@ -1067,8 +1066,7 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, MLoopNorSpaceArray *r_lnors_spacearr, const short (*clnors_data)[2], const int cd_loop_clnors_offset, - const bool do_rebuild, - const float split_angle_cos) + const bool do_rebuild) { BMIter fiter; BMFace *f_curr; @@ -1161,7 +1159,6 @@ typedef struct BMLoopsCalcNormalsWithCoordsData { const short (*clnors_data)[2]; int cd_loop_clnors_offset; bool do_rebuild; - float split_angle_cos; /* Output. */ float (*r_lnos)[3]; @@ -1254,7 +1251,6 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors_fn( data->r_lnos, data->do_rebuild, - data->split_angle_cos, /* Thread local. */ tls_data->lnors_spacearr, tls_data->edge_vectors, @@ -1269,8 +1265,7 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm, MLoopNorSpaceArray *r_lnors_spacearr, const short (*clnors_data)[2], const int cd_loop_clnors_offset, - const bool do_rebuild, - const float split_angle_cos) + const bool do_rebuild) { const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); MLoopNorSpaceArray _lnors_spacearr = {nullptr}; @@ -1321,7 +1316,6 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm, data.clnors_data = clnors_data; data.cd_loop_clnors_offset = cd_loop_clnors_offset; data.do_rebuild = do_rebuild; - data.split_angle_cos = split_angle_cos; BM_iter_parallel(bm, BM_VERTS_OF_MESH, @@ -1344,30 +1338,15 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, MLoopNorSpaceArray *r_lnors_spacearr, const short (*clnors_data)[2], const int cd_loop_clnors_offset, - const bool do_rebuild, - const float split_angle_cos) + const bool do_rebuild) { if (bm->totloop < BM_OMP_LIMIT) { - bm_mesh_loops_calc_normals__single_threaded(bm, - vcos, - fnos, - r_lnos, - r_lnors_spacearr, - clnors_data, - cd_loop_clnors_offset, - do_rebuild, - split_angle_cos); + bm_mesh_loops_calc_normals__single_threaded( + bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); } else { - bm_mesh_loops_calc_normals__multi_threaded(bm, - vcos, - fnos, - r_lnos, - r_lnors_spacearr, - clnors_data, - cd_loop_clnors_offset, - do_rebuild, - split_angle_cos); + bm_mesh_loops_calc_normals__multi_threaded( + bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); } } @@ -1689,7 +1668,6 @@ void BM_loops_calc_normal_vcos(BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], const bool use_split_normals, - const float split_angle, float (*r_lnos)[3], MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], @@ -1699,15 +1677,8 @@ void BM_loops_calc_normal_vcos(BMesh *bm, const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); if (use_split_normals) { - bm_mesh_loops_calc_normals(bm, - vcos, - fnos, - r_lnos, - r_lnors_spacearr, - clnors_data, - cd_loop_clnors_offset, - do_rebuild, - has_clnors ? -1.0f : cosf(split_angle)); + bm_mesh_loops_calc_normals( + bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); } else { BLI_assert(!r_lnors_spacearr); @@ -1736,7 +1707,6 @@ void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]) nullptr, nullptr, true, - M_PI, r_lnors, bm->lnor_spacearr, nullptr, @@ -1861,7 +1831,6 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor) nullptr, nullptr, true, - M_PI, r_lnors, bm->lnor_spacearr, nullptr, @@ -1937,17 +1906,8 @@ void BM_lnorspace_err(BMesh *bm) int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); float(*lnors)[3] = static_cast(MEM_callocN(sizeof(*lnors) * bm->totloop, __func__)); - BM_loops_calc_normal_vcos(bm, - nullptr, - nullptr, - nullptr, - true, - M_PI, - lnors, - temp, - nullptr, - cd_loop_clnors_offset, - true); + BM_loops_calc_normal_vcos( + bm, nullptr, nullptr, nullptr, true, lnors, temp, nullptr, cd_loop_clnors_offset, true); for (int i = 0; i < bm->totloop; i++) { int j = 0; diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.h b/source/blender/bmesh/intern/bmesh_mesh_normals.h index 51768af2ab0..6df66a70186 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.h +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.h @@ -60,7 +60,6 @@ void BM_loops_calc_normal_vcos(BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], bool use_split_normals, - float split_angle, float (*r_lnos)[3], struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index f892b446318..7a9e762ef73 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1329,8 +1329,7 @@ void DepsgraphRelationBuilder::build_constraints(ID *id, bool track = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0; if (track || BKE_shrinkwrap_needs_normals(scon->shrinkType, scon->shrinkMode)) { add_customdata_mask(ct->tar, - DEGCustomDataMeshMasks::MaskVert(CD_MASK_NORMAL) | - DEGCustomDataMeshMasks::MaskLoop(CD_MASK_CUSTOMLOOPNORMAL)); + DEGCustomDataMeshMasks::MaskLoop(CD_MASK_CUSTOMLOOPNORMAL)); } if (scon->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) { add_special_eval_flag(&ct->tar->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index d3ed3e532e3..c389eb3c5ec 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -338,8 +338,6 @@ void mesh_render_data_update_looptris(MeshRenderData *mr, void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_flag) { Mesh *me = mr->me; - const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0; - const float split_angle = is_auto_smooth ? me->smoothresh : float(M_PI); if (mr->extract_type != MR_EXTRACT_BMESH) { /* Mesh */ @@ -347,7 +345,9 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) { mr->poly_normals = mr->me->poly_normals(); } - if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { + if (((data_flag & MR_DATA_LOOP_NOR) && + mr->me->normal_domain_all_info() == ATTR_DOMAIN_CORNER) || + (data_flag & MR_DATA_TAN_LOOP_NOR)) { mr->corner_normals = mr->me->corner_normals(); } } @@ -356,7 +356,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ if (data_flag & MR_DATA_POLY_NOR) { /* Use #BMFace.no instead. */ } - if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { + if (((data_flag & MR_DATA_LOOP_NOR)) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { const float(*vert_coords)[3] = nullptr; const float(*vert_normals)[3] = nullptr; @@ -374,8 +374,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ vert_coords, vert_normals, poly_normals, - is_auto_smooth, - split_angle, + true, reinterpret_cast(mr->bm_loop_normals.data()), nullptr, nullptr, diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 390a341f235..0adb29bc27d 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -2161,9 +2161,7 @@ static bool draw_subdiv_create_requested_buffers(Object *ob, runtime_data->stats_totloop = draw_cache->num_subdiv_loops; draw_cache->use_custom_loop_normals = (runtime_data->use_loop_normals) && - (mesh_eval->flag & ME_AUTOSMOOTH) && - CustomData_has_layer(&mesh_eval->ldata, - CD_CUSTOMLOOPNORMAL); + mesh_eval->normal_domain_all_info() == ATTR_DOMAIN_CORNER; if (DRW_ibo_requested(mbc->buff.ibo.tris)) { draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache->mat_len); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index bc12bc24edd..f2014fc5380 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -66,6 +66,7 @@ struct MeshRenderData { const float (*bm_vert_normals)[3]; const float (*bm_poly_normals)[3]; const float (*bm_poly_centers)[3]; + blender::Array bm_loop_normals; const int *v_origindex, *e_origindex, *p_origindex; int edge_crease_ofs; @@ -98,8 +99,6 @@ struct MeshRenderData { const bool *select_poly; const bool *sharp_faces; - blender::Array bm_loop_normals; - blender::Span loose_verts; blender::Span loose_edges; const SortedPolyData *poly_sorted; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index bd1e91bd4a7..4ae23b1f136 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -41,8 +41,9 @@ static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - if (!mr->loop_normals.is_empty()) { - (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); + if (!mr->corner_normals.is_empty()) { + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3( + mr->corner_normals[l_index]); } else { if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { @@ -64,8 +65,8 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, const int poly for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; - if (!mr->loop_normals.is_empty()) { - *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); + if (!mr->corner_normals.is_empty()) { + *lnor_data = GPU_normal_convert_i10_v3(mr->corner_normals[ml_index]); } else if (mr->sharp_faces && mr->sharp_faces[poly_index]) { *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[poly_index]); @@ -163,8 +164,8 @@ static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - if (!mr->loop_normals.is_empty()) { - normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]); + if (!mr->corner_normals.is_empty()) { + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->corner_normals[l_index]); } else { if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { @@ -186,8 +187,8 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; - if (!mr->loop_normals.is_empty()) { - normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); + if (!mr->corner_normals.is_empty()) { + normal_float_to_short_v3(&lnor_data->x, mr->corner_normals[ml_index]); } else if (mr->sharp_faces && mr->sharp_faces[poly_index]) { normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[poly_index]); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index b536a2bb38a..0d32f42db3d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -257,15 +257,14 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache, draw_subdiv_extract_pos_nor(subdiv_cache, flags_buffer, vbo, orco_vbo); if (subdiv_cache->use_custom_loop_normals) { - Mesh *coarse_mesh = subdiv_cache->mesh; - const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(coarse_mesh); + const Mesh *coarse_mesh = subdiv_cache->mesh; GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc(); GPU_vertbuf_init_with_format(src_custom_normals, get_custom_normals_format()); GPU_vertbuf_data_alloc(src_custom_normals, coarse_mesh->totloop); memcpy(GPU_vertbuf_get_data(src_custom_normals), - loop_normals, + coarse_mesh->corner_normals().data(), sizeof(float[3]) * coarse_mesh->totloop); GPUVertBuf *dst_custom_normals = GPU_vertbuf_calloc(); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc index c6361345b10..fb367237172 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc @@ -102,16 +102,17 @@ static void extract_tan_init_common(const MeshRenderData *mr, short tangent_mask = 0; bool calc_active_tangent = false; if (mr->extract_type == MR_EXTRACT_BMESH) { - BKE_editmesh_loop_tangent_calc(mr->edit_bmesh, - calc_active_tangent, - r_tangent_names, - tan_len, - reinterpret_cast(mr->poly_normals.data()), - reinterpret_cast(mr->loop_normals.data()), - orco, - r_loop_data, - mr->loop_len, - &tangent_mask); + BKE_editmesh_loop_tangent_calc( + mr->edit_bmesh, + calc_active_tangent, + r_tangent_names, + tan_len, + reinterpret_cast(mr->poly_normals.data()), + reinterpret_cast(mr->corner_normals.data()), + orco, + r_loop_data, + mr->loop_len, + &tangent_mask); } else { BKE_mesh_calc_loop_tangent_ex(reinterpret_cast(mr->vert_positions.data()), @@ -126,7 +127,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, tan_len, reinterpret_cast(mr->vert_normals.data()), reinterpret_cast(mr->poly_normals.data()), - reinterpret_cast(mr->loop_normals.data()), + reinterpret_cast(mr->corner_normals.data()), orco, r_loop_data, mr->corner_verts.size(), diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index dc14ee28b27..3ce92405397 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -570,7 +570,6 @@ bool ED_operator_editable_mesh(struct bContext *C); bool ED_operator_editmesh(struct bContext *C); bool ED_operator_editmesh_view3d(struct bContext *C); bool ED_operator_editmesh_region_view3d(struct bContext *C); -bool ED_operator_editmesh_auto_smooth(struct bContext *C); bool ED_operator_editarmature(struct bContext *C); bool ED_operator_editcurve(struct bContext *C); bool ED_operator_editcurve_3d(struct bContext *C); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 92e993f74a2..eab2142a7e6 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -335,11 +335,6 @@ static bool edbm_bevel_calc(wmOperator *op) Mesh *me = obedit->data; - if (harden_normals && !(me->flag & ME_AUTOSMOOTH)) { - /* harden_normals only has a visible effect if autosmooth is on, so turn it on */ - me->flag |= ME_AUTOSMOOTH; - } - EDBM_op_init(em, &bmop, op, diff --git a/source/blender/editors/mesh/editmesh_tools.cc b/source/blender/editors/mesh/editmesh_tools.cc index e17c5db1278..08bc5711cca 100644 --- a/source/blender/editors/mesh/editmesh_tools.cc +++ b/source/blender/editors/mesh/editmesh_tools.cc @@ -8392,7 +8392,6 @@ static bool point_normals_init(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; - BKE_editmesh_ensure_autosmooth(em, static_cast(obedit->data)); BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); @@ -9019,7 +9018,6 @@ static int normals_split_merge(bContext *C, const bool do_merge) BMEdge *e; BMIter eiter; - BKE_editmesh_ensure_autosmooth(em, static_cast(obedit->data)); BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); /* Note that we need temp lnor editing data for all loops of all affected vertices, since by @@ -9158,7 +9156,6 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) BMLoop *l, *l_curr, *l_first; BMIter fiter; - BKE_editmesh_ensure_autosmooth(em, static_cast(obedit->data)); bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); @@ -9407,7 +9404,6 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) continue; } - BKE_editmesh_ensure_autosmooth(em, static_cast(obedit->data)); BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; @@ -9632,7 +9628,6 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp"); - BKE_editmesh_ensure_autosmooth(em, static_cast(obedit->data)); BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); float(*vert_normals)[3] = static_cast( @@ -9740,7 +9735,6 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) BMLoop *l; BMIter fiter, liter; - BKE_editmesh_ensure_autosmooth(em, static_cast(obedit->data)); BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 4bc023ee10e..794c30d58de 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -783,35 +783,11 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator return OPERATOR_CANCELLED; } - if (me->edit_mesh) { - BMesh &bm = *me->edit_mesh->bm; - /* Tag edges as sharp according to smooth threshold if needed, - * to preserve auto-smooth shading. */ - if (me->flag & ME_AUTOSMOOTH) { - BM_edges_sharp_from_angle_set(&bm, me->smoothresh); - } - + if (BMEditMesh *em = me->edit_mesh) { + BMesh &bm = *em->bm; BM_data_layer_add(&bm, &bm.ldata, CD_CUSTOMLOOPNORMAL); } else { - /* Tag edges as sharp according to smooth threshold if needed, - * to preserve auto-smooth shading. */ - if (me->flag & ME_AUTOSMOOTH) { - bke::MutableAttributeAccessor attributes = me->attributes_for_write(); - bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( - "sharp_edge", ATTR_DOMAIN_EDGE); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, "sharp_face")); - bke::mesh::edges_sharp_from_angle_set(me->polys(), - me->corner_verts(), - me->corner_edges(), - me->poly_normals(), - sharp_faces, - me->smoothresh, - sharp_edges.span); - sharp_edges.finish(); - } - CustomData_add_layer(&me->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me->totloop); } @@ -1476,24 +1452,15 @@ void ED_mesh_split_faces(Mesh *mesh) const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); const Span corner_edges = mesh->corner_edges(); - const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI); const bke::AttributeAccessor attributes = mesh->attributes(); const VArray mesh_sharp_edges = attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); Array sharp_edges(mesh->totedge); mesh_sharp_edges.materialize(sharp_edges); - bke::mesh::edges_sharp_from_angle_set(polys, - corner_verts, - corner_edges, - mesh->poly_normals(), - sharp_faces, - split_angle, - sharp_edges); - threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int poly_i : range) { if (sharp_faces && sharp_faces[poly_i]) { diff --git a/source/blender/editors/object/object_bake_api.cc b/source/blender/editors/object/object_bake_api.cc index 49cc126c6a6..f14453b9a5b 100644 --- a/source/blender/editors/object/object_bake_api.cc +++ b/source/blender/editors/object/object_bake_api.cc @@ -672,9 +672,8 @@ static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, { Mesh *me = BKE_mesh_new_from_object(depsgraph, object, false, preserve_origindex); - if (me->flag & ME_AUTOSMOOTH) { + if (me->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { ED_mesh_split_faces(me); - CustomData_free_layers(&me->ldata, CD_NORMAL, me->totloop); } return me; diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 4da6d6df959..1373994644f 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -521,9 +521,6 @@ static int data_transfer_exec(bContext *C, wmOperator *op) false, op->reports)) { - if (data_type == DT_TYPE_LNOR && use_create) { - ((Mesh *)ob_dst->data)->flag |= ME_AUTOSMOOTH; - } DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY); changed = true; diff --git a/source/blender/editors/object/object_edit.cc b/source/blender/editors/object/object_edit.cc index 00fd6139503..774a12dca78 100644 --- a/source/blender/editors/object/object_edit.cc +++ b/source/blender/editors/object/object_edit.cc @@ -1587,16 +1587,18 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) continue; } + Mesh *mesh = reinterpret_cast(data); bool changed = false; if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(static_cast(ob->data), use_smooth); + BKE_mesh_smooth_flag_set(mesh, use_smooth); if (use_smooth) { const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth"); - const float auto_smooth_angle = RNA_float_get(op->ptr, "auto_smooth_angle"); - BKE_mesh_auto_smooth_flag_set( - static_cast(ob->data), use_auto_smooth, auto_smooth_angle); + if (use_auto_smooth) { + const float auto_smooth_angle = RNA_float_get(op->ptr, "auto_smooth_angle"); + BKE_mesh_sharp_edges_set_from_angle(mesh, auto_smooth_angle); + } } - BKE_mesh_batch_cache_dirty_tag(static_cast(ob->data), BKE_MESH_BATCH_DIRTY_ALL); + BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL); changed = true; } else if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY)) { diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 7b6dba0f788..7f20d928d5c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -454,15 +454,6 @@ bool ED_operator_editmesh_region_view3d(bContext *C) return false; } -bool ED_operator_editmesh_auto_smooth(bContext *C) -{ - Object *obedit = CTX_data_edit_object(C); - if (obedit && obedit->type == OB_MESH && (((Mesh *)(obedit->data))->flag & ME_AUTOSMOOTH)) { - return NULL != BKE_editmesh_from_object(obedit); - } - return false; -} - bool ED_operator_editarmature(bContext *C) { Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index f35cfa98237..c6830d7d3a9 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -204,10 +204,7 @@ struct AddOperationExecutor { } const Span surface_looptris_orig = surface_orig.looptris(); - const Span corner_normals_su = { - reinterpret_cast(BKE_mesh_corner_normals_ensure(&surface_orig)), - surface_orig.totloop}; - + const Span corner_normals_su = surface_orig.corner_normals(); const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig}; geometry::AddCurvesOnMeshInputs add_inputs; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc index a6be77154cf..06d7d45b499 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc @@ -254,10 +254,7 @@ struct DensityAddOperationExecutor { } self_->new_deformed_root_positions_.extend(new_positions_cu); - const Span corner_normals_su = { - reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_orig_)), - surface_orig_->totloop}; - + const Span corner_normals_su = surface_orig_->corner_normals(); const Span surface_looptris_orig = surface_orig_->looptris(); const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig}; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index 791f3aabd10..3dfe39726d1 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -115,13 +115,10 @@ struct PuffOperationExecutor { transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_); - corner_normals_su_ = { - reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_)), - surface_->totloop}; - surface_positions_ = surface_->vert_positions(); surface_corner_verts_ = surface_->corner_verts(); surface_looptris_ = surface_->looptris(); + corner_normals_su_ = surface_->corner_normals(); BKE_bvhtree_from_mesh_get(&surface_bvh_, surface_, BVHTREE_FROM_LOOPTRI, 2); BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); }); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc index fceb50288de..876810ca9fa 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc @@ -170,16 +170,13 @@ struct SlideOperationExecutor { return; } surface_looptris_orig_ = surface_orig_->looptris(); + corner_normals_orig_su_ = surface_orig_->corner_normals(); surface_uv_map_orig_ = surface_orig_->attributes().lookup(uv_map_name, ATTR_DOMAIN_CORNER); if (surface_uv_map_orig_.is_empty()) { report_missing_uv_map_on_original_surface(stroke_extension.reports); return; } - corner_normals_orig_su_ = { - reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_orig_)), - surface_orig_->totloop}; - surface_ob_eval_ = DEG_get_evaluated_object(ctx_.depsgraph, surface_ob_orig_); if (surface_ob_eval_ == nullptr) { return; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 78a42f1a3d8..170ee0dbc37 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1996,32 +1996,30 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - if (((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH) { - BMEditMesh *em = NULL; /* BKE_editmesh_from_object(t->obedit); */ - bool do_skip = false; + BMEditMesh *em = NULL; /* BKE_editmesh_from_object(t->obedit); */ + bool do_skip = false; - /* Currently only used for two of three most frequent transform ops, - * can include more ops. - * Note that scaling cannot be included here, - * non-uniform scaling will affect normals. */ - if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) { - if (em->bm->totvertsel == em->bm->totvert) { - /* No need to invalidate if whole mesh is selected. */ - do_skip = true; - } + /* Currently only used for two of three most frequent transform ops, + * can include more ops. + * Note that scaling cannot be included here, + * non-uniform scaling will affect normals. */ + if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) { + if (em->bm->totvertsel == em->bm->totvert) { + /* No need to invalidate if whole mesh is selected. */ + do_skip = true; } + } - if (t->flag & T_MODAL) { - RNA_property_boolean_set(op->ptr, prop, false); - } - else if (!do_skip) { - const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); - if (preserve_clnor) { - BKE_editmesh_lnorspace_update(em, tc->obedit->data); - t->flag |= T_CLNOR_REBUILD; - } - BM_lnorspace_invalidate(em->bm, true); + if (t->flag & T_MODAL) { + RNA_property_boolean_set(op->ptr, prop, false); + } + else if (!do_skip) { + const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); + if (preserve_clnor) { + BKE_editmesh_lnorspace_update(em, tc->obedit->data); + t->flag |= T_CLNOR_REBUILD; } + BM_lnorspace_invalidate(em->bm, true); } } } diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c index 63303b81493..26e3e431809 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c @@ -128,7 +128,6 @@ void initNormalRotation(TransInfo *t) BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; - BKE_editmesh_ensure_autosmooth(em, tc->obedit->data); BKE_editmesh_lnorspace_update(em, tc->obedit->data); storeCustomLNorValue(tc, bm); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 6bcc5c2a1e2..416db89b619 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -414,8 +414,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) MLoopTri *mlooptri = (MLoopTri *)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__); blender::bke::mesh::looptris_calc(vert_positions, mesh_polys, corner_verts, {mlooptri, tottri}); - /* TODO: Only retrieve loop normals when necessary. */ - const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me); + const blender::Span corner_normals = me->corner_normals(); // Get other mesh data const FreestyleEdge *fed = (const FreestyleEdge *)CustomData_get_layer(&me->edata, @@ -531,10 +530,10 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) v2[2] += _z_offset; v3[2] += _z_offset; - if (_smooth && (!sharp_faces[lt->poly]) && lnors) { - copy_v3_v3(n1, lnors[lt->tri[0]]); - copy_v3_v3(n2, lnors[lt->tri[1]]); - copy_v3_v3(n3, lnors[lt->tri[2]]); + if (_smooth && (!sharp_faces[lt->poly])) { + copy_v3_v3(n1, corner_normals[lt->tri[0]]); + copy_v3_v3(n2, corner_normals[lt->tri[1]]); + copy_v3_v3(n3, corner_normals[lt->tri[2]]); mul_mat3_m4_v3(nmat, n1); mul_mat3_m4_v3(nmat, n2); diff --git a/source/blender/geometry/intern/add_curves_on_mesh.cc b/source/blender/geometry/intern/add_curves_on_mesh.cc index 817c37f0419..1ba107be59a 100644 --- a/source/blender/geometry/intern/add_curves_on_mesh.cc +++ b/source/blender/geometry/intern/add_curves_on_mesh.cc @@ -35,17 +35,9 @@ float3 compute_surface_point_normal(const MLoopTri &looptri, const float3 &bary_coord, const Span corner_normals) { - const int l0 = looptri.tri[0]; - const int l1 = looptri.tri[1]; - const int l2 = looptri.tri[2]; - - const float3 &l0_normal = corner_normals[l0]; - const float3 &l1_normal = corner_normals[l1]; - const float3 &l2_normal = corner_normals[l2]; - - const float3 normal = math::normalize( - attribute_math::mix3(bary_coord, l0_normal, l1_normal, l2_normal)); - return normal; + const float3 value = bke::mesh_surface_sample::sample_corner_attrribute_with_bary_coords( + bary_coord, looptri, corner_normals); + return math::normalize(value); } static void initialize_straight_curve_positions(const float3 &p1, @@ -247,7 +239,7 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves, Vector root_positions_cu; Vector bary_coords; - Vector looptris; + Vector looptri_indices; Vector used_uvs; /* Find faces that the passed in uvs belong to. */ @@ -262,7 +254,7 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves, } const MLoopTri &looptri = inputs.surface_looptris[result.looptri_index]; bary_coords.append(result.bary_weights); - looptris.append(&looptri); + looptri_indices.append(result.looptri_index); const float3 root_position_su = attribute_math::mix3( result.bary_weights, surface_positions[surface_corner_verts[looptri.tri[0]]], @@ -347,12 +339,14 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves, /* Find surface normal at root points. */ Array new_normals_su(added_curves_num); - threading::parallel_for(IndexRange(added_curves_num), 256, [&](const IndexRange range) { - for (const int i : range) { - new_normals_su[i] = compute_surface_point_normal( - *looptris[i], bary_coords[i], inputs.corner_normals_su); - } - }); + bke::mesh_surface_sample::sample_corner_attribute( + *inputs.surface, + looptri_indices, + bary_coords, + VArray::ForSpan(inputs.corner_normals_su), + IndexMask(added_curves_num), + new_normals_su.as_mutable_span()); + /* TODO: Normalization. */ /* Initialize position attribute. */ if (inputs.interpolate_shape) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c index c4ac6f680e6..93d18aee078 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c @@ -202,7 +202,7 @@ static void updateDepsgraph(GpencilModifierData *md, CustomData_MeshMasks mask = {0}; if (BKE_shrinkwrap_needs_normals(mmd->shrink_type, mmd->shrink_mode)) { - mask.lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; + mask.lmask |= CD_MASK_CUSTOMLOOPNORMAL; } if (mmd->target != NULL) { diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc index c41139f1d9b..7ff30dbafac 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc @@ -1987,10 +1987,6 @@ static void lineart_geometry_object_load(LineartObjectInfo *ob_info, if (orig_ob->lineart.flags & OBJECT_LRT_OWN_CREASE) { crease_angle = cosf(M_PI - orig_ob->lineart.crease_threshold); } - else if (ob_info->original_me->flag & ME_AUTOSMOOTH) { - crease_angle = cosf(ob_info->original_me->smoothresh); - use_auto_smooth = true; - } else { crease_angle = la_data->conf.crease_threshold; } diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 8253e3f6666..5d3d338e5f4 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -8,6 +8,7 @@ #include "abc_hierarchy_iterator.h" #include "intern/abc_axis_conversion.h" +#include "BLI_array_utils.hh" #include "BLI_assert.h" #include "BLI_math_vector.h" @@ -213,10 +214,9 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) std::vector points, normals; std::vector poly_verts, loop_counts; std::vector velocities; - bool has_flat_shaded_poly = false; get_vertices(mesh, points); - get_topology(mesh, poly_verts, loop_counts, has_flat_shaded_poly); + get_topology(mesh, poly_verts, loop_counts); if (!frame_has_been_written_ && args_.export_params->face_sets) { write_face_sets(context.object, mesh, abc_poly_mesh_schema_); @@ -247,7 +247,7 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) } if (args_.export_params->normals) { - get_loop_normals(mesh, normals, has_flat_shaded_poly); + get_loop_normals(mesh, normals); ON3fGeomParam::Sample normals_sample; if (!normals.empty()) { @@ -446,20 +446,10 @@ static void get_vertices(struct Mesh *mesh, std::vector &points) static void get_topology(struct Mesh *mesh, std::vector &poly_verts, - std::vector &loop_counts, - bool &r_has_flat_shaded_poly) + std::vector &loop_counts) { const OffsetIndices polys = mesh->polys(); const Span corner_verts = mesh->corner_verts(); - const bke::AttributeAccessor attributes = mesh->attributes(); - const VArray sharp_faces = attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); - for (const int i : sharp_faces.index_range()) { - if (sharp_faces[i]) { - r_has_flat_shaded_poly = true; - break; - } - } poly_verts.clear(); loop_counts.clear(); @@ -528,33 +518,50 @@ static void get_vert_creases(struct Mesh *mesh, } } -static void get_loop_normals(struct Mesh *mesh, - std::vector &normals, - bool has_flat_shaded_poly) +static void get_loop_normals(const Mesh *mesh, std::vector &normals) { normals.clear(); - /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export - * normals at all. This is also done by other software, see #71246. */ - if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL) && - (mesh->flag & ME_AUTOSMOOTH) == 0) { - return; - } - - const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh); - - normals.resize(mesh->totloop); - - /* NOTE: data needs to be written in the reverse order. */ - int abc_index = 0; - const OffsetIndices polys = mesh->polys(); - - for (const int i : polys.index_range()) { - const IndexRange poly = polys[i]; - for (int j = poly.size() - 1; j >= 0; j--, abc_index++) { - int blender_index = poly[j]; - copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]); + switch (mesh->normal_domain_all_info()) { + case ATTR_DOMAIN_POINT: { + /* If all polygons are smooth shaded, and there are no custom normals, we don't need to + * export normals at all. This is also done by other software, see #71246. */ + break; } + case ATTR_DOMAIN_FACE: { + normals.resize(mesh->totloop); + MutableSpan dst_normals(reinterpret_cast(normals.data()), normals.size()); + + const OffsetIndices polys = mesh->polys(); + const Span poly_normals = mesh->poly_normals(); + threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + float3 y_up; + copy_yup_from_zup(y_up, poly_normals[i]); + dst_normals.slice(polys[i]).fill(y_up); + } + }); + break; + } + case ATTR_DOMAIN_CORNER: { + normals.resize(mesh->totloop); + MutableSpan dst_normals(reinterpret_cast(normals.data()), normals.size()); + + /* NOTE: data needs to be written in the reverse order. */ + const OffsetIndices polys = mesh->polys(); + const Span corner_normals = mesh->corner_normals(); + threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + const IndexRange poly = polys[i]; + for (const int i : IndexRange(poly.size())) { + copy_yup_from_zup(dst_normals[poly.last(i)], corner_normals[poly[i]]); + } + } + }); + break; + } + default: + BLI_assert_unreachable(); } } diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 5ff83d25690..041a79788f4 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -279,7 +279,6 @@ static void process_loop_normals(CDStreamConfig &config, const N3fArraySamplePtr } } - mesh->flag |= ME_AUTOSMOOTH; BKE_mesh_set_custom_normals(mesh, lnors); MEM_freeN(lnors); @@ -302,7 +301,6 @@ static void process_vertex_normals(CDStreamConfig &config, copy_zup_from_yup(vert_normals[index], vertex_normals[index].getValue()); } - config.mesh->flag |= ME_AUTOSMOOTH; BKE_mesh_set_custom_normals_from_verts(config.mesh, vert_normals); MEM_freeN(vert_normals); } diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index c38ed2f6f00..6150cb9390e 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -616,11 +616,15 @@ void GeometryExporter::create_normals(std::vector &normals, int last_normal_index = -1; const Span positions = me->vert_positions(); - const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me); + const float(*vert_normals)[3] = BKE_mesh_vert_normals_ensure(me); const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); - /* TODO: Only retrieve when necessary. */ - const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(me); + + const bke::AttributeAccessor attributes = me->attributes(); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); + + const blender::Span corner_normals = me->corner_normals(); bool use_custom_normals = true; for (const int poly_index : polys.index_range()) { @@ -644,7 +648,7 @@ void GeometryExporter::create_normals(std::vector &normals, float normalized[3]; if (use_custom_normals) { - normalize_v3_v3(normalized, lnors[corner]); + normalize_v3_v3(normalized, corner_normals[corner]); } else { copy_v3_v3(normalized, vert_normals[corner_verts[corner]]); diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index e0a205f9162..0977b49ca76 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -1167,7 +1167,6 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom) } else { BKE_mesh_set_custom_normals(me, reinterpret_cast(loop_normals.data())); - me->flag |= ME_AUTOSMOOTH; } } diff --git a/source/blender/io/stl/importer/stl_import_mesh.cc b/source/blender/io/stl/importer/stl_import_mesh.cc index 1c19a96cc0d..49d10f956cb 100644 --- a/source/blender/io/stl/importer/stl_import_mesh.cc +++ b/source/blender/io/stl/importer/stl_import_mesh.cc @@ -107,7 +107,6 @@ Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name) if (use_custom_normals_ && loop_normals_.size() == mesh->totloop) { BKE_mesh_set_custom_normals(mesh, reinterpret_cast(loop_normals_.data())); - mesh->flag |= ME_AUTOSMOOTH; } return mesh; diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 4df4f7d566a..4149931a987 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -572,8 +572,6 @@ void USDMeshReader::process_normals_face_varying(Mesh *mesh) return; } - mesh->flag |= ME_AUTOSMOOTH; - long int loop_count = normals_.size(); float(*lnors)[3] = static_cast( @@ -627,7 +625,6 @@ void USDMeshReader::process_normals_uniform(Mesh *mesh) } } - mesh->flag |= ME_AUTOSMOOTH; BKE_mesh_set_custom_normals(mesh, lnors); MEM_freeN(lnors); diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index cba4f0418f2..fffd2c2028b 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -9,6 +9,7 @@ #include #include +#include "BLI_array_utils.hh" #include "BLI_assert.h" #include "BLI_math_vector.h" #include "BLI_math_vector_types.hh" @@ -424,43 +425,32 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context, void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh) { pxr::UsdTimeCode timecode = get_export_time_code(); - /* TODO: Only when necessary. */ - const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(mesh); - const OffsetIndices polys = mesh->polys(); - const Span corner_verts = mesh->corner_verts(); pxr::VtVec3fArray loop_normals; - loop_normals.reserve(mesh->totloop); + loop_normals.resize(mesh->totloop); - if (lnors != nullptr) { - /* Export custom loop normals. */ - for (int loop_idx = 0, totloop = mesh->totloop; loop_idx < totloop; ++loop_idx) { - loop_normals.push_back(pxr::GfVec3f(lnors[loop_idx])); + MutableSpan dst_normals(reinterpret_cast(loop_normals.data()), loop_normals.size()); + + switch (mesh->normal_domain_all_info()) { + case ATTR_DOMAIN_POINT: { + const Span corner_verts = mesh->corner_verts(); + array_utils::gather(mesh->vert_normals(), corner_verts, dst_normals); + break; } - } - else { - /* Compute the loop normals based on the 'smooth' flag. */ - bke::AttributeAccessor attributes = mesh->attributes(); - const Span vert_normals = mesh->vert_normals(); - const Span poly_normals = mesh->poly_normals(); - const VArray sharp_faces = attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); - for (const int i : polys.index_range()) { - const IndexRange poly = polys[i]; - if (sharp_faces[i]) { - /* Flat shaded, use common normal for all verts. */ - pxr::GfVec3f pxr_normal(&poly_normals[i].x); - for (int loop_idx = 0; loop_idx < poly.size(); ++loop_idx) { - loop_normals.push_back(pxr_normal); - } - } - else { - /* Smooth shaded, use individual vert normals. */ - for (const int vert : corner_verts.slice(poly)) { - loop_normals.push_back(pxr::GfVec3f(&vert_normals[vert].x)); - } + case ATTR_DOMAIN_FACE: { + const OffsetIndices polys = mesh->polys(); + const Span poly_normals = mesh->poly_normals(); + for (const int i : polys.index_range()) { + dst_normals.slice(polys[i]).fill(poly_normals[i]); } + break; } + case ATTR_DOMAIN_CORNER: { + array_utils::copy(mesh->corner_normals(), dst_normals); + break; + } + default: + BLI_assert_unreachable(); } pxr::UsdAttribute attr_normals = usd_mesh.CreateNormalsAttr(pxr::VtValue(), true); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index d2ee40d6cfd..7f1928bb192 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -364,8 +364,12 @@ void OBJMesh::store_normal_coords_and_indices() normal_to_index.reserve(export_mesh_->totpoly); loop_to_normal_index_.resize(export_mesh_->totloop); loop_to_normal_index_.fill(-1); - /* TODO: Only retrieve when necessary. */ - const float(*lnors)[3] = BKE_mesh_corner_normals_ensure(export_mesh_); + + Span corner_normals; + if (export_mesh_->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + corner_normals = export_mesh_->corner_normals(); + } + for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) { const IndexRange poly = mesh_polys_[poly_index]; bool need_per_loop_normals = lnors != nullptr || !(sharp_faces_[poly_index]); diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index 851c8c1b6fa..dff311982d6 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -381,7 +381,7 @@ void MeshFromGeometry::create_normals(Mesh *mesh) tot_loop_idx++; } } - mesh->flag |= ME_AUTOSMOOTH; + BKE_mesh_set_custom_normals(mesh, loop_normals); MEM_freeN(loop_normals); } diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index 22356582889..a78a1c2a910 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -133,7 +133,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest { const Span positions = mesh->vert_positions(); EXPECT_V3_NEAR(positions.first(), exp.vert_first, 0.0001f); EXPECT_V3_NEAR(positions.last(), exp.vert_last, 0.0001f); - const float3 *lnors = (const float3 *)BKE_mesh_corner_normals_ensure(mesh); + const float3 *lnors = &mesh->corner_normals().first(); float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0); EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f); const float2 *mloopuv = static_cast( diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 87551220722..e61e9ac6f1e 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -16,6 +16,7 @@ /** Workaround to forward-declare C++ type in C header. */ #ifdef __cplusplus +# include "BKE_attribute.h" # include "BLI_bounds_types.hh" # include "BLI_math_vector_types.hh" # include "BLI_offset_indices.hh" @@ -305,6 +306,12 @@ typedef struct Mesh { */ void loose_edges_tag_none() const; + /** + * \warning This ignores auto-smooth currently. This has to land *after* auto-smooth is turned + * into a modifier. + */ + eAttrDomain normal_domain_all_info() const; + /** * Normal direction of polygons, defined by positions and the winding direction of face corners. */ @@ -314,7 +321,13 @@ typedef struct Mesh { * surrounding each vertex and the normalized position for loose vertices. */ blender::Span vert_normals() const; - + /** + * Normal direction at each face corner. Defined by a combination of face normals, vertex + * normals, the `sharp_edge` and `sharp_face` attributes, and potentially by custom normals. + * + * \note Because of the large memory requirements of storing normals per face corner, prefer + * using #poly_normals() or #vert_normals() when possible (see #normal_domain_all_info()). + */ blender::Span corner_normals() const; #endif } Mesh; @@ -370,9 +383,9 @@ enum { ME_FLAG_DEPRECATED_2 = 1 << 2, /* deprecated */ ME_FLAG_UNUSED_3 = 1 << 3, /* cleared */ ME_FLAG_UNUSED_4 = 1 << 4, /* cleared */ - ME_AUTOSMOOTH = 1 << 5, - ME_FLAG_UNUSED_6 = 1 << 6, /* cleared */ - ME_FLAG_UNUSED_7 = 1 << 7, /* cleared */ + ME_AUTOSMOOTH = 1 << 5, /* deprecated */ + ME_FLAG_UNUSED_6 = 1 << 6, /* cleared */ + ME_FLAG_UNUSED_7 = 1 << 7, /* cleared */ ME_REMESH_REPROJECT_VERTEX_COLORS = 1 << 8, ME_DS_EXPAND = 1 << 9, ME_SCULPT_DYNAMIC_TOPOLOGY = 1 << 10, diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index ddc1fc21020..832e0a28507 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2099,7 +2099,7 @@ int rna_Mesh_poly_normals_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_p static void rna_Mesh_corner_normals_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); - const float(*normals)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + const float(*normals)[3] = BKE_mesh_corner_normals_ensure(mesh); if (!normals) { iter->valid = false; return; @@ -2110,16 +2110,13 @@ static void rna_Mesh_corner_normals_begin(CollectionPropertyIterator *iter, Poin static int rna_Mesh_corner_normals_length(PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); - if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { - return 0; - } return mesh->totloop; } int rna_Mesh_corner_normals_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) { const Mesh *mesh = rna_mesh(ptr); - const float(*normals)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + const float(*normals)[3] = BKE_mesh_corner_normals_ensure(mesh); if (index < 0 || index >= mesh->totloop || !normals) { return false; } @@ -4669,24 +4666,6 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); /* End Symmetry */ - prop = RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH); - RNA_def_property_ui_text( - prop, - "Auto Smooth", - "Auto smooth (based on smooth/sharp faces/edges and angle between faces), " - "or use custom split normals data if available"); - RNA_def_property_update(prop, 0, "rna_Mesh_update_geom_and_params"); - - prop = RNA_def_property(srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_float_sdna(prop, NULL, "smoothresh"); - RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f)); - RNA_def_property_ui_text(prop, - "Auto Smooth Angle", - "Maximum angle between face normals that will be considered as smooth " - "(unused if custom split normals data are available)"); - RNA_def_property_update(prop, 0, "rna_Mesh_update_geom_and_params"); - RNA_define_verify_sdna(false); prop = RNA_def_property(srna, "has_custom_normals", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "", 0); diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 25bfc5f21d4..e2b07cf16fa 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -194,11 +194,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Object *ob = ctx->object; - if (harden_normals && (ob->type == OB_MESH) && !(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) { - BKE_modifier_set_error(ob, md, "Enable 'Auto Smooth' in Object Data Properties"); - harden_normals = false; - } - BM_mesh_bevel(bm, value, offset_type, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.cc b/source/blender/modifiers/intern/MOD_datatransfer.cc index 57f8c822479..ad596ce270f 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.cc +++ b/source/blender/modifiers/intern/MOD_datatransfer.cc @@ -118,8 +118,6 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte if (dtmd->ob_source != nullptr) { CustomData_MeshMasks cddata_masks = {0}; BKE_object_data_transfer_dttypes_to_cdmask(dtmd->data_types, &cddata_masks); - BKE_mesh_remap_calc_source_cddata_masks_from_map_modes( - dtmd->vmap_mode, dtmd->emap_mode, dtmd->lmap_mode, dtmd->pmap_mode, &cddata_masks); DEG_add_object_relation( ctx->node, dtmd->ob_source, DEG_OB_COMP_GEOMETRY, "DataTransfer Modifier"); @@ -222,10 +220,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BKE_modifier_set_error(ctx->object, md, "%s", report_str); MEM_freeN((void *)report_str); } - else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) { - BKE_modifier_set_error( - ctx->object, (ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); - } return result; } diff --git a/source/blender/modifiers/intern/MOD_displace.cc b/source/blender/modifiers/intern/MOD_displace.cc index d981884606d..b5a127f7b3f 100644 --- a/source/blender/modifiers/intern/MOD_displace.cc +++ b/source/blender/modifiers/intern/MOD_displace.cc @@ -303,11 +303,12 @@ static void displaceModifier_do(DisplaceModifierData *dmd, if (CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)) { vert_clnors = static_cast( MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__)); - BKE_mesh_normals_loop_to_vertex(verts_num, - mesh->corner_verts().data(), - mesh->totloop, - BKE_mesh_corner_normals_ensure(mesh), - vert_clnors); + BKE_mesh_normals_loop_to_vertex( + verts_num, + mesh->corner_verts().data(), + mesh->totloop, + reinterpret_cast(mesh->corner_normals().data()), + vert_clnors); } else { direction = MOD_DISP_DIR_NOR; diff --git a/source/blender/modifiers/intern/MOD_multires.cc b/source/blender/modifiers/intern/MOD_multires.cc index 03c7523c04a..3621ee49707 100644 --- a/source/blender/modifiers/intern/MOD_multires.cc +++ b/source/blender/modifiers/intern/MOD_multires.cc @@ -66,7 +66,6 @@ static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_ma { MultiresModifierData *mmd = (MultiresModifierData *)md; if (mmd->flags & eMultiresModifierFlag_UseCustomNormals) { - r_cddata_masks->lmask |= CD_MASK_NORMAL; r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL; } } @@ -216,8 +215,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return result; } const bool use_clnors = mmd->flags & eMultiresModifierFlag_UseCustomNormals && - mesh->flag & ME_AUTOSMOOTH && - CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); + mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER; /* NOTE: Orco needs final coordinates on CPU side, which are expected to be * accessible via mesh vertices. For this reason we do not evaluate multires to * grids when orco is requested. */ @@ -252,11 +250,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } else { if (use_clnors) { - CustomData_add_layer(&mesh->ldata, - CD_NORMAL, - CD_DUPLICATE, - const_cast(BKE_mesh_corner_normals_ensure(mesh)), - mesh->totloop); + void *data = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop); + memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes()); } result = multires_as_mesh(mmd, ctx, mesh, subdiv); diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index 1f460218994..8db958b1a56 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -237,6 +237,9 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, blender::MutableSpan corner_edges, const blender::OffsetIndices polys) { + using namespace blender; + const bke::AttributeAccessor attributes = mesh->attributes(); + Object *ob_target = enmd->target; const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; @@ -328,8 +331,8 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, corner_verts, corner_edges, nos.data(), &mesh->ldata, polys, mesh->poly_normals())) { BKE_mesh_tag_face_winding_changed(mesh); } - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_loop_custom_set(vert_positions, edges, polys, @@ -365,6 +368,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, blender::MutableSpan corner_edges, const blender::OffsetIndices polys) { + using namespace blender; + const bke::AttributeAccessor attributes = mesh->attributes(); Object *ob_target = enmd->target; const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; @@ -435,8 +440,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, corner_verts, corner_edges, nos.data(), &mesh->ldata, polys, mesh->poly_normals())) { BKE_mesh_tag_face_winding_changed(mesh); } - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_loop_custom_set(positions, edges, polys, @@ -486,22 +491,6 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, return mesh; } - /* XXX TODO(Rohan Rathi): - * Once we fully switch to Mesh evaluation of modifiers, - * we can expect to get that flag from the COW copy. - * But for now, it is lost in the DM intermediate step, - * so we need to directly check orig object's data. */ -#if 0 - if (!(mesh->flag & ME_AUTOSMOOTH)) -#else - if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) -#endif - { - BKE_modifier_set_error( - ob, (ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); - return mesh; - } - Mesh *result; if (mesh->edges().data() == ((Mesh *)ob->data)->edges().data()) { /* We need to duplicate data here, otherwise setting custom normals @@ -536,8 +525,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, clnors = static_cast( CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); loop_normals.reinitialize(corner_verts.size()); - const bool *sharp_faces = static_cast( - CustomData_get_layer_named(&result->pdata, CD_PROP_BOOL, "sharp_face")); + const VArray sharp_faces = attributes.lookup_or_default( + "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_calc_loop(positions, edges, polys, @@ -546,10 +535,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, {}, result->vert_normals(), result->poly_normals(), - sharp_edges.span.data(), + VArray::ForSpan(sharp_edges.span), sharp_faces, - true, - result->smoothresh, clnors, nullptr, loop_normals); diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index f841dbfc779..a625e663ace 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -155,8 +155,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte CustomData_MeshMasks mask = {0}; if (BKE_shrinkwrap_needs_normals(smd->shrinkType, smd->shrinkMode)) { - mask.vmask |= CD_MASK_NORMAL; - mask.lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; + mask.lmask |= CD_MASK_CUSTOMLOOPNORMAL; } if (smd->target != NULL) { diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index b9b7d15fe73..37b5638dc54 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -65,7 +65,6 @@ static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_ma { SubsurfModifierData *smd = (SubsurfModifierData *)md; if (smd->flags & eSubsurfModifierFlag_UseCustomNormals) { - r_cddata_masks->lmask |= CD_MASK_NORMAL; r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL; } if (smd->flags & eSubsurfModifierFlag_UseCrease) { @@ -262,11 +261,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh); if (use_clnors) { - CustomData_add_layer(&mesh->ldata, - CD_NORMAL, - CD_DUPLICATE, - const_cast(BKE_mesh_corner_normals_ensure(mesh)), - mesh->totloop); + void *data = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop); + memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes()); } /* TODO(sergey): Decide whether we ever want to use CCG for subsurf, * maybe when it is a last modifier in the stack? */ diff --git a/source/blender/modifiers/intern/MOD_triangulate.cc b/source/blender/modifiers/intern/MOD_triangulate.cc index 9f69bc63ba0..775410ebe8e 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.cc +++ b/source/blender/modifiers/intern/MOD_triangulate.cc @@ -51,11 +51,8 @@ static Mesh *triangulate_mesh(Mesh *mesh, bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0; if (keep_clnors) { - CustomData_add_layer(&mesh->ldata, - CD_NORMAL, - CD_DUPLICATE, - const_cast(BKE_mesh_corner_normals_ensure(mesh)), - mesh->totloop); + void *data = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop); + memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes()); } BMeshCreateParams bmesh_create_params{}; diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index 40ef86b7488..2905fa901a8 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -80,11 +80,10 @@ struct WeightedNormalData { blender::Span loop_to_poly; short (*clnors)[2]; bool has_clnors; /* True if clnors already existed, false if we had to create them. */ - float split_angle; blender::OffsetIndices polys; blender::Span poly_normals; - const bool *sharp_faces; + blender::VArray sharp_faces; const int *poly_strength; const MDeformVert *dvert; @@ -203,7 +202,6 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, ModePair *mode_pair = wn_data->mode_pair; const bool has_clnors = wn_data->has_clnors; - const float split_angle = wn_data->split_angle; MLoopNorSpaceArray lnors_spacearr = {nullptr}; const bool keep_sharp = (wnmd->flag & MOD_WEIGHTEDNORMAL_KEEP_SHARP) != 0; @@ -229,10 +227,8 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, loop_to_poly, wn_data->vert_normals, wn_data->poly_normals, - wn_data->sharp_edges.data(), + blender::VArray::ForSpan(wn_data->sharp_edges), wn_data->sharp_faces, - true, - split_angle, has_clnors ? clnors : nullptr, &lnors_spacearr, loop_normals); @@ -395,10 +391,8 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, loop_to_poly, wn_data->vert_normals, poly_normals, - wn_data->sharp_edges.data(), + blender::VArray::ForSpan(wn_data->sharp_edges), wn_data->sharp_faces, - true, - split_angle, has_clnors ? clnors : nullptr, nullptr, loop_normals); @@ -521,24 +515,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md; Object *ob = ctx->object; - /* XXX TODO(Rohan Rathi): - * Once we fully switch to Mesh evaluation of modifiers, - * we can expect to get that flag from the COW copy. - * But for now, it is lost in the DM intermediate step, - * so we need to directly check orig object's data. */ -#if 0 - if (!(mesh->flag & ME_AUTOSMOOTH)) -#else - if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) -#endif - { - BKE_modifier_set_error( - ctx->object, (ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); - return mesh; - } - - Mesh *result; - result = (Mesh *)BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE); + Mesh *result = (Mesh *)BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE); const int verts_num = result->totvert; const blender::Span positions = mesh->vert_positions(); @@ -564,7 +541,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * weight = (weight - 1) * 25; } - const float split_angle = mesh->smoothresh; short(*clnors)[2] = static_cast( CustomData_get_layer_for_write(&result->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop)); @@ -599,12 +575,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * wn_data.loop_to_poly = loop_to_poly_map; wn_data.clnors = clnors; wn_data.has_clnors = has_clnors; - wn_data.split_angle = split_angle; wn_data.polys = polys; wn_data.poly_normals = mesh->poly_normals(); - wn_data.sharp_faces = static_cast( - CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); + wn_data.sharp_faces = attributes.lookup_or_default("sharp_face", ATTR_DOMAIN_FACE, false); wn_data.poly_strength = static_cast(CustomData_get_layer_named( &result->pdata, CD_PROP_INT32, MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc index cf46623c1de..295170db503 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc @@ -315,12 +315,8 @@ static void node_geo_exec(GeoNodeExecParams params) /* Retrieve face corner normals from each mesh. It's necessary to use face corner normals * because face normals or vertex normals may lose information (custom normals, auto smooth) in * some cases. */ - const Span corner_normals_orig( - reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_mesh_orig)), - surface_mesh_orig->totloop); - const Span corner_normals_eval( - reinterpret_cast(BKE_mesh_corner_normals_ensure(surface_mesh_eval)), - surface_mesh_eval->totloop); + const Span corner_normals_orig = surface_mesh_orig->corner_normals(); + const Span corner_normals_eval = surface_mesh_eval->corner_normals(); std::atomic invalid_uv_count = 0; diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 7344c6d29ce..36f60474060 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -332,25 +332,41 @@ static void compute_normal_outputs(const Mesh &mesh, const Span looptri_indices, MutableSpan r_normals) { - Array corner_normals(mesh.totloop); - BKE_mesh_calc_normals_split_ex( - const_cast(&mesh), nullptr, reinterpret_cast(corner_normals.data())); + /* TODO: Normalization. */ + switch (mesh.normal_domain_all_info()) { + case ATTR_DOMAIN_POINT: { + const Span vert_normals = mesh.vert_normals(); + bke::mesh_surface_sample::sample_point_attribute(mesh, + looptri_indices, + bary_coords, + VArray::ForSpan(vert_normals), + IndexMask(looptri_indices.index_range()), + r_normals); - const Span looptris = mesh.looptris(); - - threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) { - for (const int i : range) { - const int looptri_index = looptri_indices[i]; - const MLoopTri &looptri = looptris[looptri_index]; - const float3 &bary_coord = bary_coords[i]; - - const float3 normal = math::normalize( - bke::mesh_surface_sample::sample_corner_attrribute_with_bary_coords( - bary_coord, looptri, corner_normals.as_span())); - - r_normals[i] = normal; + break; } - }); + case ATTR_DOMAIN_FACE: { + const Span poly_normals = mesh.poly_normals(); + bke::mesh_surface_sample::sample_face_attribute(mesh, + looptri_indices, + VArray::ForSpan(poly_normals), + IndexMask(looptri_indices.index_range()), + r_normals); + break; + } + case ATTR_DOMAIN_CORNER: { + const Span corner_normals = mesh.corner_normals(); + bke::mesh_surface_sample::sample_corner_attribute(mesh, + looptri_indices, + bary_coords, + VArray::ForSpan(corner_normals), + IndexMask(looptri_indices.index_range()), + r_normals); + break; + } + default: + BLI_assert_unreachable(); + } } static void compute_legacy_normal_outputs(const Mesh &mesh, diff --git a/source/blender/render/intern/bake.cc b/source/blender/render/intern/bake.cc index d31d49ea2a0..6f927c91b79 100644 --- a/source/blender/render/intern/bake.cc +++ b/source/blender/render/intern/bake.cc @@ -487,14 +487,14 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval } const TSpace *tspace = nullptr; - const float(*loop_normals)[3] = nullptr; + blender::Span corner_normals; if (tangent) { - BKE_mesh_calc_loop_tangents(me_eval, true, NULL, 0); + BKE_mesh_calc_loop_tangents(me_eval, true, nullptr, 0); tspace = static_cast(CustomData_get_layer(&me_eval->ldata, CD_TANGENT)); BLI_assert(tspace); - loop_normals = BKE_mesh_corner_normals_ensure(me_eval); + corner_normals = me_eval->corner_normals(); } const blender::Span vert_normals = me->vert_normals(); @@ -515,10 +515,10 @@ static TriTessFace *mesh_calc_tri_tessface(Mesh *me, bool tangent, Mesh *me_eval triangles[i].tspace[2] = &tspace[lt->tri[2]]; } - if (loop_normals) { - triangles[i].loop_normal[0] = loop_normals[lt->tri[0]]; - triangles[i].loop_normal[1] = loop_normals[lt->tri[1]]; - triangles[i].loop_normal[2] = loop_normals[lt->tri[2]]; + if (!corner_normals.is_empty()) { + triangles[i].loop_normal[0] = corner_normals[lt->tri[0]]; + triangles[i].loop_normal[1] = corner_normals[lt->tri[1]]; + triangles[i].loop_normal[2] = corner_normals[lt->tri[2]]; } if (calculate_normal) { diff --git a/source/blender/render/intern/multires_bake.cc b/source/blender/render/intern/multires_bake.cc index 64e5cc6e121..2dc777521a6 100644 --- a/source/blender/render/intern/multires_bake.cc +++ b/source/blender/render/intern/multires_bake.cc @@ -505,6 +505,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, const blender::Span corner_verts = temp_mesh->corner_verts(); const blender::Span vert_normals = temp_mesh->vert_normals(); const blender::Span poly_normals = temp_mesh->poly_normals(); + const blender::Span corner_normals = temp_mesh->corner_normals(); const blender::Span looptris = temp_mesh->looptris(); if (require_tangent) { @@ -523,7 +524,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, 0, reinterpret_cast(vert_normals.data()), reinterpret_cast(poly_normals.data()), - BKE_mesh_corner_normals_ensure(temp_mesh), + reinterpret_cast(corner_normals.data()), (const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* May be nullptr. */ /* result */ &dm->loopData, -- 2.30.2 From d05bba2b61278e10e5ccd871b59784991f93b9de Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 10 Apr 2023 15:01:28 -0400 Subject: [PATCH 08/85] Progress --- .../bmesh/intern/bmesh_mesh_normals.cc | 45 ++----------------- .../draw_cache_extract_mesh_render_data.cc | 2 - .../io/alembic/exporter/abc_writer_mesh.cc | 7 +-- .../wavefront_obj/exporter/obj_export_mesh.cc | 4 +- source/blender/makesrna/intern/rna_mesh.c | 5 +-- source/blender/makesrna/intern/rna_mesh_api.c | 1 - 6 files changed, 10 insertions(+), 54 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.cc b/source/blender/bmesh/intern/bmesh_mesh_normals.cc index 4e5c844c1d9..16dfce75fbb 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.cc @@ -870,7 +870,6 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(BMesh *bm, const short (*clnors_data)[2], const int cd_loop_clnors_offset, const bool do_rebuild, - const float split_angle_cos, /* TLS */ MLoopNorSpaceArray *r_lnors_spacearr, BLI_Stack *edge_vectors, @@ -889,8 +888,6 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(BMesh *bm, const bool has_clnors = true; LinkNode *loops_of_vert = nullptr; int loops_of_vert_count = 0; - /* When false the caller must have already tagged the edges. */ - const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); /* The loop with the lowest index. */ { @@ -903,10 +900,6 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(BMesh *bm, continue; } - if (do_edge_tag) { - bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); - } - do { /* Radial loops. */ if (l_curr->v != v) { continue; @@ -997,8 +990,6 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( { const bool has_clnors = false; const short(*clnors_data)[2] = nullptr; - /* When false the caller must have already tagged the edges. */ - const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); const int cd_loop_clnors_offset = -1; BMEdge *e_curr_iter; @@ -1011,10 +1002,6 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( continue; } - if (do_edge_tag) { - bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); - } - do { /* Radial loops. */ if (l_curr->v != v) { continue; @@ -1071,8 +1058,6 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, BMIter fiter; BMFace *f_curr; const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); - /* When false the caller must have already tagged the edges. */ - const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); MLoopNorSpaceArray _lnors_spacearr = {nullptr}; @@ -1111,12 +1096,6 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, } bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); - /* Always tag edges based on winding & sharp edge flag - * (even when the auto-smooth angle doesn't need to be calculated). */ - if (do_edge_tag) { - bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? -1.0f : split_angle_cos, false); - } - /* We now know edges that can be smoothed (they are tagged), * and edges that will be hard (they aren't). * Now, time to generate the normals. @@ -1228,7 +1207,6 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors_fn( data->clnors_data, data->cd_loop_clnors_offset, data->do_rebuild, - data->split_angle_cos, /* Thread local. */ tls_data->lnors_spacearr, tls_data->edge_vectors, @@ -1565,15 +1543,8 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm, /* Finish computing lnos by accumulating face normals * in each fan of faces defined by sharp edges. */ - bm_mesh_loops_calc_normals(bm, - vcos, - fnos, - cur_lnors, - r_lnors_spacearr, - r_clnors_data, - cd_loop_clnors_offset, - false, - EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); + bm_mesh_loops_calc_normals( + bm, vcos, fnos, cur_lnors, r_lnors_spacearr, r_clnors_data, cd_loop_clnors_offset, false); /* Extract new normals from the data layer if necessary. */ float(*custom_lnors)[3] = new_lnors; @@ -1607,15 +1578,8 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm, * spacearr/smooth fans matching the given custom lnors. */ BKE_lnor_spacearr_clear(r_lnors_spacearr); - bm_mesh_loops_calc_normals(bm, - vcos, - fnos, - cur_lnors, - r_lnors_spacearr, - r_clnors_data, - cd_loop_clnors_offset, - false, - EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); + bm_mesh_loops_calc_normals( + bm, vcos, fnos, cur_lnors, r_lnors_spacearr, r_clnors_data, cd_loop_clnors_offset, false); } /* And we just have to convert plain object-space custom normals to our @@ -1674,7 +1638,6 @@ void BM_loops_calc_normal_vcos(BMesh *bm, const int cd_loop_clnors_offset, const bool do_rebuild) { - const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); if (use_split_normals) { bm_mesh_loops_calc_normals( diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index c389eb3c5ec..95138480200 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -337,8 +337,6 @@ void mesh_render_data_update_looptris(MeshRenderData *mr, void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_flag) { - Mesh *me = mr->me; - if (mr->extract_type != MR_EXTRACT_BMESH) { /* Mesh */ mr->vert_normals = mr->me->vert_normals(); diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 5d3d338e5f4..5391c019e48 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -62,8 +62,7 @@ namespace blender::io::alembic { static void get_vertices(struct Mesh *mesh, std::vector &points); static void get_topology(struct Mesh *mesh, std::vector &poly_verts, - std::vector &loop_counts, - bool &r_has_flat_shaded_poly); + std::vector &loop_counts); static void get_edge_creases(struct Mesh *mesh, std::vector &indices, std::vector &lengths, @@ -71,9 +70,7 @@ static void get_edge_creases(struct Mesh *mesh, static void get_vert_creases(struct Mesh *mesh, std::vector &indices, std::vector &sharpnesses); -static void get_loop_normals(struct Mesh *mesh, - std::vector &normals, - bool has_flat_shaded_poly); +static void get_loop_normals(struct Mesh *mesh, std::vector &normals); ABCGenericMeshWriter::ABCGenericMeshWriter(const ABCWriterConstructorArgs &args) : ABCAbstractWriter(args), is_subd_(false) diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 7f1928bb192..a48c90dcdb6 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -372,12 +372,12 @@ void OBJMesh::store_normal_coords_and_indices() for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) { const IndexRange poly = mesh_polys_[poly_index]; - bool need_per_loop_normals = lnors != nullptr || !(sharp_faces_[poly_index]); + bool need_per_loop_normals = !corner_normals.is_empty() && !(sharp_faces_[poly_index]); if (need_per_loop_normals) { for (const int corner : poly) { float3 loop_normal; BLI_assert(corner < export_mesh_->totloop); - copy_v3_v3(loop_normal, lnors[corner]); + copy_v3_v3(loop_normal, corner_normals[corner]); mul_m3_v3(world_and_axes_normal_transform_, loop_normal); normalize_v3(loop_normal); float3 rounded_loop_normal = round_float3_to_n_digits(loop_normal, round_digits); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 832e0a28507..f7157064775 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -620,11 +620,10 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values) Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); - const float(*nor)[3] = loop_normals[index]; const float(*vec)[4] = CustomData_get(&me->ldata, index, CD_MLOOPTANGENT); - if (nor && vec) { - cross_v3_v3v3(values, nor[index], vec[index]); + if (vec) { + cross_v3_v3v3(values, loop_normals[index][index], vec[index]); mul_v3_fl(values, vec[index][3]); } else { diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 98e7c43c1f8..d0c876ec306 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -51,7 +51,6 @@ static void rna_Mesh_create_normals_split(Mesh *mesh) static void rna_Mesh_free_normals_split(Mesh *mesh) { /* TODO: Deprecation? */ - BKE_mesh_normals_tag_dirty(mesh); } static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap) -- 2.30.2 From 55dd8b2db50a02e7329ef6abf84c188c20546156 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 10 Apr 2023 17:20:07 -0400 Subject: [PATCH 09/85] Progress Need the normals shared cache changes to move forward here --- intern/cycles/blender/mesh.cpp | 2 +- intern/cycles/blender/util.h | 6 +- scripts/startup/bl_ui/properties_data_mesh.py | 23 ------ source/blender/blenkernel/BKE_editmesh.h | 2 +- source/blender/blenkernel/BKE_mesh.h | 8 +- source/blender/blenkernel/BKE_mesh.hh | 6 +- source/blender/blenkernel/BKE_mesh_remap.h | 2 - .../blender/blenkernel/intern/DerivedMesh.cc | 78 +++++++++++-------- .../blenkernel/intern/data_transfer.cc | 7 +- source/blender/blenkernel/intern/displist.cc | 1 - source/blender/blenkernel/intern/editmesh.cc | 2 +- source/blender/blenkernel/intern/key.cc | 2 +- .../blender/blenkernel/intern/mesh_mirror.cc | 2 +- .../blender/blenkernel/intern/mesh_normals.cc | 56 +++++-------- .../blender/blenkernel/intern/mesh_remap.cc | 2 - .../blender/blenkernel/intern/mesh_runtime.cc | 2 + .../blender/blenkernel/intern/mesh_wrapper.cc | 7 +- .../blenloader/intern/versioning_defaults.cc | 2 + source/blender/bmesh/intern/bmesh_opdefines.c | 1 - source/blender/bmesh/operators/bmo_bevel.c | 2 - source/blender/bmesh/tools/bmesh_bevel.c | 5 -- source/blender/bmesh/tools/bmesh_bevel.h | 1 - source/blender/editors/include/ED_mesh.h | 1 + source/blender/editors/mesh/editmesh_bevel.c | 3 +- source/blender/editors/mesh/editmesh_tools.cc | 14 ++-- source/blender/editors/mesh/mesh_data.cc | 6 +- source/blender/editors/transform/transform.c | 2 +- .../transform_mode_edge_rotate_normal.c | 2 +- .../io/alembic/exporter/abc_writer_mesh.cc | 5 +- source/blender/makesdna/DNA_mesh_defaults.h | 1 - source/blender/makesdna/DNA_mesh_types.h | 2 +- source/blender/makesrna/RNA_enum_items.h | 1 + .../blender/makesrna/intern/rna_attribute.c | 7 ++ source/blender/makesrna/intern/rna_mesh.c | 16 +++- source/blender/makesrna/intern/rna_mesh_api.c | 2 +- source/blender/modifiers/intern/MOD_bevel.c | 3 - .../modifiers/intern/MOD_normal_edit.cc | 10 +-- .../modifiers/intern/MOD_weighted_normal.cc | 9 +-- 38 files changed, 138 insertions(+), 165 deletions(-) diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index 7e1b73ea40b..3fc8ccb27aa 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -985,7 +985,7 @@ static void create_mesh(Scene *scene, const int polys_num = b_mesh.polygons.length(); int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length(); const int numcorners = b_mesh.loops.length(); - bool use_loop_normals = b_mesh.use_auto_smooth() && + bool use_loop_normals = b_mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT && (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK); /* If no faces, create empty mesh. */ diff --git a/intern/cycles/blender/util.h b/intern/cycles/blender/util.h index 7394fa5ba51..d0bbefc6203 100644 --- a/intern/cycles/blender/util.h +++ b/intern/cycles/blender/util.h @@ -87,8 +87,8 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, /* Make a copy to split faces if we use autosmooth, otherwise not needed. * Also in edit mode do we need to make a copy, to ensure data layers like * UV are not empty. */ - if (mesh.is_editmode() || - (mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE)) { + if (mesh.is_editmode() || (mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT && + subdivision_type == Mesh::SUBDIVISION_NONE)) { BL::Depsgraph depsgraph(PointerRNA_NULL); mesh = b_ob_info.real_object.to_mesh(false, depsgraph); } @@ -112,7 +112,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, #endif if ((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) { - if (mesh.use_auto_smooth()) { + if (mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT) { mesh.calc_normals_split(); mesh.split_faces(false); } diff --git a/scripts/startup/bl_ui/properties_data_mesh.py b/scripts/startup/bl_ui/properties_data_mesh.py index 3f31426be23..f4ce459a3cb 100644 --- a/scripts/startup/bl_ui/properties_data_mesh.py +++ b/scripts/startup/bl_ui/properties_data_mesh.py @@ -186,28 +186,6 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel): layout.template_ID(space, "pin_id") -class DATA_PT_normals(MeshButtonsPanel, Panel): - bl_label = "Normals" - bl_options = {'DEFAULT_CLOSED'} - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'} - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - - mesh = context.mesh - - col = layout.column(align=False, heading="Auto Smooth") - col.use_property_decorate = False - row = col.row(align=True) - sub = row.row(align=True) - sub.prop(mesh, "use_auto_smooth", text="") - sub = sub.row(align=True) - sub.active = mesh.use_auto_smooth and not mesh.has_custom_normals - sub.prop(mesh, "auto_smooth_angle", text="") - row.prop_decorator(mesh, "auto_smooth_angle") - - class DATA_PT_texture_space(MeshButtonsPanel, Panel): bl_label = "Texture Space" bl_options = {'DEFAULT_CLOSED'} @@ -738,7 +716,6 @@ classes = ( DATA_PT_vertex_colors, DATA_PT_face_maps, DATA_PT_mesh_attributes, - DATA_PT_normals, DATA_PT_texture_space, DATA_PT_remesh, DATA_PT_customdata, diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 439aa472d13..2cd17ffc40e 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -118,7 +118,7 @@ const float (*BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph int *r_vert_len, bool *r_is_alloc))[3]; -void BKE_editmesh_lnorspace_update(BMEditMesh *em, struct Mesh *me); +void BKE_editmesh_lnorspace_update(BMEditMesh *em); struct BoundBox *BKE_editmesh_cage_boundbox_get(struct Object *object, BMEditMesh *em); #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index de71ec0e02d..78db67afe92 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -364,11 +364,6 @@ void BKE_mesh_calc_poly_normal(const int *poly_verts, int verts_num, float r_no[3]); -/** - * Called after calculating all modifiers. - */ -void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh); - /** * References a contiguous loop-fan with normal offset vars. */ @@ -710,8 +705,7 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, bool selec void BKE_mesh_calc_edges_tessface(struct Mesh *mesh); /* In DerivedMesh.cc */ -void BKE_mesh_wrapper_deferred_finalize_mdata(struct Mesh *me_eval, - const struct CustomData_MeshMasks *cd_mask_finalize); +void BKE_mesh_wrapper_deferred_finalize_mdata(struct Mesh *me_eval); /* **** Depsgraph evaluation **** */ diff --git a/source/blender/blenkernel/BKE_mesh.hh b/source/blender/blenkernel/BKE_mesh.hh index 2e2381cf274..9a27a4e0a0b 100644 --- a/source/blender/blenkernel/BKE_mesh.hh +++ b/source/blender/blenkernel/BKE_mesh.hh @@ -98,7 +98,7 @@ void normals_calc_loop(Span vert_positions, Span poly_normals, const VArray &sharp_edges, const VArray &sharp_faces, - short (*clnors_data)[2], + const short2 *custom_normals_data, MLoopNorSpaceArray *r_lnors_spacearr, MutableSpan r_loop_normals); @@ -112,7 +112,7 @@ void normals_loop_custom_set(Span vert_positions, const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_loop_normals, - short (*r_clnors_data)[2]); + short2 *r_clnors_data); void normals_loop_custom_set_from_verts(Span vert_positions, Span edges, @@ -124,7 +124,7 @@ void normals_loop_custom_set_from_verts(Span vert_positions, const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_vert_normals, - short (*r_clnors_data)[2]); + short2 *r_clnors_data); /** * Define sharp edges as needed to mimic 'autosmooth' from angle threshold. diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index c9a2c9fc860..d9cc32f9a7e 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -201,8 +201,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(int mode, const struct Mesh *mesh_dst, const float (*vert_positions_dst)[3], int numverts_dst, - const struct MEdge *edges_dst, - int numedges_dst, const int *corner_verts_dst, int numloops_dst, const blender::OffsetIndices polys_dst, diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 00443529c7a..45afd6b7a72 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -83,10 +83,8 @@ using blender::VArray; #endif static void mesh_init_origspace(Mesh *mesh); -static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, - const CustomData_MeshMasks *final_datamask); -static void editbmesh_calc_modifier_final_normals_or_defer( - Mesh *mesh_final, const CustomData_MeshMasks *final_datamask); +static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final); +static void editbmesh_calc_modifier_final_normals_or_defer(Mesh *mesh_final); /* -------------------------------------------------------------------- */ @@ -440,21 +438,17 @@ static void add_orco_mesh( } } -static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, - const CustomData_MeshMasks *final_datamask, - const bool sculpt_dyntopo, - Mesh *mesh_final) +static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *mesh_final) { - /* Compute normals. */ - const bool calc_loop_normals = mesh_final->normal_domain_all_info() == ATTR_DOMAIN_CORNER; + const eAttrDomain domain = mesh_final->normal_domain_all_info(); /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; if (subsurf_runtime_data) { - subsurf_runtime_data->calc_loop_normals = calc_loop_normals; + subsurf_runtime_data->calc_loop_normals = domain == ATTR_DOMAIN_CORNER; } - if (calc_loop_normals) { + if (domain == ATTR_DOMAIN_CORNER) { /* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case * of deferred CPU subdivision, this will be computed when the wrapper is generated. */ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { @@ -468,7 +462,12 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, * this where possible since calculating polygon normals isn't fast, * note that this isn't a problem for subsurf (only quads) or edit-mode * which deals with drawing differently. */ - BKE_mesh_ensure_normals_for_display(mesh_final); + if (domain == ATTR_DOMAIN_FACE) { + mesh_final->poly_normals(); + } + else if (domain == ATTR_DOMAIN_FACE) { + mesh_final->vert_normals(); + } } } } @@ -487,11 +486,10 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval) mesh_eval->edit_mesh = mesh_input->edit_mesh; } -void BKE_mesh_wrapper_deferred_finalize_mdata(Mesh *me_eval, - const CustomData_MeshMasks *cd_mask_finalize) +void BKE_mesh_wrapper_deferred_finalize_mdata(Mesh *me_eval) { if (me_eval->runtime->wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) { - editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize); + editbmesh_calc_modifier_final_normals(me_eval); me_eval->runtime->wrapper_type_finalize = eMeshWrapperType( me_eval->runtime->wrapper_type_finalize & ~(1 << ME_WRAPPER_TYPE_BMESH)); } @@ -970,7 +968,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* Compute normals. */ if (is_own_mesh) { - mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); + mesh_calc_modifier_final_normals(sculpt_dyntopo, mesh_final); mesh_calc_finalize(mesh_input, mesh_final); } else { @@ -982,8 +980,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, * Isolate since computing normals is multithreaded and we are holding a lock. */ blender::threading::isolate_task([&] { mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); - mesh_calc_modifier_final_normals( - mesh_input, &final_datamask, sculpt_dyntopo, mesh_final); + mesh_calc_modifier_final_normals(sculpt_dyntopo, mesh_final); mesh_calc_finalize(mesh_input, mesh_final); runtime->mesh_eval = mesh_final; }); @@ -1047,17 +1044,16 @@ bool editbmesh_modifier_is_enabled(const Scene *scene, return true; } -static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, - const CustomData_MeshMasks *final_datamask) +static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final) { - const bool calc_loop_normals = mesh_final->normal_domain_all_info() == ATTR_DOMAIN_CORNER; + const eAttrDomain domain = mesh_final->normal_domain_all_info(); SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; if (subsurf_runtime_data) { - subsurf_runtime_data->calc_loop_normals = calc_loop_normals; + subsurf_runtime_data->calc_loop_normals = domain == ATTR_DOMAIN_CORNER; } - if (calc_loop_normals) { + if (domain == ATTR_DOMAIN_CORNER) { /* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the * wrapper is generated. */ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { @@ -1065,14 +1061,32 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, } } else { - /* Same as #mesh_calc_modifiers. - * If using loop normals, poly normals have already been computed. */ - BKE_mesh_ensure_normals_for_display(mesh_final); + switch (mesh_final->runtime->wrapper_type) { + case ME_WRAPPER_TYPE_SUBD: + break; + case ME_WRAPPER_TYPE_MDATA: + /* Same as #mesh_calc_modifiers. */ + if (domain == ATTR_DOMAIN_FACE) { + mesh_final->poly_normals(); + } + else if (domain == ATTR_DOMAIN_FACE) { + mesh_final->vert_normals(); + } + break; + case ME_WRAPPER_TYPE_BMESH: { + BMEditMesh *em = mesh_final->edit_mesh; + EditMeshData *emd = mesh_final->runtime->edit_data; + if (emd->vertexCos) { + BKE_editmesh_cache_ensure_vert_normals(em, emd); + BKE_editmesh_cache_ensure_poly_normals(em, emd); + } + return; + } + } } } -static void editbmesh_calc_modifier_final_normals_or_defer( - Mesh *mesh_final, const CustomData_MeshMasks *final_datamask) +static void editbmesh_calc_modifier_final_normals_or_defer(Mesh *mesh_final) { if (mesh_final->runtime->wrapper_type != ME_WRAPPER_TYPE_MDATA) { /* Generated at draw time. */ @@ -1081,7 +1095,7 @@ static void editbmesh_calc_modifier_final_normals_or_defer( return; } - editbmesh_calc_modifier_final_normals(mesh_final, final_datamask); + editbmesh_calc_modifier_final_normals(mesh_final); } static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, @@ -1362,9 +1376,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } /* Compute normals. */ - editbmesh_calc_modifier_final_normals_or_defer(mesh_final, &final_datamask); + editbmesh_calc_modifier_final_normals_or_defer(mesh_final); if (mesh_cage && (mesh_cage != mesh_final)) { - editbmesh_calc_modifier_final_normals_or_defer(mesh_cage, &final_datamask); + editbmesh_calc_modifier_final_normals_or_defer(mesh_cage); } /* Return final mesh. */ diff --git a/source/blender/blenkernel/intern/data_transfer.cc b/source/blender/blenkernel/intern/data_transfer.cc index 483d2313783..dff32a70f2c 100644 --- a/source/blender/blenkernel/intern/data_transfer.cc +++ b/source/blender/blenkernel/intern/data_transfer.cc @@ -361,11 +361,11 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst, blender::float3 *loop_nors_dst = static_cast( CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->totloop)); - short(*custom_nors_dst)[2] = static_cast( + blender::short2 *custom_nors_dst = static_cast( CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop)); if (!custom_nors_dst) { - custom_nors_dst = static_cast( + custom_nors_dst = static_cast( CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me_dst->totloop)); } @@ -1503,7 +1503,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (DT_DATATYPE_IS_LOOP(dtdata_type)) { const float(*positions_dst)[3] = BKE_mesh_vert_positions(me_dst); const int num_verts_dst = me_dst->totvert; - const blender::Span edges_dst = me_dst->edges(); const blender::OffsetIndices polys_dst = me_dst->polys(); const blender::Span corner_verts_dst = me_dst->corner_verts(); @@ -1542,8 +1541,6 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, me_dst, positions_dst, num_verts_dst, - edges_dst.data(), - edges_dst.size(), corner_verts_dst.data(), corner_verts_dst.size(), polys_dst, diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index 45e8abe2a53..bee345ac25b 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -758,7 +758,6 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph, if (geometry_set.has_mesh()) { Mesh *final_mesh = geometry_set.get_mesh_for_write(); - BKE_mesh_ensure_normals_for_display(final_mesh); BLI_strncpy(final_mesh->id.name, cu->id.name, sizeof(final_mesh->id.name)); *((short *)final_mesh->id.name) = ID_ME; diff --git a/source/blender/blenkernel/intern/editmesh.cc b/source/blender/blenkernel/intern/editmesh.cc index a2b90cae6e1..679d762e22c 100644 --- a/source/blender/blenkernel/intern/editmesh.cc +++ b/source/blender/blenkernel/intern/editmesh.cc @@ -250,7 +250,7 @@ float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3] return BM_mesh_vert_coords_alloc(em->bm, r_vert_len); } -void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me) +void BKE_editmesh_lnorspace_update(BMEditMesh *em) { BM_lnorspace_update(em->bm); } diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index fedc2e3247a..ae00baf2bc3 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -2280,7 +2280,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, "sharp_edge", ATTR_DOMAIN_EDGE, false); const blender::VArray sharp_faces = attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); - const short(*custom_normals)[2] = static_cast( + const blender::short2 *custom_normals = static_cast( CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)); blender::bke::mesh::normals_calc_loop( {reinterpret_cast(positions), mesh->totvert}, diff --git a/source/blender/blenkernel/intern/mesh_mirror.cc b/source/blender/blenkernel/intern/mesh_mirror.cc index 86278e58559..536ea21b449 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.cc +++ b/source/blender/blenkernel/intern/mesh_mirror.cc @@ -380,7 +380,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, result->totpoly > 0) { blender::Array loop_normals(result_corner_verts.size()); CustomData *ldata = &result->ldata; - short(*clnors)[2] = static_cast( + blender::short2 *clnors = static_cast( CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop)); MLoopNorSpaceArray lnors_spacearr = {nullptr}; diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 361bc9d346e..fd02b7a82de 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -319,8 +319,8 @@ enum class BoolArrayMix { AllTrue, Mixed, }; -BoolArrayMix bool_array_mix_calc(const VArray &varray, - const blender::IndexRange range_to_check) +static BoolArrayMix bool_array_mix_calc(const VArray &varray, + const blender::IndexRange range_to_check) { using namespace blender; if (varray.is_empty()) { @@ -372,7 +372,7 @@ BoolArrayMix bool_array_mix_calc(const VArray &varray, [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); } -BoolArrayMix bool_array_mix_calc(const VArray &varray) +static BoolArrayMix bool_array_mix_calc(const VArray &varray) { return bool_array_mix_calc(varray, varray.index_range()); } @@ -381,9 +381,11 @@ eAttrDomain Mesh::normal_domain_all_info() const { using namespace blender; using namespace blender::bke; - const short(*custom_normals)[2] = static_cast( - CustomData_get_layer(&this->ldata, CD_CUSTOMLOOPNORMAL)); - if (custom_normals) { + if (this->totpoly == 0) { + return ATTR_DOMAIN_POINT; + } + + if (CustomData_has_layer(&this->ldata, CD_CUSTOMLOOPNORMAL)) { return ATTR_DOMAIN_CORNER; } @@ -520,7 +522,7 @@ blender::Span Mesh::corner_normals() const "sharp_edge", ATTR_DOMAIN_EDGE, false); const VArray sharp_faces = attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); - const short(*custom_normals)[2] = static_cast( + const short2 *custom_normals = static_cast( CustomData_get_layer(&this->ldata, CD_CUSTOMLOOPNORMAL)); bke::mesh::normals_calc_loop(this->vert_positions(), @@ -553,26 +555,6 @@ const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] return reinterpret_cast(mesh->corner_normals().data()); } -void BKE_mesh_ensure_normals_for_display(Mesh *mesh) -{ - switch (mesh->runtime->wrapper_type) { - case ME_WRAPPER_TYPE_SUBD: - case ME_WRAPPER_TYPE_MDATA: - mesh->vert_normals(); - mesh->poly_normals(); - break; - case ME_WRAPPER_TYPE_BMESH: { - BMEditMesh *em = mesh->edit_mesh; - EditMeshData *emd = mesh->runtime->edit_data; - if (emd->vertexCos) { - BKE_editmesh_cache_ensure_vert_normals(em, emd); - BKE_editmesh_cache_ensure_poly_normals(em, emd); - } - return; - } - } -} - void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops, const char data_type) @@ -1589,7 +1571,7 @@ void normals_calc_loop(const Span vert_positions, const Span poly_normals, const VArray &sharp_edges, const VArray &sharp_faces, - short (*clnors_data)[2], + const short2 *custom_normals_data, MLoopNorSpaceArray *r_lnors_spacearr, MutableSpan r_loop_normals) { @@ -1626,7 +1608,7 @@ void normals_calc_loop(const Span vert_positions, SCOPED_TIMER_AVERAGED(__func__); #endif - if (!r_lnors_spacearr && clnors_data) { + if (!r_lnors_spacearr && custom_normals_data) { /* We need to compute lnor spacearr if some custom lnor data are given to us! */ r_lnors_spacearr = &_lnors_spacearr; } @@ -1638,8 +1620,8 @@ void normals_calc_loop(const Span vert_positions, LoopSplitTaskDataCommon common_data; common_data.lnors_spacearr = r_lnors_spacearr; common_data.loop_normals = r_loop_normals; - common_data.clnors_data = {reinterpret_cast(clnors_data), - clnors_data ? corner_verts.size() : 0}; + common_data.clnors_data = {const_cast(custom_normals_data), + custom_normals_data ? corner_verts.size() : 0}; common_data.positions = vert_positions; common_data.edges = edges; common_data.polys = polys; @@ -1704,7 +1686,7 @@ static void mesh_normals_loop_custom_set(Span positions, const bool use_vertices, MutableSpan r_custom_loop_normals, MutableSpan sharp_edges, - short (*r_clnors_data)[2]) + short2 *r_clnors_data) { /* We *may* make that poor #bke::mesh::normals_calc_loop() even more complex by making it * handling that feature too, would probably be more efficient in absolute. However, this @@ -1926,7 +1908,7 @@ void normals_loop_custom_set(const Span vert_positions, const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_loop_normals, - short (*r_clnors_data)[2]) + short2 *r_clnors_data) { mesh_normals_loop_custom_set(vert_positions, edges, @@ -1952,7 +1934,7 @@ void normals_loop_custom_set_from_verts(const Span vert_positions, const VArray &sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_vert_normals, - short (*r_clnors_data)[2]) + short2 *r_clnors_data) { mesh_normals_loop_custom_set(vert_positions, edges, @@ -1970,16 +1952,16 @@ void normals_loop_custom_set_from_verts(const Span vert_positions, static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices) { - short(*clnors)[2]; + short2 *clnors; const int numloops = mesh->totloop; - clnors = (short(*)[2])CustomData_get_layer_for_write( + clnors = (short2 *)CustomData_get_layer_for_write( &mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop); if (clnors != nullptr) { memset(clnors, 0, sizeof(*clnors) * size_t(numloops)); } else { - clnors = (short(*)[2])CustomData_add_layer( + clnors = (short2 *)CustomData_add_layer( &mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, numloops); } MutableAttributeAccessor attributes = mesh->attributes_for_write(); diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index da485a22929..b1961d85c50 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -1206,8 +1206,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const Mesh *mesh_dst, const float (*vert_positions_dst)[3], const int numverts_dst, - const MEdge *edges_dst, - const int numedges_dst, const int *corner_verts_dst, const int numloops_dst, const blender::OffsetIndices polys_dst, diff --git a/source/blender/blenkernel/intern/mesh_runtime.cc b/source/blender/blenkernel/intern/mesh_runtime.cc index 85c391503b6..dea720e6209 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.cc +++ b/source/blender/blenkernel/intern/mesh_runtime.cc @@ -247,12 +247,14 @@ void BKE_mesh_tag_face_winding_changed(Mesh *mesh) { mesh->runtime->vert_normals_dirty = true; mesh->runtime->poly_normals_dirty = true; + mesh->runtime->corner_normals_dirty = true; } void BKE_mesh_tag_positions_changed(Mesh *mesh) { mesh->runtime->vert_normals_dirty = true; mesh->runtime->poly_normals_dirty = true; + mesh->runtime->corner_normals_dirty = true; free_bvh_cache(*mesh->runtime); mesh->runtime->looptris_cache.tag_dirty(); mesh->runtime->bounds_cache.tag_dirty(); diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index 36add44ba59..99e97ae8c24 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -140,7 +140,7 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me) } if (me->runtime->wrapper_type_finalize) { - BKE_mesh_wrapper_deferred_finalize_mdata(me, &me->runtime->cd_mask_extra); + BKE_mesh_wrapper_deferred_finalize_mdata(me); } /* Keep type assignment last, so that read-only access only uses the mdata code paths after all @@ -338,8 +338,9 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me) Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me); if (use_clnors) { - BKE_mesh_set_custom_normals( - subdiv_mesh, reinterpret_cast(subdiv_mesh->corner_normals().data())); + BKE_mesh_set_custom_normals(subdiv_mesh, + const_cast(reinterpret_cast( + subdiv_mesh->corner_normals().data()))); } if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) { diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index abdda14bb72..50ee995fd65 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -11,6 +11,8 @@ * To update preference defaults see `userdef_default.c`. */ +#define DNA_DEPRECATED_ALLOW + #include "MEM_guardedalloc.h" #include "BLI_listbase.h" diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 98de2ea60bd..6f72782eb13 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1796,7 +1796,6 @@ static BMOpDefine bmo_bevel_def = { {"miter_inner", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_bevel_miter_type}, /* outer miter kind */ {"spread", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ - {"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */ {"custom_profile", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_STRUCT}}, /* CurveProfile, if None ignored */ {"vmesh_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_bevel_vmesh_method}, /* The method to use to create meshes at intersections. */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index ef53f8bd9d9..fc3c50eb843 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -33,7 +33,6 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) const int miter_outer = BMO_slot_int_get(op->slots_in, "miter_outer"); const int miter_inner = BMO_slot_int_get(op->slots_in, "miter_inner"); const float spread = BMO_slot_float_get(op->slots_in, "spread"); - const float smoothresh = BMO_slot_float_get(op->slots_in, "smoothresh"); const CurveProfile *custom_profile = BMO_slot_ptr_get(op->slots_in, "custom_profile"); const int vmesh_method = BMO_slot_int_get(op->slots_in, "vmesh_method"); @@ -79,7 +78,6 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) miter_outer, miter_inner, spread, - smoothresh, custom_profile, vmesh_method); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 5118eb792d5..4890e778de6 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -367,8 +367,6 @@ typedef struct BevelParams { int vmesh_method; /** Amount to spread when doing inside miter. */ float spread; - /** Mesh's smoothresh, used if hardening. */ - float smoothresh; } BevelParams; // #pragma GCC diagnostic ignored "-Wpadded" @@ -2476,7 +2474,6 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm) * to mark the sharpen the edges that are only sharp because of the angle test -- otherwise would * be smooth. */ if (cd_clnors_offset == -1) { - BM_edges_sharp_from_angle_set(bm, bp->smoothresh); bevel_edges_sharp_boundary(bm, bp); } @@ -7724,7 +7721,6 @@ void BM_mesh_bevel(BMesh *bm, const int miter_outer, const int miter_inner, const float spread, - const float smoothresh, const struct CurveProfile *custom_profile, const int vmesh_method) { @@ -7757,7 +7753,6 @@ void BM_mesh_bevel(BMesh *bm, .miter_outer = miter_outer, .miter_inner = miter_inner, .spread = spread, - .smoothresh = smoothresh, .face_hash = NULL, .profile_type = profile_type, .custom_profile = custom_profile, diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 9729d19bb10..66a6349e212 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -41,6 +41,5 @@ void BM_mesh_bevel(BMesh *bm, int miter_outer, int miter_inner, float spread, - float smoothresh, const struct CurveProfile *custom_profile, int vmesh_method); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 1c5058a2a2b..51816798908 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -573,6 +573,7 @@ const bool *ED_mesh_uv_map_edge_select_layer_get(const struct Mesh *mesh, int uv const bool *ED_mesh_uv_map_pin_layer_get(const struct Mesh *mesh, int uv_map_index); bool ED_mesh_edge_is_loose(const struct Mesh *mesh, int index); +int ED_mesh_normal_domain_all_info_get(const struct Mesh *mesh); void ED_mesh_uv_ensure(struct Mesh *me, const char *name); int ED_mesh_uv_add( diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index eab2142a7e6..7413ae853d0 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -341,7 +341,7 @@ static bool edbm_bevel_calc(wmOperator *op) "bevel geom=%hev offset=%f segments=%i affect=%i offset_type=%i " "profile_type=%i profile=%f clamp_overlap=%b material=%i loop_slide=%b " "mark_seam=%b mark_sharp=%b harden_normals=%b face_strength_mode=%i " - "miter_outer=%i miter_inner=%i spread=%f smoothresh=%f custom_profile=%p " + "miter_outer=%i miter_inner=%i spread=%f custom_profile=%p " "vmesh_method=%i", BM_ELEM_SELECT, offset, @@ -360,7 +360,6 @@ static bool edbm_bevel_calc(wmOperator *op) miter_outer, miter_inner, spread, - me->smoothresh, opdata->custom_profile, vmesh_method); diff --git a/source/blender/editors/mesh/editmesh_tools.cc b/source/blender/editors/mesh/editmesh_tools.cc index 08bc5711cca..a74f6a38f94 100644 --- a/source/blender/editors/mesh/editmesh_tools.cc +++ b/source/blender/editors/mesh/editmesh_tools.cc @@ -8392,7 +8392,7 @@ static bool point_normals_init(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; - BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); + BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); op->customdata = lnors_ed_arr; @@ -9018,7 +9018,7 @@ static int normals_split_merge(bContext *C, const bool do_merge) BMEdge *e; BMIter eiter; - BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); + BKE_editmesh_lnorspace_update(em); /* Note that we need temp lnor editing data for all loops of all affected vertices, since by * setting some faces/edges as smooth we are going to change clnors spaces... See also #65809. @@ -9036,7 +9036,7 @@ static int normals_split_merge(bContext *C, const bool do_merge) } bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; - BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); + BKE_editmesh_lnorspace_update(em); if (do_merge) { normals_merge(bm, lnors_ed_arr); @@ -9157,7 +9157,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) BMIter fiter; bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; - BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); + BKE_editmesh_lnorspace_update(em); const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); @@ -9404,7 +9404,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) continue; } - BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); + BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; @@ -9628,7 +9628,7 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp"); - BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); + BKE_editmesh_lnorspace_update(em); float(*vert_normals)[3] = static_cast( MEM_mallocN(sizeof(*vert_normals) * bm->totvert, __func__)); @@ -9735,7 +9735,7 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) BMLoop *l; BMIter fiter, liter; - BKE_editmesh_lnorspace_update(em, static_cast(obedit->data)); + BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); float(*smooth_normal)[3] = static_cast( diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 794c30d58de..313f4ef2514 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1110,6 +1110,11 @@ bool ED_mesh_edge_is_loose(const Mesh *mesh, const int index) return loose_edges.count > 0 && loose_edges.is_loose_bits[index]; } +int ED_mesh_normal_domain_all_info_get(const Mesh *mesh) +{ + return mesh->normal_domain_all_info(); +} + static void mesh_add_verts(Mesh *mesh, int len) { using namespace blender; @@ -1450,7 +1455,6 @@ void ED_mesh_split_faces(Mesh *mesh) { using namespace blender; const OffsetIndices polys = mesh->polys(); - const Span corner_verts = mesh->corner_verts(); const Span corner_edges = mesh->corner_edges(); const bke::AttributeAccessor attributes = mesh->attributes(); const VArray mesh_sharp_edges = attributes.lookup_or_default( diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 170ee0dbc37..53d89038835 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2016,7 +2016,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve else if (!do_skip) { const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); if (preserve_clnor) { - BKE_editmesh_lnorspace_update(em, tc->obedit->data); + BKE_editmesh_lnorspace_update(em); t->flag |= T_CLNOR_REBUILD; } BM_lnorspace_invalidate(em->bm, true); diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c index 26e3e431809..14dafbe5781 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c @@ -128,7 +128,7 @@ void initNormalRotation(TransInfo *t) BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; - BKE_editmesh_lnorspace_update(em, tc->obedit->data); + BKE_editmesh_lnorspace_update(em); storeCustomLNorValue(tc, bm); } diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 5391c019e48..ab6ed8110bb 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -70,7 +70,7 @@ static void get_edge_creases(struct Mesh *mesh, static void get_vert_creases(struct Mesh *mesh, std::vector &indices, std::vector &sharpnesses); -static void get_loop_normals(struct Mesh *mesh, std::vector &normals); +static void get_loop_normals(const Mesh *mesh, std::vector &normals); ABCGenericMeshWriter::ABCGenericMeshWriter(const ABCWriterConstructorArgs &args) : ABCAbstractWriter(args), is_subd_(false) @@ -277,10 +277,9 @@ void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *me std::vector points; std::vector poly_verts, loop_counts; std::vector edge_crease_indices, edge_crease_lengths, vert_crease_indices; - bool has_flat_poly = false; get_vertices(mesh, points); - get_topology(mesh, poly_verts, loop_counts, has_flat_poly); + get_topology(mesh, poly_verts, loop_counts); get_edge_creases(mesh, edge_crease_indices, edge_crease_lengths, edge_crease_sharpness); get_vert_creases(mesh, vert_crease_indices, vert_crease_sharpness); diff --git a/source/blender/makesdna/DNA_mesh_defaults.h b/source/blender/makesdna/DNA_mesh_defaults.h index 32a85e73b84..debb67ac910 100644 --- a/source/blender/makesdna/DNA_mesh_defaults.h +++ b/source/blender/makesdna/DNA_mesh_defaults.h @@ -16,7 +16,6 @@ #define _DNA_DEFAULT_Mesh \ { \ .texspace_size = {1.0f, 1.0f, 1.0f}, \ - .smoothresh = DEG2RADF(30), \ .texspace_flag = ME_TEXSPACE_FLAG_AUTO, \ .remesh_voxel_size = 0.1f, \ .remesh_voxel_adaptivity = 0.0f, \ diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index e61e9ac6f1e..a055d4aa25b 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -148,7 +148,7 @@ typedef struct Mesh { /** * The angle for auto smooth in radians. `M_PI` (180 degrees) causes all edges to be smooth. */ - float smoothresh; + float smoothresh DNA_DEPRECATED; /** Per-mesh settings for voxel remesh. */ float remesh_voxel_size; diff --git a/source/blender/makesrna/RNA_enum_items.h b/source/blender/makesrna/RNA_enum_items.h index 510469c2756..41b27df8743 100644 --- a/source/blender/makesrna/RNA_enum_items.h +++ b/source/blender/makesrna/RNA_enum_items.h @@ -213,6 +213,7 @@ DEF_ENUM(rna_enum_color_attribute_type_items) DEF_ENUM(rna_enum_attribute_type_with_auto_items) DEF_ENUM(rna_enum_attribute_domain_items) DEF_ENUM(rna_enum_attribute_domain_only_mesh_items) +DEF_ENUM(rna_enum_attribute_domain_only_mesh_no_edge_items) DEF_ENUM(rna_enum_attribute_curves_domain_items) DEF_ENUM(rna_enum_color_attribute_domain_items) DEF_ENUM(rna_enum_attribute_domain_without_corner_items) diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index 3aedc92a248..43cda0247ab 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -91,6 +91,13 @@ const EnumPropertyItem rna_enum_attribute_domain_only_mesh_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_attribute_domain_only_mesh_no_edge_items[] = { + {ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"}, + {ATTR_DOMAIN_FACE, "FACE", 0, "Face", "Attribute on mesh faces"}, + {ATTR_DOMAIN_CORNER, "CORNER", 0, "Face Corner", "Attribute on mesh face corner"}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_attribute_domain_without_corner_items[] = { {ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"}, {ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"}, diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index f7157064775..23638381875 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -620,10 +620,10 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values) Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); - const float(*vec)[4] = CustomData_get(&me->ldata, index, CD_MLOOPTANGENT); + const float(*vec)[4] = CustomData_get_layer(&me->ldata, CD_MLOOPTANGENT); if (vec) { - cross_v3_v3v3(values, loop_normals[index][index], vec[index]); + cross_v3_v3v3(values, loop_normals[index], vec[index]); mul_v3_fl(values, vec[index][3]); } else { @@ -2043,6 +2043,12 @@ int rna_Mesh_loops_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) return true; } +static int rna_Mesh_normal_domain_all_info_get(PointerRNA *ptr) +{ + const Mesh *mesh = rna_mesh(ptr); + return ED_mesh_normal_domain_all_info_get(mesh); +} + static void rna_Mesh_vertex_normals_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); @@ -4217,6 +4223,12 @@ static void rna_def_mesh(BlenderRNA *brna) rna_def_normal_layer_value(brna); + prop = RNA_def_property(srna, "normal_domain_all_info", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_attribute_domain_only_mesh_no_edge_items); + RNA_def_property_ui_text(prop, "Normal Domain ALl Info", ""); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_enum_funcs(prop, "rna_Mesh_normal_domain_all_info_get", NULL, NULL); + prop = RNA_def_property(srna, "vertex_normals", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "MeshNormalValue"); RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index d0c876ec306..3644622eb16 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -48,7 +48,7 @@ static void rna_Mesh_create_normals_split(Mesh *mesh) BKE_mesh_corner_normals_ensure(mesh); } -static void rna_Mesh_free_normals_split(Mesh *mesh) +static void rna_Mesh_free_normals_split(Mesh *UNUSED(mesh)) { /* TODO: Deprecation? */ } diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index e2b07cf16fa..2c5ec9df179 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -192,8 +192,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } } - Object *ob = ctx->object; - BM_mesh_bevel(bm, value, offset_type, @@ -214,7 +212,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * miter_outer, miter_inner, spread, - mesh->smoothresh, bmd->custom_profile, bmd->vmesh_method); diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index 8db958b1a56..c8aa484588b 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -222,7 +222,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, const ModifierEvalContext * /*ctx*/, Object *ob, Mesh *mesh, - short (*clnors)[2], + blender::short2 *clnors, blender::MutableSpan loop_normals, const short mix_mode, const float mix_factor, @@ -353,7 +353,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, const ModifierEvalContext * /*ctx*/, Object *ob, Mesh *mesh, - short (*clnors)[2], + blender::short2 *clnors, blender::MutableSpan loop_normals, const short mix_mode, const float mix_factor, @@ -519,10 +519,10 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - short(*clnors)[2] = static_cast( + blender::short2 *clnors = static_cast( CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); if (use_current_clnors) { - clnors = static_cast( + clnors = static_cast( CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); loop_normals.reinitialize(corner_verts.size()); const VArray sharp_faces = attributes.lookup_or_default( @@ -543,7 +543,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, } if (clnors == nullptr) { - clnors = static_cast( + clnors = static_cast( CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size())); } diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index 2905fa901a8..3787c717b6c 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -78,7 +78,7 @@ struct WeightedNormalData { blender::Span corner_verts; blender::Span corner_edges; blender::Span loop_to_poly; - short (*clnors)[2]; + blender::short2 *clnors; bool has_clnors; /* True if clnors already existed, false if we had to create them. */ blender::OffsetIndices polys; @@ -190,7 +190,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, const blender::Span corner_verts = wn_data->corner_verts; const blender::Span corner_edges = wn_data->corner_edges; - short(*clnors)[2] = wn_data->clnors; + blender::short2 *clnors = wn_data->clnors; const blender::Span loop_to_poly = wn_data->loop_to_poly; const blender::Span poly_normals = wn_data->poly_normals; @@ -513,7 +513,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * { using namespace blender; WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md; - Object *ob = ctx->object; Mesh *result = (Mesh *)BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE); @@ -541,14 +540,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * weight = (weight - 1) * 25; } - short(*clnors)[2] = static_cast( + blender::short2 *clnors = static_cast( CustomData_get_layer_for_write(&result->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop)); /* Keep info whether we had clnors, * it helps when generating clnor spaces and default normals. */ const bool has_clnors = clnors != nullptr; if (!clnors) { - clnors = static_cast(CustomData_add_layer( + clnors = static_cast(CustomData_add_layer( &result->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size())); } -- 2.30.2 From 003bf9ef0f294de223632cebd54ef51e5f23bb54 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 14 Apr 2023 17:24:56 -0400 Subject: [PATCH 10/85] Cleanup --- source/blender/blenkernel/BKE_mesh_sample.hh | 15 ++++ .../blender/blenkernel/intern/mesh_sample.cc | 82 ++++++++++++------- .../node_geo_distribute_points_on_faces.cc | 28 +++---- 3 files changed, 80 insertions(+), 45 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh index 3f181d0ae28..d3f0e32f56a 100644 --- a/source/blender/blenkernel/BKE_mesh_sample.hh +++ b/source/blender/blenkernel/BKE_mesh_sample.hh @@ -30,6 +30,14 @@ void sample_point_attribute(const Mesh &mesh, IndexMask mask, GMutableSpan dst); +void sample_point_normals(const Span corner_verts, + const Span looptris, + const Span looptri_indices, + const Span bary_coords, + const Span src, + const IndexMask mask, + const MutableSpan dst); + void sample_corner_attribute(const Mesh &mesh, Span looptri_indices, Span bary_coords, @@ -37,6 +45,13 @@ void sample_corner_attribute(const Mesh &mesh, IndexMask mask, GMutableSpan dst); +void sample_corner_normals(const Span looptris, + const Span looptri_indices, + const Span bary_coords, + const Span src, + const IndexMask mask, + const MutableSpan dst); + void sample_face_attribute(const Mesh &mesh, Span looptri_indices, const GVArray &src, diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 4c7474e244c..08c05da9884 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -13,8 +13,28 @@ namespace blender::bke::mesh_surface_sample { +void sample_point_normals(const Span corner_verts, + const Span looptris, + const Span looptri_indices, + const Span bary_coords, + const Span src, + const IndexMask mask, + const MutableSpan dst) +{ + for (const int i : mask) { + const MLoopTri &tri = looptris[looptri_indices[i]]; + const float3 &bary_coord = bary_coords[i]; + const float3 value = attribute_math::mix3(bary_coord, + src[corner_verts[tri.tri[0]]], + src[corner_verts[tri.tri[1]]], + src[corner_verts[tri.tri[2]]]); + dst[i] = math::normalize(value); + } +} + template -BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh, +BLI_NOINLINE static void sample_point_attribute(const Span corner_verts, + const Span looptris, const Span looptri_indices, const Span bary_coords, const VArray &src, @@ -25,20 +45,12 @@ BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh, const Span looptris = mesh.looptris(); for (const int i : mask) { - const int looptri_index = looptri_indices[i]; - const MLoopTri &looptri = looptris[looptri_index]; + const MLoopTri &tri = looptris[looptri_indices[i]]; const float3 &bary_coord = bary_coords[i]; - - const int v0_index = corner_verts[looptri.tri[0]]; - const int v1_index = corner_verts[looptri.tri[1]]; - const int v2_index = corner_verts[looptri.tri[2]]; - - const T v0 = src[v0_index]; - const T v1 = src[v1_index]; - const T v2 = src[v2_index]; - - const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); - dst[i] = interpolated_value; + dst[i] = attribute_math::mix3(bary_coord, + src[corner_verts[tri.tri[0]]], + src[corner_verts[tri.tri[1]]], + src[corner_verts[tri.tri[2]]]); } } @@ -55,36 +67,46 @@ void sample_point_attribute(const Mesh &mesh, const CPPType &type = src.type(); attribute_math::convert_to_static_type(type, [&](auto dummy) { using T = decltype(dummy); - sample_point_attribute( - mesh, looptri_indices, bary_coords, src.typed(), mask, dst.typed()); + sample_point_attribute(mesh.corner_verts(), + mesh.looptris(), + looptri_indices, + bary_coords, + src.typed(), + mask, + dst.typed()); }); } template -BLI_NOINLINE static void sample_corner_attribute(const Mesh &mesh, +BLI_NOINLINE static void sample_corner_attribute(const Span looptris, const Span looptri_indices, const Span bary_coords, const VArray &src, const IndexMask mask, const MutableSpan dst) { - const Span looptris = mesh.looptris(); - for (const int i : mask) { const int looptri_index = looptri_indices[i]; - const MLoopTri &looptri = looptris[looptri_index]; + const MLoopTri &tri = looptris[looptri_index]; const float3 &bary_coord = bary_coords[i]; + dst[i] = attribute_math::mix3(bary_coord, src[tri.tri[0]], src[tri.tri[1]], src[tri.tri[2]]); + } +} - const int loop_index_0 = looptri.tri[0]; - const int loop_index_1 = looptri.tri[1]; - const int loop_index_2 = looptri.tri[2]; - - const T v0 = src[loop_index_0]; - const T v1 = src[loop_index_1]; - const T v2 = src[loop_index_2]; - - const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); - dst[i] = interpolated_value; +void sample_corner_normals(const Span looptris, + const Span looptri_indices, + const Span bary_coords, + const Span src, + const IndexMask mask, + const MutableSpan dst) +{ + for (const int i : mask) { + const int looptri_index = looptri_indices[i]; + const MLoopTri &tri = looptris[looptri_index]; + const float3 &bary_coord = bary_coords[i]; + const float3 value = attribute_math::mix3( + bary_coord, src[tri.tri[0]], src[tri.tri[1]], src[tri.tri[2]]); + dst[i] = math::normalize(value); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 38345b5294e..f20a71c92a9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -332,16 +332,15 @@ static void compute_normal_outputs(const Mesh &mesh, const Span looptri_indices, MutableSpan r_normals) { - /* TODO: Normalization. */ switch (mesh.normal_domain_all_info()) { case ATTR_DOMAIN_POINT: { - const Span vert_normals = mesh.vert_normals(); - bke::mesh_surface_sample::sample_point_attribute(mesh, - looptri_indices, - bary_coords, - VArray::ForSpan(vert_normals), - IndexMask(looptri_indices.index_range()), - r_normals); + bke::mesh_surface_sample::sample_point_normals(mesh.corner_verts(), + mesh.looptris(), + looptri_indices, + bary_coords, + mesh.vert_normals(), + IndexMask(looptri_indices.index_range()), + r_normals); break; } @@ -355,13 +354,12 @@ static void compute_normal_outputs(const Mesh &mesh, break; } case ATTR_DOMAIN_CORNER: { - const Span corner_normals = mesh.corner_normals(); - bke::mesh_surface_sample::sample_corner_attribute(mesh, - looptri_indices, - bary_coords, - VArray::ForSpan(corner_normals), - IndexMask(looptri_indices.index_range()), - r_normals); + bke::mesh_surface_sample::sample_corner_normals(mesh.looptris(), + looptri_indices, + bary_coords, + mesh.corner_normals(), + IndexMask(looptri_indices.index_range()), + r_normals); break; } default: -- 2.30.2 From 737dc652344d3de49e104e2e104b8706cd8dce75 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 16 Apr 2023 14:18:38 -0400 Subject: [PATCH 11/85] Cleanup --- .../blender/blenkernel/intern/mesh_sample.cc | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 08c05da9884..4f898bd4ddc 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -13,6 +13,25 @@ namespace blender::bke::mesh_surface_sample { +template +BLI_NOINLINE static void sample_point_attribute(const Span corner_verts, + const Span looptris, + const Span looptri_indices, + const Span bary_coords, + const VArray &src, + const IndexMask mask, + const MutableSpan dst) +{ + for (const int i : mask) { + const MLoopTri &tri = looptris[looptri_indices[i]]; + const float3 &bary_coord = bary_coords[i]; + dst[i] = attribute_math::mix3(bary_coord, + src[corner_verts[tri.tri[0]]], + src[corner_verts[tri.tri[1]]], + src[corner_verts[tri.tri[2]]]); + } +} + void sample_point_normals(const Span corner_verts, const Span looptris, const Span looptri_indices, @@ -32,28 +51,6 @@ void sample_point_normals(const Span corner_verts, } } -template -BLI_NOINLINE static void sample_point_attribute(const Span corner_verts, - const Span looptris, - const Span looptri_indices, - const Span bary_coords, - const VArray &src, - const IndexMask mask, - const MutableSpan dst) -{ - const Span corner_verts = mesh.corner_verts(); - const Span looptris = mesh.looptris(); - - for (const int i : mask) { - const MLoopTri &tri = looptris[looptri_indices[i]]; - const float3 &bary_coord = bary_coords[i]; - dst[i] = attribute_math::mix3(bary_coord, - src[corner_verts[tri.tri[0]]], - src[corner_verts[tri.tri[1]]], - src[corner_verts[tri.tri[2]]]); - } -} - void sample_point_attribute(const Mesh &mesh, const Span looptri_indices, const Span bary_coords, @@ -124,19 +121,17 @@ void sample_corner_attribute(const Mesh &mesh, attribute_math::convert_to_static_type(type, [&](auto dummy) { using T = decltype(dummy); sample_corner_attribute( - mesh, looptri_indices, bary_coords, src.typed(), mask, dst.typed()); + mesh.looptris(), looptri_indices, bary_coords, src.typed(), mask, dst.typed()); }); } template -void sample_face_attribute(const Mesh &mesh, +void sample_face_attribute(const Span looptris, const Span looptri_indices, const VArray &src, const IndexMask mask, const MutableSpan dst) { - const Span looptris = mesh.looptris(); - for (const int i : mask) { const int looptri_index = looptri_indices[i]; const MLoopTri &looptri = looptris[looptri_index]; @@ -157,7 +152,8 @@ void sample_face_attribute(const Mesh &mesh, const CPPType &type = src.type(); attribute_math::convert_to_static_type(type, [&](auto dummy) { using T = decltype(dummy); - sample_face_attribute(mesh, looptri_indices, src.typed(), mask, dst.typed()); + sample_face_attribute( + mesh.looptris(), looptri_indices, src.typed(), mask, dst.typed()); }); } -- 2.30.2 From cb2220999e430d0013fb72209608b0d130a15024 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 27 Apr 2023 23:39:22 -0400 Subject: [PATCH 12/85] Fixes/cleanup --- intern/cycles/blender/mesh.cpp | 3 ++- intern/cycles/blender/util.h | 8 +++---- source/blender/blenkernel/BKE_mesh.h | 2 +- source/blender/blenkernel/intern/displist.cc | 2 -- source/blender/blenkernel/intern/key.cc | 4 ++-- source/blender/blenkernel/intern/mesh.cc | 6 +++--- .../blender/blenkernel/intern/mesh_mirror.cc | 4 ++-- .../blender/blenkernel/intern/mesh_normals.cc | 21 +++++++++++-------- .../blender/blenkernel/intern/mesh_sample.cc | 6 ++---- source/blender/editors/mesh/editmesh_bevel.c | 2 -- source/blender/editors/mesh/mesh_data.cc | 2 +- .../editors/sculpt_paint/curves_sculpt_add.cc | 2 +- .../sculpt_paint/curves_sculpt_density.cc | 4 ++-- .../sculpt_paint/curves_sculpt_puff.cc | 6 +++--- .../sculpt_paint/curves_sculpt_slide.cc | 4 ++-- .../blender/io/usd/intern/usd_writer_mesh.cc | 3 +-- .../wavefront_obj/importer/obj_import_mesh.cc | 1 - source/blender/makesrna/intern/rna_mesh.c | 5 ++++- source/blender/makesrna/intern/rna_mesh_api.c | 21 ------------------- .../modifiers/intern/MOD_normal_edit.cc | 6 +++--- .../modifiers/intern/MOD_weighted_normal.cc | 2 +- 21 files changed, 46 insertions(+), 68 deletions(-) diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index 913eb96fce8..6417abf37ab 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -998,7 +998,8 @@ static void create_mesh(Scene *scene, const int polys_num = b_mesh.polygons.length(); int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length(); const int numcorners = b_mesh.loops.length(); - bool use_loop_normals = b_mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT && + bool use_loop_normals = b_mesh.normal_domain_all_info() == + BL::Mesh::normal_domain_all_info_CORNER && (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK); /* If no faces, create empty mesh. */ diff --git a/intern/cycles/blender/util.h b/intern/cycles/blender/util.h index d0bbefc6203..316e459917a 100644 --- a/intern/cycles/blender/util.h +++ b/intern/cycles/blender/util.h @@ -87,8 +87,9 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, /* Make a copy to split faces if we use autosmooth, otherwise not needed. * Also in edit mode do we need to make a copy, to ensure data layers like * UV are not empty. */ - if (mesh.is_editmode() || (mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT && - subdivision_type == Mesh::SUBDIVISION_NONE)) { + if (mesh.is_editmode() || + (mesh.normal_domain_all_info() == BL::Mesh::normal_domain_all_info_CORNER && + subdivision_type == Mesh::SUBDIVISION_NONE)) { BL::Depsgraph depsgraph(PointerRNA_NULL); mesh = b_ob_info.real_object.to_mesh(false, depsgraph); } @@ -112,8 +113,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, #endif if ((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) { - if (mesh.normal_domain_all_info()== BL::Mesh::normal_domain_all_info_POINT) { - mesh.calc_normals_split(); + if (mesh.normal_domain_all_info() == BL::Mesh::normal_domain_all_info_CORNER) { mesh.split_faces(false); } diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index e1c10d8c15c..1ad973da1e3 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -214,7 +214,7 @@ bool BKE_mesh_material_index_used(struct Mesh *me, short index); void BKE_mesh_material_index_clear(struct Mesh *me); void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len); void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth); -void BKE_mesh_sharp_edges_set_from_angle(struct Mesh *me, float auto_smooth_angle); +void BKE_mesh_sharp_edges_set_from_angle(struct Mesh *me, float angle); /** * Used for unit testing; compares two meshes, checking only diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index bee345ac25b..0588ca8de6c 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -757,8 +757,6 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph, if (geometry_set.has_mesh()) { Mesh *final_mesh = geometry_set.get_mesh_for_write(); - - BLI_strncpy(final_mesh->id.name, cu->id.name, sizeof(final_mesh->id.name)); *((short *)final_mesh->id.name) = ID_ME; } diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index bea8ef7f6c9..3fd08fb2bc1 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -2276,9 +2276,9 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, } if (loop_normals_needed) { const blender::bke::AttributeAccessor attributes = mesh->attributes(); - const blender::VArray sharp_edges = attributes.lookup_or_default( + const blender::VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const blender::VArray sharp_faces = attributes.lookup_or_default( + const blender::VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); const blender::short2 *custom_normals = static_cast( CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index e0a371a1d47..9c2bf18b06a 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1554,21 +1554,21 @@ void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth) } } -void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float auto_smooth_angle) +void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle) { using namespace blender; using namespace blender::bke; bke::MutableAttributeAccessor attributes = me->attributes_for_write(); bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); bke::mesh::edges_sharp_from_angle_set(me->polys(), me->corner_verts(), me->corner_edges(), me->poly_normals(), sharp_faces, - auto_smooth_angle, + angle, sharp_edges.span); sharp_edges.finish(); } diff --git a/source/blender/blenkernel/intern/mesh_mirror.cc b/source/blender/blenkernel/intern/mesh_mirror.cc index d893397bd0c..4d0f6a11e88 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.cc +++ b/source/blender/blenkernel/intern/mesh_mirror.cc @@ -392,9 +392,9 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, /* calculate custom normals into loop_normals, then mirror first half into second half */ const blender::bke::AttributeAccessor attributes = result->attributes(); - const blender::VArray sharp_edges = attributes.lookup_or_default( + const blender::VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const blender::VArray sharp_faces = attributes.lookup_or_default( + const blender::VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_calc_loop(result->vert_positions(), result_edges, diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 1e47967819c..a85d2b7db6e 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -293,14 +293,16 @@ void normals_calc_poly_vert(const Span positions, } } -/** \} */ - } // namespace blender::bke::mesh +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Mesh Normal Calculation * \{ */ +namespace blender::bke { + enum class BoolArrayMix { None, AllFalse, @@ -365,6 +367,8 @@ static BoolArrayMix bool_array_mix_calc(const VArray &varray) return bool_array_mix_calc(varray, varray.index_range()); } +} // namespace blender::bke + eAttrDomain Mesh::normal_domain_all_info() const { using namespace blender; @@ -378,7 +382,7 @@ eAttrDomain Mesh::normal_domain_all_info() const } const AttributeAccessor attributes = this->attributes(); - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); const BoolArrayMix face_mix = bool_array_mix_calc(sharp_faces); @@ -386,7 +390,7 @@ eAttrDomain Mesh::normal_domain_all_info() const return ATTR_DOMAIN_FACE; } - const VArray sharp_edges = attributes.lookup_or_default( + const VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); const BoolArrayMix edge_mix = bool_array_mix_calc(sharp_edges); if (edge_mix == BoolArrayMix::AllTrue) { @@ -507,9 +511,9 @@ blender::Span Mesh::corner_normals() const } case ATTR_DOMAIN_CORNER: { const AttributeAccessor attributes = this->attributes(); - const VArray sharp_edges = attributes.lookup_or_default( + const VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); const short2 *custom_normals = static_cast( CustomData_get_layer(&this->ldata, CD_CUSTOMLOOPNORMAL)); @@ -925,8 +929,7 @@ static void build_edge_to_loop_map(const OffsetIndices polys, /* Second loop using this edge, time to test its sharpness. * An edge is sharp if it is tagged as such, or its face is not smooth, * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the - * same vertex, or angle between both its polys' normals is above split_angle value. - */ + * same vertex. */ if (sharp_faces[poly_i] || sharp_edges[edge_i] || vert_i == corner_verts[e2l[0]]) { /* NOTE: we are sure that loop != 0 here ;). */ e2l[1] = INDEX_INVALID; @@ -1814,7 +1817,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const MutableAttributeAccessor attributes = mesh->attributes_for_write(); SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); mesh_normals_loop_custom_set( diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 4f898bd4ddc..dde2e6a9dd4 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -24,8 +24,7 @@ BLI_NOINLINE static void sample_point_attribute(const Span corner_verts, { for (const int i : mask) { const MLoopTri &tri = looptris[looptri_indices[i]]; - const float3 &bary_coord = bary_coords[i]; - dst[i] = attribute_math::mix3(bary_coord, + dst[i] = attribute_math::mix3(bary_coords[i], src[corner_verts[tri.tri[0]]], src[corner_verts[tri.tri[1]]], src[corner_verts[tri.tri[2]]]); @@ -42,8 +41,7 @@ void sample_point_normals(const Span corner_verts, { for (const int i : mask) { const MLoopTri &tri = looptris[looptri_indices[i]]; - const float3 &bary_coord = bary_coords[i]; - const float3 value = attribute_math::mix3(bary_coord, + const float3 value = attribute_math::mix3(bary_coords[i], src[corner_verts[tri.tri[0]]], src[corner_verts[tri.tri[1]]], src[corner_verts[tri.tri[2]]]); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 7413ae853d0..0a6ddba8210 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -333,8 +333,6 @@ static bool edbm_bevel_calc(wmOperator *op) const int material = CLAMPIS(material_init, -1, obedit->totcol - 1); - Mesh *me = obedit->data; - EDBM_op_init(em, &bmop, op, diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 4544c921603..6288c8168cf 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1462,7 +1462,7 @@ void ED_mesh_split_faces(Mesh *mesh) const bke::AttributeAccessor attributes = mesh->attributes(); const VArray mesh_sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); Array sharp_edges(mesh->totedge); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index 364fc44599f..ca7443e338e 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -125,7 +125,7 @@ struct AddOperationExecutor { transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface); Object &surface_ob_orig = *curves_id_orig_->surface; - const Mesh &surface_orig = *static_cast(surface_ob_orig.data); + const Mesh &surface_orig = *static_cast(surface_ob_orig.data); if (surface_orig.totpoly == 0) { report_empty_original_surface(stroke_extension.reports); return; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc index e0b1b96a58e..89243c6b56c 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc @@ -73,7 +73,7 @@ struct DensityAddOperationExecutor { CurvesGeometry *curves_orig_ = nullptr; Object *surface_ob_orig_ = nullptr; - Mesh *surface_orig_ = nullptr; + const Mesh *surface_orig_ = nullptr; Object *surface_ob_eval_ = nullptr; Mesh *surface_eval_ = nullptr; @@ -112,7 +112,7 @@ struct DensityAddOperationExecutor { } surface_ob_orig_ = curves_id_orig_->surface; - surface_orig_ = static_cast(surface_ob_orig_->data); + surface_orig_ = static_cast(surface_ob_orig_->data); if (surface_orig_->totpoly == 0) { report_empty_original_surface(stroke_extension.reports); return; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index 2f5e79941b1..c12d2b921c5 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -71,8 +71,8 @@ struct PuffOperationExecutor { CurvesSurfaceTransforms transforms_; - Object *surface_ob_ = nullptr; - Mesh *surface_ = nullptr; + const Object *surface_ob_ = nullptr; + const Mesh *surface_ = nullptr; Span surface_positions_; Span surface_corner_verts_; Span surface_looptris_; @@ -111,7 +111,7 @@ struct PuffOperationExecutor { falloff_shape_ = static_cast(brush_->falloff_shape); surface_ob_ = curves_id_->surface; - surface_ = static_cast(surface_ob_->data); + surface_ = static_cast(surface_ob_->data); transforms_ = CurvesSurfaceTransforms(*object_, surface_ob_); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc index 9c0e439f502..7f5311504d2 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc @@ -97,7 +97,7 @@ struct SlideOperationExecutor { CurvesGeometry *curves_orig_ = nullptr; Object *surface_ob_orig_ = nullptr; - Mesh *surface_orig_ = nullptr; + const Mesh *surface_orig_ = nullptr; Span surface_looptris_orig_; VArraySpan surface_uv_map_orig_; Span corner_normals_orig_su_; @@ -164,7 +164,7 @@ struct SlideOperationExecutor { transforms_ = CurvesSurfaceTransforms(*curves_ob_orig_, curves_id_orig_->surface); surface_ob_orig_ = curves_id_orig_->surface; - surface_orig_ = static_cast(surface_ob_orig_->data); + surface_orig_ = static_cast(surface_ob_orig_->data); if (surface_orig_->totpoly == 0) { report_empty_original_surface(stroke_extension.reports); return; diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 24b8844b03a..b5247fd2b34 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -503,8 +503,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ switch (mesh->normal_domain_all_info()) { case ATTR_DOMAIN_POINT: { - const Span corner_verts = mesh->corner_verts(); - array_utils::gather(mesh->vert_normals(), corner_verts, dst_normals); + array_utils::gather(mesh->vert_normals(), mesh->corner_verts(), dst_normals); break; } case ATTR_DOMAIN_FACE: { diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index 0d9bc542c33..d780980638c 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -381,7 +381,6 @@ void MeshFromGeometry::create_normals(Mesh *mesh) tot_loop_idx++; } } - BKE_mesh_set_custom_normals(mesh, loop_normals); MEM_freeN(loop_normals); } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 61ed12b235e..2ca2228b118 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -4242,7 +4242,10 @@ static void rna_def_mesh(BlenderRNA *brna) prop = RNA_def_property(srna, "normal_domain_all_info", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_domain_only_mesh_no_edge_items); - RNA_def_property_ui_text(prop, "Normal Domain ALl Info", ""); + RNA_def_property_ui_text( + prop, + "Normal Domain All Info", + "The attribute domain that gives enough information to represent the mesh's normals"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_funcs(prop, "rna_Mesh_normal_domain_all_info_get", NULL, NULL); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 03fbc29914e..97dbdabbf5c 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -42,17 +42,6 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, return ret; } -static void rna_Mesh_create_normals_split(Mesh *mesh) -{ - /* TODO: Deprecation? */ - BKE_mesh_corner_normals_ensure(mesh); -} - -static void rna_Mesh_free_normals_split(Mesh *UNUSED(mesh)) -{ - /* TODO: Deprecation? */ -} - static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap) { float(*r_looptangents)[4]; @@ -226,16 +215,6 @@ void RNA_api_mesh(StructRNA *srna) RNA_def_function_ui_description( func, "Deprecated. Has no effect. Normals are calculated upon retrieval"); - func = RNA_def_function(srna, "create_normals_split", "rna_Mesh_create_normals_split"); - RNA_def_function_ui_description(func, "Empty split vertex normals"); - - func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_create_normals_split"); - RNA_def_function_ui_description(func, - "Calculate split vertex normals, which preserve sharp edges"); - - func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split"); - RNA_def_function_ui_description(func, "Free split vertex normals"); - func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces"); RNA_def_function_ui_description(func, "Split faces based on the edge angle"); /* TODO: This parameter has no effect anymore, since the internal code does not need to diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index 40e7f5ffca6..faea9cb91c3 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -331,7 +331,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, corner_verts, corner_edges, nos.data(), &mesh->ldata, polys, mesh->poly_normals())) { BKE_mesh_tag_face_winding_changed(mesh); } - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_loop_custom_set(vert_positions, edges, @@ -440,7 +440,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, corner_verts, corner_edges, nos.data(), &mesh->ldata, polys, mesh->poly_normals())) { BKE_mesh_tag_face_winding_changed(mesh); } - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_loop_custom_set(positions, edges, @@ -525,7 +525,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, clnors = static_cast( CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); loop_normals.reinitialize(corner_verts.size()); - const VArray sharp_faces = attributes.lookup_or_default( + const VArray sharp_faces =* attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); blender::bke::mesh::normals_calc_loop(positions, edges, diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index a692d72642a..d1e91e594af 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -573,7 +573,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * wn_data.polys = polys; wn_data.poly_normals = mesh->poly_normals(); - wn_data.sharp_faces = attributes.lookup_or_default("sharp_face", ATTR_DOMAIN_FACE, false); + wn_data.sharp_faces = *attributes.lookup_or_default("sharp_face", ATTR_DOMAIN_FACE, false); wn_data.poly_strength = static_cast(CustomData_get_layer_named( &result->pdata, CD_PROP_INT32, MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID)); -- 2.30.2 From 5f42d264b173e917396c992e51ab9267002af156 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 10 May 2023 21:40:45 -0400 Subject: [PATCH 13/85] Fix compile error --- source/blender/blenkernel/intern/mesh_normals.cc | 3 ++- .../geometry/nodes/node_geo_distribute_points_on_faces.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index ebe29adf728..adb3df911df 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -1494,7 +1494,8 @@ void normals_calc_loop(const Span vert_positions, CornerNormalSpaceArray _lnors_spacearr; -#ifdef DEBUG_TIME SCOPED_TIMER_AVERAGED(__func__); +#ifdef DEBUG_TIME + SCOPED_TIMER_AVERAGED(__func__); #endif if (!r_lnors_spacearr && custom_normals_data) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 6f0f10c3ccd..a573a4d3557 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -343,7 +343,7 @@ static void compute_normal_outputs(const Mesh &mesh, } case ATTR_DOMAIN_FACE: { const Span poly_normals = mesh.poly_normals(); - bke::mesh_surface_sample::sample_face_attribute(mesh.looptris(), + bke::mesh_surface_sample::sample_face_attribute(mesh.looptri_polys(), looptri_indices, VArray::ForSpan(poly_normals), IndexMask(looptri_indices.index_range()), -- 2.30.2 From d70da203e48baba4d0e9bc7e09ca64d2685ec273 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 10 May 2023 21:40:53 -0400 Subject: [PATCH 14/85] Add nicer comment --- source/blender/makesdna/DNA_mesh_types.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 4b666fa40fd..683a8f2bdf6 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -336,11 +336,17 @@ typedef struct Mesh { void tag_loose_verts_none() const; /** - * \warning This ignores auto-smooth currently. This has to land *after* auto-smooth is turned - * into a modifier. + * Returns the least complex attribute domain needed to store normals encoding all relevant mesh + * data. When all edges or faces are sharp, face normals are enough. When all are smooth, vertex + * normals are enough. With a combination of sharp and smooth, normals may be "split", + * requiring face corner storage. + * + * Depending on the sharp edge and face tags and custom normals, sometimes a less complex + * domain is enough. When possible, it's preferred to use face normals over vertex normals and + * vertex normals over face corner normals, since there is a 2-4x performance cost increase for + * each step. */ eAttrDomain normal_domain_all_info() const; - /** * Normal direction of polygons, defined by positions and the winding direction of face corners. */ -- 2.30.2 From aa90e9ff89660f0c55533a2c0ac621c4c5011839 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 10 May 2023 22:03:34 -0400 Subject: [PATCH 15/85] Fix crash --- source/blender/blenkernel/BKE_mesh_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index c2af950854a..b56c6f590bb 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -166,7 +166,7 @@ struct MeshRuntime { */ bool vert_normals_dirty = true; bool poly_normals_dirty = true; - bool corner_normals_dirty = false; + bool corner_normals_dirty = true; mutable Vector vert_normals; mutable Vector poly_normals; mutable Vector corner_normals; -- 2.30.2 From 29134a0b6f48a2a00dffc746a025712c7b6787c1 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 10 May 2023 22:03:49 -0400 Subject: [PATCH 16/85] Fix deadlock --- source/blender/blenkernel/intern/mesh_normals.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index adb3df911df..a7231dd4631 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -484,6 +484,8 @@ blender::Span Mesh::corner_normals() const return this->runtime->corner_normals; } + const Span vert_normals = this->vert_normals(); + const Span poly_normals = this->poly_normals(); std::lock_guard lock{this->runtime->normals_mutex}; if (!this->runtime->corner_normals_dirty) { BLI_assert(this->runtime->corner_normals.size() == this->totloop); @@ -497,11 +499,10 @@ blender::Span Mesh::corner_normals() const MutableSpan corner_normals = this->runtime->corner_normals; switch (this->normal_domain_all_info()) { case ATTR_DOMAIN_POINT: { - array_utils::gather(this->vert_normals(), this->corner_verts(), corner_normals); + array_utils::gather(vert_normals, this->corner_verts(), corner_normals); break; } case ATTR_DOMAIN_FACE: { - const Span poly_normals = this->poly_normals(); threading::parallel_for(poly_normals.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { corner_normals.slice(polys[i]).fill(poly_normals[i]); @@ -524,8 +525,8 @@ blender::Span Mesh::corner_normals() const this->corner_verts(), this->corner_edges(), {}, - this->vert_normals(), - this->poly_normals(), + vert_normals, + poly_normals, sharp_edges, sharp_faces, custom_normals, -- 2.30.2 From b6241154e2bd60870cb44210201b859949d04ee5 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 May 2023 11:45:00 -0400 Subject: [PATCH 17/85] Tag normals dirty --- .../blenkernel/intern/geometry_component_mesh.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 3a2cbe755cf..d546ad487fb 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -871,6 +871,14 @@ static void tag_component_positions_changed(void *owner) } } +static void tag_component_corner_normals_dirty(void *owner) +{ + Mesh *mesh = static_cast(owner); + if (mesh != nullptr) { + mesh->runtime->corner_normals_dirty = true; + } +} + class VArrayImpl_For_VertexWeights final : public VMutableArrayImpl { private: MDeformVert *dverts_; @@ -1195,7 +1203,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() BuiltinAttributeProvider::Creatable, BuiltinAttributeProvider::Deletable, face_access, - nullptr); + tag_component_corner_normals_dirty); static BuiltinCustomDataLayerProvider sharp_edge("sharp_edge", ATTR_DOMAIN_EDGE, @@ -1204,7 +1212,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() BuiltinAttributeProvider::Creatable, BuiltinAttributeProvider::Deletable, edge_access, - nullptr); + tag_component_corner_normals_dirty); static const auto crease_clamp = mf::build::SI1_SO( "Crease Clamp", -- 2.30.2 From 5cb1a45bb5606f036d00933e12d9ee44cda630f5 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 May 2023 12:19:15 -0400 Subject: [PATCH 18/85] Progress with versioning --- source/blender/blenloader/intern/readfile.cc | 3 ++ source/blender/blenloader/intern/readfile.h | 1 + .../blenloader/intern/versioning_400.cc | 53 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 1d5e83559dd..308ff7e8fe3 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -3566,6 +3566,9 @@ static void do_versions_after_linking(FileData *fd, Main *main) if (!main->is_read_invalid) { do_versions_after_linking_300(fd, main); } + if (!main->is_read_invalid) { + do_versions_after_linking_400(fd, main); + } if (!main->is_read_invalid) { do_versions_after_linking_cycles(main); } diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 915917afe14..d8c3176b0e5 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -232,6 +232,7 @@ void do_versions_after_linking_270(struct Main *bmain); void do_versions_after_linking_280(struct FileData *fd, struct Main *bmain); void do_versions_after_linking_290(struct FileData *fd, struct Main *bmain); void do_versions_after_linking_300(struct FileData *fd, struct Main *bmain); +void do_versions_after_linking_400(struct FileData *fd, struct Main *bmain); void do_versions_after_linking_cycles(struct Main *bmain); /** diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 1fc1e0146ff..ce1a05dfd81 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -8,6 +8,7 @@ #include "CLG_log.h" +#include "DNA_mesh_types.h" #include "DNA_movieclip_types.h" #include "BLI_assert.h" @@ -15,16 +16,68 @@ #include "BKE_main.h" #include "BKE_mesh_legacy_convert.h" +#include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_tracking.h" #include "BLO_readfile.h" +#include "BLT_translation.h" + #include "readfile.h" #include "versioning_common.h" // static CLG_LogRef LOG = {"blo.readfile.doversion"}; +static bNodeTree *add_realize_node_tree(Main &bmain) +{ + bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth 4.0 Legacy"), "GeometryNodeTree"); + + ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", "Geometry"); + ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketFloatAngle", "Angle"); + ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", "Geometry"); + + bNode *group_input = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_INPUT); + group_input->locx = -400.0f; + bNode *group_output = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_OUTPUT); + group_output->locx = 500.0f; + group_output->flag |= NODE_DO_OUTPUT; + + bNode *shade_smooth = nodeAddNode(nullptr, node_tree, "GeometryNodeSetShadeSmooth"); + + bNode *store_node = nodeAddNode(nullptr, node_tree, "GeometryNodeStoreNamedAttribute"); + static_cast(store_node->storage)->data_type = CD_PROP_BOOL; + static_cast(store_node->storage)->domain = ATTR_DOMAIN_EDGE; + bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); + STRNCPY(name->default_value_typed()->value, "sharp_face"); + + bNode *greater_node = nodeAddNode(nullptr, node_tree, "FunctionNodeCompare"); + static_cast(store_node->storage)->operation = NODE_COMPARE_GREATER_THAN; + static_cast(store_node->storage)->data_type = CD_PROP_FLOAT; +} + +void do_versions_after_linking_400(FileData * /*fd*/, Main *bmain) +{ + bNodeTree *auto_smooth_node_tree = nullptr; + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + if (object->type == OB_MESH) { + Mesh *mesh = static_cast(object->data); + if (mesh->flag & ME_AUTOSMOOTH) { + if (!auto_smooth_node_tree) { + auto_smooth_node_tree = add_realize_node_tree(*bmain); + } + auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); + STRNCPY(md->modifier.name, DATA_("Auto Smooth 4.0 Legacy")); + BKE_modifier_unique_name(&object->modifiers, &md->modifier); + md->node_group = auto_smooth_node_tree; + + BLI_addtail(&object->modifiers, md); + } + } + } +} + static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh) { BKE_mesh_legacy_convert_flags_to_selection_layers(&mesh); -- 2.30.2 From fd92da5515a6e56f5103a0657196c19e616dc549 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 May 2023 16:07:02 -0400 Subject: [PATCH 19/85] Versioning node group --- .../blenloader/intern/versioning_400.cc | 64 ++++++++++++++++--- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index ce1a05dfd81..42859ab1d29 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -14,6 +14,7 @@ #include "BLI_assert.h" #include "BLI_listbase.h" +#include "BKE_idprop.hh" #include "BKE_main.h" #include "BKE_mesh_legacy_convert.h" #include "BKE_modifier.h" @@ -34,9 +35,9 @@ static bNodeTree *add_realize_node_tree(Main &bmain) { bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth 4.0 Legacy"), "GeometryNodeTree"); - ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", "Geometry"); - ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketFloatAngle", "Angle"); - ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", "Geometry"); + ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", DATA_("Geometry")); + ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketFloatAngle", DATA_("Angle")); + ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", DATA_("Geometry")); bNode *group_input = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_INPUT); group_input->locx = -400.0f; @@ -50,34 +51,77 @@ static bNodeTree *add_realize_node_tree(Main &bmain) static_cast(store_node->storage)->data_type = CD_PROP_BOOL; static_cast(store_node->storage)->domain = ATTR_DOMAIN_EDGE; bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); - STRNCPY(name->default_value_typed()->value, "sharp_face"); + STRNCPY(name->default_value_typed()->value, "sharp_edge"); bNode *greater_node = nodeAddNode(nullptr, node_tree, "FunctionNodeCompare"); - static_cast(store_node->storage)->operation = NODE_COMPARE_GREATER_THAN; - static_cast(store_node->storage)->data_type = CD_PROP_FLOAT; + static_cast(greater_node->storage)->operation = NODE_COMPARE_GREATER_THAN; + static_cast(greater_node->storage)->data_type = SOCK_FLOAT; + + bNode *edge_angle_node = nodeAddNode(nullptr, node_tree, "GeometryNodeInputMeshEdgeAngle"); + + nodeAddLink(node_tree, + group_input, + static_cast(group_input->outputs.first), + shade_smooth, + nodeFindSocket(shade_smooth, SOCK_IN, "Geometry")); + nodeAddLink(node_tree, + shade_smooth, + nodeFindSocket(shade_smooth, SOCK_OUT, "Geometry"), + store_node, + nodeFindSocket(store_node, SOCK_IN, "Geometry")); + nodeAddLink(node_tree, + edge_angle_node, + nodeFindSocket(edge_angle_node, SOCK_OUT, "Unsigned Angle"), + greater_node, + nodeFindSocket(greater_node, SOCK_IN, "A")); + nodeAddLink(node_tree, + group_input, + static_cast(BLI_findlink(&group_input->outputs, 1)), + greater_node, + nodeFindSocket(greater_node, SOCK_IN, "B")); + nodeAddLink(node_tree, + greater_node, + nodeFindSocket(greater_node, SOCK_OUT, "Result"), + store_node, + nodeFindSocket(store_node, SOCK_IN, "Value_Bool")); + nodeAddLink(node_tree, + store_node, + nodeFindSocket(store_node, SOCK_OUT, "Geometry"), + group_output, + static_cast(group_output->inputs.first)); + return node_tree; } -void do_versions_after_linking_400(FileData * /*fd*/, Main *bmain) +static void version_mesh_objects_replace_auto_smooth(Main &bmain) { + using namespace blender; bNodeTree *auto_smooth_node_tree = nullptr; - LISTBASE_FOREACH (Object *, object, &bmain->objects) { + LISTBASE_FOREACH (Object *, object, &bmain.objects) { if (object->type == OB_MESH) { Mesh *mesh = static_cast(object->data); if (mesh->flag & ME_AUTOSMOOTH) { if (!auto_smooth_node_tree) { - auto_smooth_node_tree = add_realize_node_tree(*bmain); + auto_smooth_node_tree = add_realize_node_tree(bmain); } auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); STRNCPY(md->modifier.name, DATA_("Auto Smooth 4.0 Legacy")); BKE_modifier_unique_name(&object->modifiers, &md->modifier); md->node_group = auto_smooth_node_tree; - BLI_addtail(&object->modifiers, md); + + md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); + IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); + IDP_AddToGroup(md->settings.properties, angle_prop); } } } } +void do_versions_after_linking_400(FileData * /*fd*/, Main *bmain) +{ + version_mesh_objects_replace_auto_smooth(*bmain); +} + static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh) { BKE_mesh_legacy_convert_flags_to_selection_layers(&mesh); -- 2.30.2 From a38672e385dab83b4cc71615180bc45cdb2d393e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 May 2023 16:21:11 -0400 Subject: [PATCH 20/85] Place nodes in new node group properly --- .../blender/blenloader/intern/versioning_400.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 42859ab1d29..91ddfe2276f 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -33,31 +33,39 @@ static bNodeTree *add_realize_node_tree(Main &bmain) { - bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth 4.0 Legacy"), "GeometryNodeTree"); + bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth"), "GeometryNodeTree"); ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", DATA_("Geometry")); ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketFloatAngle", DATA_("Angle")); ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", DATA_("Geometry")); bNode *group_input = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_INPUT); - group_input->locx = -400.0f; + group_input->locx = -380.0f; bNode *group_output = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_OUTPUT); - group_output->locx = 500.0f; + group_output->locx = 260.0f; group_output->flag |= NODE_DO_OUTPUT; bNode *shade_smooth = nodeAddNode(nullptr, node_tree, "GeometryNodeSetShadeSmooth"); + shade_smooth->locx = -160.0f; + shade_smooth->locy = 40.0f; bNode *store_node = nodeAddNode(nullptr, node_tree, "GeometryNodeStoreNamedAttribute"); + store_node->locx = 40.0f; + store_node->locy = 40.0f; static_cast(store_node->storage)->data_type = CD_PROP_BOOL; static_cast(store_node->storage)->domain = ATTR_DOMAIN_EDGE; bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); STRNCPY(name->default_value_typed()->value, "sharp_edge"); bNode *greater_node = nodeAddNode(nullptr, node_tree, "FunctionNodeCompare"); + greater_node->locx = -160.0f; + greater_node->locy = -100.0f; static_cast(greater_node->storage)->operation = NODE_COMPARE_GREATER_THAN; static_cast(greater_node->storage)->data_type = SOCK_FLOAT; bNode *edge_angle_node = nodeAddNode(nullptr, node_tree, "GeometryNodeInputMeshEdgeAngle"); + edge_angle_node->locx = -380.0f; + edge_angle_node->locy = -180.0f; nodeAddLink(node_tree, group_input, @@ -104,7 +112,7 @@ static void version_mesh_objects_replace_auto_smooth(Main &bmain) auto_smooth_node_tree = add_realize_node_tree(bmain); } auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); - STRNCPY(md->modifier.name, DATA_("Auto Smooth 4.0 Legacy")); + STRNCPY(md->modifier.name, DATA_("Auto Smooth")); BKE_modifier_unique_name(&object->modifiers, &md->modifier); md->node_group = auto_smooth_node_tree; BLI_addtail(&object->modifiers, md); -- 2.30.2 From ca331b969bc0c3d73a6e6f669b6a46d54ed0eb6d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 May 2023 16:29:11 -0400 Subject: [PATCH 21/85] Move bool array mix calc to array utils header --- .../blender/blenkernel/intern/mesh_normals.cc | 80 ++----------------- source/blender/blenlib/BLI_array_utils.hh | 11 +++ source/blender/blenlib/intern/array_utils.cc | 51 ++++++++++++ 3 files changed, 69 insertions(+), 73 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index a7231dd4631..fbe3761ae6a 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -301,74 +301,6 @@ void normals_calc_poly_vert(const Span positions, /** \name Mesh Normal Calculation * \{ */ -namespace blender::bke { - -enum class BoolArrayMix { - None, - AllFalse, - AllTrue, - Mixed, -}; -static BoolArrayMix bool_array_mix_calc(const VArray &varray, - const blender::IndexRange range_to_check) -{ - using namespace blender; - if (varray.is_empty()) { - return BoolArrayMix::None; - } - const CommonVArrayInfo info = varray.common_info(); - if (info.type == CommonVArrayInfo::Type::Single) { - return *static_cast(info.data) ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; - } - if (info.type == CommonVArrayInfo::Type::Span) { - const Span span(static_cast(info.data), varray.size()); - return threading::parallel_reduce( - range_to_check, - 4096, - BoolArrayMix::None, - [&](const IndexRange range, const BoolArrayMix init) { - if (init == BoolArrayMix::Mixed) { - return init; - } - - const Span slice = span.slice(range); - const bool first = slice.first(); - for (const bool value : slice.drop_front(1)) { - if (value != first) { - return BoolArrayMix::Mixed; - } - } - return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; - }, - [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); - } - return threading::parallel_reduce( - range_to_check, - 2048, - BoolArrayMix::None, - [&](const IndexRange range, const BoolArrayMix init) { - if (init == BoolArrayMix::Mixed) { - return init; - } - /* Alternatively, this could use #materialize to retrieve many values at once. */ - const bool first = varray[range.first()]; - for (const int64_t i : range.drop_front(1)) { - if (varray[i] != first) { - return BoolArrayMix::Mixed; - } - } - return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; - }, - [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); -} - -static BoolArrayMix bool_array_mix_calc(const VArray &varray) -{ - return bool_array_mix_calc(varray, varray.index_range()); -} - -} // namespace blender::bke - eAttrDomain Mesh::normal_domain_all_info() const { using namespace blender; @@ -385,19 +317,21 @@ eAttrDomain Mesh::normal_domain_all_info() const const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); - const BoolArrayMix face_mix = bool_array_mix_calc(sharp_faces); - if (face_mix == BoolArrayMix::AllTrue) { + const array_utils::BoolArrayMix face_mix = array_utils::bool_array_mix_calc(sharp_faces); + if (face_mix == array_utils::BoolArrayMix::AllTrue) { return ATTR_DOMAIN_FACE; } const VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const BoolArrayMix edge_mix = bool_array_mix_calc(sharp_edges); - if (edge_mix == BoolArrayMix::AllTrue) { + const array_utils::BoolArrayMix edge_mix = array_utils::bool_array_mix_calc(sharp_edges); + if (edge_mix == array_utils::BoolArrayMix::AllTrue) { return ATTR_DOMAIN_FACE; } - if (edge_mix == BoolArrayMix::AllFalse && face_mix == BoolArrayMix::AllFalse) { + if (edge_mix == array_utils::BoolArrayMix::AllFalse && + face_mix == array_utils::BoolArrayMix::AllFalse) + { return ATTR_DOMAIN_POINT; } diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index 883ad1c1bf0..aea493124b3 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -140,5 +140,16 @@ inline void gather(const VArray &src, } void invert_booleans(MutableSpan span); +enum class BoolArrayMix { + None, + AllFalse, + AllTrue, + Mixed, +}; +BoolArrayMix bool_array_mix_calc(const VArray &varray, const IndexRange range_to_check); +inline BoolArrayMix bool_array_mix_calc(const VArray &varray) +{ + return bool_array_mix_calc(varray, varray.index_range()); +} } // namespace blender::array_utils diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc index 4abf9ce5e34..69ce30d1306 100644 --- a/source/blender/blenlib/intern/array_utils.cc +++ b/source/blender/blenlib/intern/array_utils.cc @@ -52,4 +52,55 @@ void invert_booleans(MutableSpan span) }); } +BoolArrayMix bool_array_mix_calc(const VArray &varray, const IndexRange range_to_check) +{ + if (varray.is_empty()) { + return BoolArrayMix::None; + } + const CommonVArrayInfo info = varray.common_info(); + if (info.type == CommonVArrayInfo::Type::Single) { + return *static_cast(info.data) ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + } + if (info.type == CommonVArrayInfo::Type::Span) { + const Span span(static_cast(info.data), varray.size()); + return threading::parallel_reduce( + range_to_check, + 4096, + BoolArrayMix::None, + [&](const IndexRange range, const BoolArrayMix init) { + if (init == BoolArrayMix::Mixed) { + return init; + } + + const Span slice = span.slice(range); + const bool first = slice.first(); + for (const bool value : slice.drop_front(1)) { + if (value != first) { + return BoolArrayMix::Mixed; + } + } + return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + }, + [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); + } + return threading::parallel_reduce( + range_to_check, + 2048, + BoolArrayMix::None, + [&](const IndexRange range, const BoolArrayMix init) { + if (init == BoolArrayMix::Mixed) { + return init; + } + /* Alternatively, this could use #materialize to retrieve many values at once. */ + const bool first = varray[range.first()]; + for (const int64_t i : range.drop_front(1)) { + if (varray[i] != first) { + return BoolArrayMix::Mixed; + } + } + return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + }, + [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); +} + } // namespace blender::array_utils -- 2.30.2 From c055bfe93edcf64e4d3458987aa7ead395ad2aaf Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 May 2023 16:36:22 -0400 Subject: [PATCH 22/85] Probably fix mesh subdivision --- source/blender/blenkernel/intern/mesh_wrapper.cc | 9 +++++++-- source/blender/modifiers/intern/MOD_subsurf.cc | 13 ++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index 1f927934533..b32549166c9 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -332,6 +332,10 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me) if (use_clnors) { /* If custom normals are present and the option is turned on calculate the split * normals and clear flag so the normals get interpolated to the result mesh. */ + blender::MutableSpan data(static_cast(CustomData_add_layer( + &me->ldata, CD_NORMAL, CD_CONSTRUCT, me->totloop)), + me->totloop); + data.copy_from(me->corner_normals()); CustomData_clear_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } @@ -339,8 +343,9 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me) if (use_clnors) { BKE_mesh_set_custom_normals(subdiv_mesh, - const_cast(reinterpret_cast( - subdiv_mesh->corner_normals().data()))); + static_cast(CustomData_get_layer_for_write( + &subdiv_mesh->ldata, CD_NORMAL, me->totloop))); + CustomData_free_layers(&subdiv_mesh->ldata, CD_NORMAL, me->totloop); } if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) { diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index b49ea8105c0..1851d235f88 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -261,8 +261,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh); if (use_clnors) { - void *data = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop); - memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes()); + blender::MutableSpan data( + static_cast( + CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop)), + mesh->totloop); + data.copy_from(mesh->corner_normals()); } /* TODO(sergey): Decide whether we ever want to use CCG for subsurf, * maybe when it is a last modifier in the stack? */ @@ -274,9 +277,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } if (use_clnors) { - float(*lnors)[3] = static_cast( - CustomData_get_layer_for_write(&result->ldata, CD_NORMAL, result->totloop)); - BKE_mesh_set_custom_normals(result, lnors); + BKE_mesh_set_custom_normals(result, + static_cast(CustomData_get_layer_for_write( + &result->ldata, CD_NORMAL, result->totloop))); CustomData_free_layers(&result->ldata, CD_NORMAL, result->totloop); } // BKE_subdiv_stats_print(&subdiv->stats); -- 2.30.2 From 237e209c5b8ddd7927e6674801aee5dac69669ff Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 May 2023 10:05:33 -0400 Subject: [PATCH 23/85] Cleanup: Remove const in header --- source/blender/blenkernel/BKE_mesh_sample.hh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh index e52e214ecad..17e4ba0d83d 100644 --- a/source/blender/blenkernel/BKE_mesh_sample.hh +++ b/source/blender/blenkernel/BKE_mesh_sample.hh @@ -35,13 +35,13 @@ void sample_point_attribute(Span corner_verts, IndexMask mask, GMutableSpan dst); -void sample_point_normals(const Span corner_verts, - const Span looptris, - const Span looptri_indices, - const Span bary_coords, - const Span src, - const IndexMask mask, - const MutableSpan dst); +void sample_point_normals(Span corner_verts, + Span looptris, + Span looptri_indices, + Span bary_coords, + Span src, + IndexMask mask, + MutableSpan dst); void sample_corner_attribute(Span looptris, Span looptri_indices, -- 2.30.2 From 7a9a4b98d368dcdb17ca144d0b92a2744a10bc68 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 May 2023 10:05:50 -0400 Subject: [PATCH 24/85] Better consistency in manual normal propagation --- source/blender/blenkernel/intern/mesh_wrapper.cc | 7 ++----- source/blender/modifiers/intern/MOD_subsurf.cc | 7 ++----- source/blender/modifiers/intern/MOD_triangulate.cc | 1 + 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index b32549166c9..a8f28b949d0 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -332,11 +332,8 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me) if (use_clnors) { /* If custom normals are present and the option is turned on calculate the split * normals and clear flag so the normals get interpolated to the result mesh. */ - blender::MutableSpan data(static_cast(CustomData_add_layer( - &me->ldata, CD_NORMAL, CD_CONSTRUCT, me->totloop)), - me->totloop); - data.copy_from(me->corner_normals()); - CustomData_clear_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); + void *data = CustomData_add_layer(&me->ldata, CD_NORMAL, CD_CONSTRUCT, me->totloop); + memcpy(data, me->corner_normals().data(), me->corner_normals().size_in_bytes()); } Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me); diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index 1851d235f88..3f448d2ace9 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -261,11 +261,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh); if (use_clnors) { - blender::MutableSpan data( - static_cast( - CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop)), - mesh->totloop); - data.copy_from(mesh->corner_normals()); + void *data = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop); + memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes()); } /* TODO(sergey): Decide whether we ever want to use CCG for subsurf, * maybe when it is a last modifier in the stack? */ diff --git a/source/blender/modifiers/intern/MOD_triangulate.cc b/source/blender/modifiers/intern/MOD_triangulate.cc index 17bc5242de8..a81b775a0b4 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.cc +++ b/source/blender/modifiers/intern/MOD_triangulate.cc @@ -53,6 +53,7 @@ static Mesh *triangulate_mesh(Mesh *mesh, if (keep_clnors) { void *data = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CONSTRUCT, mesh->totloop); memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes()); + cd_mask_extra.lmask |= CD_MASK_NORMAL; } BMeshCreateParams bmesh_create_params{}; -- 2.30.2 From 025045945629895dc0317aca5e4539530721ca0d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 May 2023 10:06:07 -0400 Subject: [PATCH 25/85] Skip versioning node group in some cases --- .../blenloader/intern/versioning_400.cc | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 91ddfe2276f..d84fd665675 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -19,6 +19,7 @@ #include "BKE_mesh_legacy_convert.h" #include "BKE_modifier.h" #include "BKE_node.h" +#include "BKE_node_runtime.hh" #include "BKE_tracking.h" #include "BLO_readfile.h" @@ -105,23 +106,28 @@ static void version_mesh_objects_replace_auto_smooth(Main &bmain) using namespace blender; bNodeTree *auto_smooth_node_tree = nullptr; LISTBASE_FOREACH (Object *, object, &bmain.objects) { - if (object->type == OB_MESH) { - Mesh *mesh = static_cast(object->data); - if (mesh->flag & ME_AUTOSMOOTH) { - if (!auto_smooth_node_tree) { - auto_smooth_node_tree = add_realize_node_tree(bmain); - } - auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); - STRNCPY(md->modifier.name, DATA_("Auto Smooth")); - BKE_modifier_unique_name(&object->modifiers, &md->modifier); - md->node_group = auto_smooth_node_tree; - BLI_addtail(&object->modifiers, md); - - md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); - IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); - IDP_AddToGroup(md->settings.properties, angle_prop); - } + if (object->type != OB_MESH) { + continue; } + Mesh *mesh = static_cast(object->data); + if (!(mesh->flag & ME_AUTOSMOOTH)) { + continue; + } + if (CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)) { + continue; + } + if (!auto_smooth_node_tree) { + auto_smooth_node_tree = add_realize_node_tree(bmain); + } + auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); + STRNCPY(md->modifier.name, DATA_("Auto Smooth")); + BKE_modifier_unique_name(&object->modifiers, &md->modifier); + md->node_group = auto_smooth_node_tree; + BLI_addtail(&object->modifiers, md); + + md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); + IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); + IDP_AddToGroup(md->settings.properties, angle_prop); } } -- 2.30.2 From 19b44869fa05bf5c92446ae46b3a3db53b28a0fa Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 May 2023 10:31:15 -0400 Subject: [PATCH 26/85] Add some more stuff to versioning node group --- source/blender/blenloader/intern/versioning_400.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index d84fd665675..223d70a8452 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -20,6 +20,7 @@ #include "BKE_modifier.h" #include "BKE_node.h" #include "BKE_node_runtime.hh" +#include "BKE_node_tree_update.h" #include "BKE_tracking.h" #include "BLO_readfile.h" @@ -98,6 +99,13 @@ static bNodeTree *add_realize_node_tree(Main &bmain) nodeFindSocket(store_node, SOCK_OUT, "Geometry"), group_output, static_cast(group_output->inputs.first)); + + LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { + nodeSetSelected(node, false); + } + + version_socket_update_is_used(node_tree); + return node_tree; } -- 2.30.2 From 9a42de4967f66f3604104a2f1011eebe4fc275e0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 May 2023 16:38:17 -0400 Subject: [PATCH 27/85] Add normals panel back, but just with custom normals button --- scripts/startup/bl_ui/properties_data_mesh.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/scripts/startup/bl_ui/properties_data_mesh.py b/scripts/startup/bl_ui/properties_data_mesh.py index 5f941e566c5..506536f725c 100644 --- a/scripts/startup/bl_ui/properties_data_mesh.py +++ b/scripts/startup/bl_ui/properties_data_mesh.py @@ -186,6 +186,23 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel): layout.template_ID(space, "pin_id") +class DATA_PT_normals(MeshButtonsPanel, Panel): + bl_label = "Normals" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + mesh = context.mesh + + if mesh.has_custom_normals: + col.operator("mesh.customdata_custom_splitnormals_clear", icon='X') + else: + col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') + + class DATA_PT_texture_space(MeshButtonsPanel, Panel): bl_label = "Texture Space" bl_options = {'DEFAULT_CLOSED'} @@ -469,11 +486,6 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel): col.operator("mesh.customdata_mask_clear", icon='X') col.operator("mesh.customdata_skin_clear", icon='X') - if me.has_custom_normals: - col.operator("mesh.customdata_custom_splitnormals_clear", icon='X') - else: - col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') - if me.has_bevel_weight_edge: col.operator("mesh.customdata_bevel_weight_edge_clear", icon='X') else: @@ -716,6 +728,7 @@ classes = ( DATA_PT_vertex_colors, DATA_PT_face_maps, DATA_PT_mesh_attributes, + DATA_PT_normals, DATA_PT_texture_space, DATA_PT_remesh, DATA_PT_customdata, -- 2.30.2 From 09ec47a9737e7e976373313ce68781982cbcfcbf Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 May 2023 17:09:20 -0400 Subject: [PATCH 28/85] Cleanup: Make diff smaller --- .../draw_cache_extract_mesh_render_data.cc | 7 +++--- .../intern/mesh_extractors/extract_mesh.hh | 2 +- .../mesh_extractors/extract_mesh_vbo_lnor.cc | 17 +++++++------- .../mesh_extractors/extract_mesh_vbo_tan.cc | 23 +++++++++---------- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index e5d4e35b57b..86ed1aaded2 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -332,8 +332,9 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ } if (((data_flag & MR_DATA_LOOP_NOR) && mr->me->normal_domain_all_info() == ATTR_DOMAIN_CORNER) || - (data_flag & MR_DATA_TAN_LOOP_NOR)) { - mr->corner_normals = mr->me->corner_normals(); + (data_flag & MR_DATA_TAN_LOOP_NOR)) + { + mr->loop_normals = mr->me->corner_normals(); } } else { @@ -365,7 +366,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ nullptr, clnors_offset, false); - mr->corner_normals = mr->bm_loop_normals; + mr->loop_normals = mr->bm_loop_normals; } } } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index affdb3b6df2..604ac553866 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -91,7 +91,7 @@ struct MeshRenderData { const int *material_indices; blender::Span vert_normals; blender::Span poly_normals; - blender::Span corner_normals; + blender::Span loop_normals; const bool *hide_vert; const bool *hide_edge; const bool *hide_poly; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index 5e004ea3b1b..5dbfde46ee1 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -41,9 +41,8 @@ static void extract_lnor_iter_poly_bm(const MeshRenderData *mr, l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - if (!mr->corner_normals.is_empty()) { - (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3( - mr->corner_normals[l_index]); + if (!mr->loop_normals.is_empty()) { + (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); } else { if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { @@ -65,8 +64,8 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr, const int poly for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; - if (!mr->corner_normals.is_empty()) { - *lnor_data = GPU_normal_convert_i10_v3(mr->corner_normals[ml_index]); + if (!mr->loop_normals.is_empty()) { + *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); } else if (mr->sharp_faces && mr->sharp_faces[poly_index]) { *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[poly_index]); @@ -164,8 +163,8 @@ static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr, l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { const int l_index = BM_elem_index_get(l_iter); - if (!mr->corner_normals.is_empty()) { - normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->corner_normals[l_index]); + if (!mr->loop_normals.is_empty()) { + normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]); } else { if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) { @@ -187,8 +186,8 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr, for (const int ml_index : mr->polys[poly_index]) { const int vert = mr->corner_verts[ml_index]; gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; - if (!mr->corner_normals.is_empty()) { - normal_float_to_short_v3(&lnor_data->x, mr->corner_normals[ml_index]); + if (!mr->loop_normals.is_empty()) { + normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); } else if (mr->sharp_faces && mr->sharp_faces[poly_index]) { normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[poly_index]); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc index 639483aaac1..274bbb8db36 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc @@ -102,17 +102,16 @@ static void extract_tan_init_common(const MeshRenderData *mr, short tangent_mask = 0; bool calc_active_tangent = false; if (mr->extract_type == MR_EXTRACT_BMESH) { - BKE_editmesh_loop_tangent_calc( - mr->edit_bmesh, - calc_active_tangent, - r_tangent_names, - tan_len, - reinterpret_cast(mr->poly_normals.data()), - reinterpret_cast(mr->corner_normals.data()), - orco, - r_loop_data, - mr->loop_len, - &tangent_mask); + BKE_editmesh_loop_tangent_calc(mr->edit_bmesh, + calc_active_tangent, + r_tangent_names, + tan_len, + reinterpret_cast(mr->poly_normals.data()), + reinterpret_cast(mr->loop_normals.data()), + orco, + r_loop_data, + mr->loop_len, + &tangent_mask); } else { BKE_mesh_calc_loop_tangent_ex(reinterpret_cast(mr->vert_positions.data()), @@ -128,7 +127,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, tan_len, reinterpret_cast(mr->vert_normals.data()), reinterpret_cast(mr->poly_normals.data()), - reinterpret_cast(mr->corner_normals.data()), + reinterpret_cast(mr->loop_normals.data()), orco, r_loop_data, mr->corner_verts.size(), -- 2.30.2 From c34b92f6d17eadb17e9f24d18adb4031a97657f8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 17 May 2023 18:53:46 -0400 Subject: [PATCH 29/85] A few fixes --- scripts/startup/bl_ui/properties_data_mesh.py | 4 ++-- source/blender/blenloader/intern/versioning_400.cc | 12 +++++++++++- source/blender/editors/mesh/mesh_data.cc | 1 + source/blender/makesrna/intern/rna_mesh.c | 3 +-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/scripts/startup/bl_ui/properties_data_mesh.py b/scripts/startup/bl_ui/properties_data_mesh.py index 506536f725c..99a825f9879 100644 --- a/scripts/startup/bl_ui/properties_data_mesh.py +++ b/scripts/startup/bl_ui/properties_data_mesh.py @@ -198,9 +198,9 @@ class DATA_PT_normals(MeshButtonsPanel, Panel): mesh = context.mesh if mesh.has_custom_normals: - col.operator("mesh.customdata_custom_splitnormals_clear", icon='X') + layout.operator("mesh.customdata_custom_splitnormals_clear", icon='X') else: - col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') + layout.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') class DATA_PT_texture_space(MeshButtonsPanel, Panel): diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index c03a65f34a4..0437d14bdf0 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -131,7 +131,17 @@ static void version_mesh_objects_replace_auto_smooth(Main &bmain) STRNCPY(md->modifier.name, DATA_("Auto Smooth")); BKE_modifier_unique_name(&object->modifiers, &md->modifier); md->node_group = auto_smooth_node_tree; - BLI_addtail(&object->modifiers, md); + if (!BLI_listbase_is_empty(&object->modifiers) && + static_cast(object->modifiers.last)->type == eModifierType_Subsurf) + { + /* Add the auto smooth node group before the last subdivision surface modifier if possible. + * Subdivision surface modifiers have special handling for interpolating face corner normals, + * and recalculating them afterwards isn't usually helpful and can be much slower. */ + BLI_insertlinkbefore(&object->modifiers, object->modifiers.last, md); + } + else { + BLI_addtail(&object->modifiers, md); + } md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 1f77d61e7b4..51ca6a80d16 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -749,6 +749,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator } else { CustomData_add_layer(&me->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me->totloop); + me->runtime->corner_normals_dirty = true; } DEG_id_tag_update(&me->id, 0); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index cf545105e19..ae173f02669 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2451,8 +2451,7 @@ static void rna_def_mlooptri(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Split Normals", - "Local space unit length split normals vectors of the vertices of this triangle " - "(must be computed beforehand using calc_normals_split or calc_tangents)"); + "Local space unit length split normal vectors of the face corners of this triangle"); prop = RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); -- 2.30.2 From fb2433804fdce96cd77972840c1b8f64b240bfea Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 18 May 2023 09:42:56 -0400 Subject: [PATCH 30/85] Also adjust sharp edge attribute in shade smooth/flat operator --- source/blender/blenkernel/intern/mesh.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 27489be7323..61c3c0a7f98 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1483,9 +1483,11 @@ void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth) using namespace blender::bke; MutableAttributeAccessor attributes = me->attributes_for_write(); if (use_smooth) { + attributes.remove("sharp_edge"); attributes.remove("sharp_face"); } else { + attributes.remove("sharp_edge"); SpanAttributeWriter sharp_faces = attributes.lookup_or_add_for_write_only_span( "sharp_face", ATTR_DOMAIN_FACE); sharp_faces.span.fill(true); @@ -1498,6 +1500,15 @@ void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle) using namespace blender; using namespace blender::bke; bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + if (angle >= M_PI) { + attributes.remove("sharp_edge"); + attributes.remove("sharp_face"); + return; + } + if (angle == 0.0f) { + BKE_mesh_smooth_flag_set(me, false); + return; + } bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); const VArray sharp_faces = *attributes.lookup_or_default( -- 2.30.2 From 1f204b4b84627283fd196952c1d8749035443004 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 18 May 2023 09:43:26 -0400 Subject: [PATCH 31/85] Add mesh API function tp set sharp edges from angle --- source/blender/editors/include/ED_mesh.h | 5 +++++ source/blender/editors/mesh/mesh_data.cc | 8 ++++++++ source/blender/makesrna/intern/rna_mesh_api.c | 7 ++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 32e5487b7d4..07f2684eb65 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -602,6 +602,11 @@ struct Mesh *ED_mesh_context(struct bContext *C); */ void ED_mesh_split_faces(struct Mesh *mesh); +/** + * Reset and fill the "sharp_edge" attribute based on the angle of manifold edges. + */ +void ED_mesh_sharp_from_angle_set(struct Mesh *mesh, float angle); + /* mesh backup */ typedef struct BMBackup { struct BMesh *bmcopy; diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 51ca6a80d16..529bc8171e8 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1447,3 +1447,11 @@ void ED_mesh_split_faces(Mesh *mesh) geometry::split_edges(*mesh, split_mask, {}); } + +void ED_mesh_sharp_from_angle_set(Mesh *mesh, const float angle) +{ + mesh->attributes_for_write().remove("sharp_edge"); + mesh->attributes_for_write().remove("sharp_face"); + BKE_mesh_sharp_edges_set_from_angle(mesh, angle); + DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY); +} diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 97dbdabbf5c..4ae21f83e8a 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -12,8 +12,8 @@ #include "DNA_customdata_types.h" +#include "BLI_math_base.h" #include "BLI_sys_types.h" - #include "BLI_utildefines.h" #include "rna_internal.h" /* own include */ @@ -215,6 +215,11 @@ void RNA_api_mesh(StructRNA *srna) RNA_def_function_ui_description( func, "Deprecated. Has no effect. Normals are calculated upon retrieval"); + func = RNA_def_function(srna, "set_sharp_from_angle", "ED_mesh_sharp_from_angle_set"); + RNA_def_function_ui_description( + func, "Set the sharp edge status for edges based on the angle of incident faces"); + RNA_def_float(func, "angle", M_PI, 0.0f, M_PI, "Angle", "", 0.0f, M_PI); + func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces"); RNA_def_function_ui_description(func, "Split faces based on the edge angle"); /* TODO: This parameter has no effect anymore, since the internal code does not need to -- 2.30.2 From 772c14d1156e96acbe0b46aa6102b3c9dd59d51f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 23 May 2023 19:24:22 -0400 Subject: [PATCH 32/85] Cleanup --- source/blender/blenlib/BLI_array_utils.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index aea493124b3..4ca964dee3c 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -146,7 +146,7 @@ enum class BoolArrayMix { AllTrue, Mixed, }; -BoolArrayMix bool_array_mix_calc(const VArray &varray, const IndexRange range_to_check); +BoolArrayMix bool_array_mix_calc(const VArray &varray, IndexRange range_to_check); inline BoolArrayMix bool_array_mix_calc(const VArray &varray) { return bool_array_mix_calc(varray, varray.index_range()); -- 2.30.2 From 8aefc6772b4291439f9f8c2655182c2eb8862530 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 23 May 2023 19:25:28 -0400 Subject: [PATCH 33/85] Cleanup: Rename boolean mix calc function --- source/blender/blenkernel/intern/mesh_normals.cc | 4 ++-- source/blender/blenlib/BLI_array_utils.hh | 6 +++--- source/blender/blenlib/intern/array_utils.cc | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index fbe3761ae6a..222f4e66268 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -317,14 +317,14 @@ eAttrDomain Mesh::normal_domain_all_info() const const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); - const array_utils::BoolArrayMix face_mix = array_utils::bool_array_mix_calc(sharp_faces); + const array_utils::BoolArrayMix face_mix = array_utils::booleans_mix_calc(sharp_faces); if (face_mix == array_utils::BoolArrayMix::AllTrue) { return ATTR_DOMAIN_FACE; } const VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const array_utils::BoolArrayMix edge_mix = array_utils::bool_array_mix_calc(sharp_edges); + const array_utils::BoolArrayMix edge_mix = array_utils::booleans_mix_calc(sharp_edges); if (edge_mix == array_utils::BoolArrayMix::AllTrue) { return ATTR_DOMAIN_FACE; } diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index 4ca964dee3c..e42c23a6b94 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -146,10 +146,10 @@ enum class BoolArrayMix { AllTrue, Mixed, }; -BoolArrayMix bool_array_mix_calc(const VArray &varray, IndexRange range_to_check); -inline BoolArrayMix bool_array_mix_calc(const VArray &varray) +BoolArrayMix booleans_mix_calc(const VArray &varray, IndexRange range_to_check); +inline BoolArrayMix booleans_mix_calc(const VArray &varray) { - return bool_array_mix_calc(varray, varray.index_range()); + return booleans_mix_calc(varray, varray.index_range()); } } // namespace blender::array_utils diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc index 69ce30d1306..410b266b9d3 100644 --- a/source/blender/blenlib/intern/array_utils.cc +++ b/source/blender/blenlib/intern/array_utils.cc @@ -52,7 +52,7 @@ void invert_booleans(MutableSpan span) }); } -BoolArrayMix bool_array_mix_calc(const VArray &varray, const IndexRange range_to_check) +BoolArrayMix booleans_mix_calc(const VArray &varray, const IndexRange range_to_check) { if (varray.is_empty()) { return BoolArrayMix::None; -- 2.30.2 From 4ee088cb79592e8eaf5ea9d472acdc55aae83c47 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 23 May 2023 19:28:51 -0400 Subject: [PATCH 34/85] Fix: Remove function again after merge mistake --- source/blender/makesrna/intern/rna_mesh_api.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 34f1ab31cc7..d59dcebde9d 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -204,10 +204,6 @@ void RNA_api_mesh(StructRNA *srna) "Invert winding of all polygons " "(clears tessellation, does not handle custom normals)"); - func = RNA_def_function(srna, "calc_normals", "rna_Mesh_calc_normals"); - RNA_def_function_ui_description( - func, "Deprecated. Has no effect. Normals are calculated upon retrieval"); - func = RNA_def_function(srna, "set_sharp_from_angle", "ED_mesh_sharp_from_angle_set"); RNA_def_function_ui_description( func, "Set the sharp edge status for edges based on the angle of incident faces"); -- 2.30.2 From fc775c17d9aadaade4995a40ea3a92bd9c6391e4 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 24 May 2023 09:45:32 -0400 Subject: [PATCH 35/85] Cleanup: Rename enum --- .../blender/blenkernel/intern/mesh_normals.cc | 13 ++++---- source/blender/blenlib/BLI_array_utils.hh | 7 +++-- source/blender/blenlib/intern/array_utils.cc | 30 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 529c4af6cfe..d305737e6b7 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -317,21 +317,20 @@ eAttrDomain Mesh::normal_domain_all_info() const const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); - const array_utils::BoolArrayMix face_mix = array_utils::booleans_mix_calc(sharp_faces); - if (face_mix == array_utils::BoolArrayMix::AllTrue) { + const array_utils::BooleanMix face_mix = array_utils::booleans_mix_calc(sharp_faces); + if (face_mix == array_utils::BooleanMix::AllTrue) { return ATTR_DOMAIN_FACE; } const VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const array_utils::BoolArrayMix edge_mix = array_utils::booleans_mix_calc(sharp_edges); - if (edge_mix == array_utils::BoolArrayMix::AllTrue) { + const array_utils::BooleanMix edge_mix = array_utils::booleans_mix_calc(sharp_edges); + if (edge_mix == array_utils::BooleanMix::AllTrue) { return ATTR_DOMAIN_FACE; } - if (edge_mix == array_utils::BoolArrayMix::AllFalse && - face_mix == array_utils::BoolArrayMix::AllFalse) - { + if (edge_mix == array_utils::BooleanMix::AllFalse && + face_mix == array_utils::BooleanMix::AllFalse) { return ATTR_DOMAIN_POINT; } diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index e42c23a6b94..dc56492e909 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -140,14 +140,15 @@ inline void gather(const VArray &src, } void invert_booleans(MutableSpan span); -enum class BoolArrayMix { + +enum class BooleanMix { None, AllFalse, AllTrue, Mixed, }; -BoolArrayMix booleans_mix_calc(const VArray &varray, IndexRange range_to_check); -inline BoolArrayMix booleans_mix_calc(const VArray &varray) +BooleanMix booleans_mix_calc(const VArray &varray, IndexRange range_to_check); +inline BooleanMix booleans_mix_calc(const VArray &varray) { return booleans_mix_calc(varray, varray.index_range()); } diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc index 410b266b9d3..12e27b5ab1c 100644 --- a/source/blender/blenlib/intern/array_utils.cc +++ b/source/blender/blenlib/intern/array_utils.cc @@ -52,23 +52,23 @@ void invert_booleans(MutableSpan span) }); } -BoolArrayMix booleans_mix_calc(const VArray &varray, const IndexRange range_to_check) +BooleanMix booleans_mix_calc(const VArray &varray, const IndexRange range_to_check) { if (varray.is_empty()) { - return BoolArrayMix::None; + return BooleanMix::None; } const CommonVArrayInfo info = varray.common_info(); if (info.type == CommonVArrayInfo::Type::Single) { - return *static_cast(info.data) ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + return *static_cast(info.data) ? BooleanMix::AllTrue : BooleanMix::AllFalse; } if (info.type == CommonVArrayInfo::Type::Span) { const Span span(static_cast(info.data), varray.size()); return threading::parallel_reduce( range_to_check, 4096, - BoolArrayMix::None, - [&](const IndexRange range, const BoolArrayMix init) { - if (init == BoolArrayMix::Mixed) { + BooleanMix::None, + [&](const IndexRange range, const BooleanMix init) { + if (init == BooleanMix::Mixed) { return init; } @@ -76,31 +76,31 @@ BoolArrayMix booleans_mix_calc(const VArray &varray, const IndexRange rang const bool first = slice.first(); for (const bool value : slice.drop_front(1)) { if (value != first) { - return BoolArrayMix::Mixed; + return BooleanMix::Mixed; } } - return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + return first ? BooleanMix::AllTrue : BooleanMix::AllFalse; }, - [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); + [&](BooleanMix a, BooleanMix b) { return (a == b) ? a : BooleanMix::Mixed; }); } return threading::parallel_reduce( range_to_check, 2048, - BoolArrayMix::None, - [&](const IndexRange range, const BoolArrayMix init) { - if (init == BoolArrayMix::Mixed) { + BooleanMix::None, + [&](const IndexRange range, const BooleanMix init) { + if (init == BooleanMix::Mixed) { return init; } /* Alternatively, this could use #materialize to retrieve many values at once. */ const bool first = varray[range.first()]; for (const int64_t i : range.drop_front(1)) { if (varray[i] != first) { - return BoolArrayMix::Mixed; + return BooleanMix::Mixed; } } - return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse; + return first ? BooleanMix::AllTrue : BooleanMix::AllFalse; }, - [&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; }); + [&](BooleanMix a, BooleanMix b) { return (a == b) ? a : BooleanMix::Mixed; }); } } // namespace blender::array_utils -- 2.30.2 From 9c8ddef516842715a8160a054ec237a28f83c0c5 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 7 Jun 2023 10:42:06 -0400 Subject: [PATCH 36/85] Cleanup --- source/blender/blenkernel/intern/DerivedMesh.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 9d10ccd589d..4ddd3d44088 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -450,7 +450,7 @@ static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *me /* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case * of deferred CPU subdivision, this will be computed when the wrapper is generated. */ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { - BKE_mesh_corner_normals_ensure(mesh_final); + mesh_final->corner_normals(); } } else { @@ -1068,7 +1068,7 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final) /* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the * wrapper is generated. */ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { - BKE_mesh_corner_normals_ensure(mesh_final); + mesh_final->corner_normals(); } } else { -- 2.30.2 From 4771976d54dd42741d6ba9d1fd8163924182b732 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 7 Jun 2023 11:20:14 -0400 Subject: [PATCH 37/85] Cleanup --- .../intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc | 5 +++-- source/blender/editors/mesh/mesh_data.cc | 5 ++--- source/blender/editors/object/object_data_transfer.c | 2 -- source/blender/editors/object/object_edit.cc | 7 +++---- source/blender/makesdna/DNA_mesh_types.h | 7 +++---- .../geometry/nodes/node_geo_distribute_points_on_faces.cc | 3 +-- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index ec2e0629be7..881584a9b9b 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -260,14 +260,15 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache, if (subdiv_cache->use_custom_loop_normals) { const Mesh *coarse_mesh = subdiv_cache->mesh; + const Span corner_normals = coarse_mesh->corner_normals(); GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc(); GPU_vertbuf_init_with_format(src_custom_normals, get_custom_normals_format()); GPU_vertbuf_data_alloc(src_custom_normals, coarse_mesh->totloop); memcpy(GPU_vertbuf_get_data(src_custom_normals), - coarse_mesh->corner_normals().data(), - sizeof(float[3]) * coarse_mesh->totloop); + corner_normals.data(), + corner_normals.size_in_bytes()); GPUVertBuf *dst_custom_normals = GPU_vertbuf_calloc(); GPU_vertbuf_init_build_on_device( diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 8c69ac55914..5b4055ecf86 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -743,13 +743,12 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator return OPERATOR_CANCELLED; } - if (BMEditMesh *em = me->edit_mesh) { - BMesh &bm = *em->bm; + if (me->edit_mesh) { + BMesh &bm = *me->edit_mesh->bm; BM_data_layer_add(&bm, &bm.ldata, CD_CUSTOMLOOPNORMAL); } else { CustomData_add_layer(&me->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me->totloop); - me->runtime->corner_normals_dirty = true; } DEG_id_tag_update(&me->id, 0); diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index f0030d5617d..1675db6ffbe 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -524,8 +524,6 @@ static int data_transfer_exec(bContext *C, wmOperator *op) false, op->reports)) { - - DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY); changed = true; } diff --git a/source/blender/editors/object/object_edit.cc b/source/blender/editors/object/object_edit.cc index 595cb56cf41..cd09e646f4b 100644 --- a/source/blender/editors/object/object_edit.cc +++ b/source/blender/editors/object/object_edit.cc @@ -1598,18 +1598,17 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) continue; } - Mesh *mesh = reinterpret_cast(data); bool changed = false; if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(mesh, use_smooth); + BKE_mesh_smooth_flag_set(static_cast(ob->data), use_smooth); if (use_smooth) { const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth"); if (use_auto_smooth) { const float auto_smooth_angle = RNA_float_get(op->ptr, "auto_smooth_angle"); - BKE_mesh_sharp_edges_set_from_angle(mesh, auto_smooth_angle); + BKE_mesh_sharp_edges_set_from_angle(static_cast(ob->data), auto_smooth_angle); } } - BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL); + BKE_mesh_batch_cache_dirty_tag(static_cast(ob->data), BKE_MESH_BATCH_DIRTY_ALL); changed = true; } else if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY)) { diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 5f7e35b8673..065e81e7143 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -342,10 +342,9 @@ typedef struct Mesh { * normals are enough. With a combination of sharp and smooth, normals may be "split", * requiring face corner storage. * - * Depending on the sharp edge and face tags and custom normals, sometimes a less complex - * domain is enough. When possible, it's preferred to use face normals over vertex normals and - * vertex normals over face corner normals, since there is a 2-4x performance cost increase for - * each step. + * When possible, it's preferred to use face normals over vertex normals and vertex normals over + * face corner normals, since there is a 2-4x performance cost increase for each more complex + * domain. */ eAttrDomain normal_domain_all_info() const; /** diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index ff51bc776ce..b07478d6e29 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -343,10 +343,9 @@ static void compute_normal_outputs(const Mesh &mesh, break; } case ATTR_DOMAIN_FACE: { - const Span poly_normals = mesh.poly_normals(); bke::mesh_surface_sample::sample_face_attribute(mesh.looptri_polys(), looptri_indices, - VArray::ForSpan(poly_normals), + VArray::ForSpan(mesh.poly_normals()), IndexMask(looptri_indices.index_range()), r_normals); break; -- 2.30.2 From f159645eae4591cf4a3212016e2b92078e19b682 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 13 Jun 2023 17:15:53 -0400 Subject: [PATCH 38/85] Cleanup --- .../blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/BKE_mesh.h | 6 ----- .../blender/blenkernel/intern/mesh_normals.cc | 5 ----- .../blenloader/intern/versioning_400.cc | 7 ++++-- source/blender/makesrna/intern/rna_mesh.cc | 22 ++++++++++--------- 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index c171a7e82b9..96edba09c31 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 7 +#define BLENDER_FILE_SUBVERSION 8 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 6736b76741d..1ce45dec78b 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -323,12 +323,6 @@ const float (*BKE_mesh_vert_normals_ensure(const struct Mesh *mesh))[3]; */ const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]; -/** - * See #Mesh::corner_normals(). - * \warning May return null if the mesh is empty or has no polygons. - */ -const float (*BKE_mesh_corner_normals_ensure(const struct Mesh *mesh))[3]; - /** * Retrieve write access to the cached vertex normals, ensuring that they are allocated but *not* * that they are calculated. The provided vertex normals should be the same as if they were diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 8d49bdc3f18..570401f2d82 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -478,11 +478,6 @@ blender::Span Mesh::corner_normals() const return this->runtime->corner_normals; } -const float (*BKE_mesh_corner_normals_ensure(const Mesh *mesh))[3] -{ - return reinterpret_cast(mesh->corner_normals().data()); -} - void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops, const char data_type) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 35786c348f5..108b7846b71 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -154,8 +154,12 @@ static void version_mesh_objects_replace_auto_smooth(Main &bmain) } } -void do_versions_after_linking_400(FileData * /*fd*/, Main * /*bmain*/) +void do_versions_after_linking_400(FileData * /*fd*/, Main *bmain) { + if (!MAIN_VERSION_ATLEAST(bmain, 400, 8)) { + version_mesh_objects_replace_auto_smooth(*bmain); + } + /** * Versioning code until next subversion bump goes here. * @@ -170,7 +174,6 @@ void do_versions_after_linking_400(FileData * /*fd*/, Main * /*bmain*/) */ { /* Keep this block, even when empty. */ - version_mesh_objects_replace_auto_smooth(*bmain); } } diff --git a/source/blender/makesrna/intern/rna_mesh.cc b/source/blender/makesrna/intern/rna_mesh.cc index 8418f786b69..dec1952f12b 100644 --- a/source/blender/makesrna/intern/rna_mesh.cc +++ b/source/blender/makesrna/intern/rna_mesh.cc @@ -478,7 +478,7 @@ static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); - const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); + const blender::Span loop_normals = me->corner_normals(); copy_v3_v3(values, loop_normals[index]); } @@ -511,8 +511,9 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); - const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); - const float(*vec)[4] = CustomData_get_layer(&me->ldata, CD_MLOOPTANGENT); + const blender::Span loop_normals = me->corner_normals(); + const float(*vec)[4] = static_cast( + CustomData_get_layer(&me->ldata, CD_MLOOPTANGENT)); if (vec) { cross_v3_v3v3(values, loop_normals[index], vec[index]); @@ -686,7 +687,7 @@ static void rna_MeshLoopTriangle_normal_get(PointerRNA *ptr, float *values) static void rna_MeshLoopTriangle_split_normals_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); - const float(*loop_normals)[3] = BKE_mesh_corner_normals_ensure(me); + const blender::Span loop_normals = me->corner_normals(); const MLoopTri *lt = (const MLoopTri *)ptr->data; copy_v3_v3(values + 0, loop_normals[lt->tri[0]]); copy_v3_v3(values + 3, loop_normals[lt->tri[1]]); @@ -1675,12 +1676,13 @@ int rna_Mesh_poly_normals_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_p static void rna_Mesh_corner_normals_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { const Mesh *mesh = rna_mesh(ptr); - const float(*normals)[3] = BKE_mesh_corner_normals_ensure(mesh); - if (!normals) { + const blender::Span normals = mesh->corner_normals(); + if (normals.is_empty()) { iter->valid = false; return; } - rna_iterator_array_begin(iter, (void *)normals, sizeof(float[3]), mesh->totloop, false, nullptr); + rna_iterator_array_begin( + iter, (void *)normals.data(), sizeof(float[3]), mesh->totloop, false, nullptr); } static int rna_Mesh_corner_normals_length(PointerRNA *ptr) @@ -1692,14 +1694,14 @@ static int rna_Mesh_corner_normals_length(PointerRNA *ptr) int rna_Mesh_corner_normals_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) { const Mesh *mesh = rna_mesh(ptr); - const float(*normals)[3] = BKE_mesh_corner_normals_ensure(mesh); - if (index < 0 || index >= mesh->totloop || !normals) { + const blender::Span normals = mesh->corner_normals(); + if (index < 0 || index >= mesh->totloop || normals.is_empty()) { return false; } /* Casting away const is okay because this RNA type doesn't allow changing the value. */ r_ptr->owner_id = (ID *)&mesh->id; r_ptr->type = &RNA_MeshNormalValue; - r_ptr->data = (float *)normals[index]; + r_ptr->data = (float *)&normals[index]; return true; } -- 2.30.2 From d378d14d43fc4f26c8652cee54ad820fa5e365b9 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 21 Jun 2023 15:23:05 -0400 Subject: [PATCH 39/85] Cleanup --- .../blender/blenkernel/intern/geometry_component_mesh.cc | 3 +-- source/blender/editors/include/ED_mesh.h | 1 - source/blender/editors/mesh/mesh_data.cc | 5 ----- source/blender/makesrna/intern/rna_mesh.cc | 9 +++------ 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 98a69b4b844..14bbda60ae1 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -864,8 +864,7 @@ static void tag_component_positions_changed(void *owner) static void tag_component_corner_normals_dirty(void *owner) { - Mesh *mesh = static_cast(owner); - if (mesh != nullptr) { + if (Mesh *mesh = static_cast(owner)) { mesh->runtime->corner_normals_dirty = true; } } diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index d249b3e6172..3298b92e387 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -584,7 +584,6 @@ const bool *ED_mesh_uv_map_edge_select_layer_get(const struct Mesh *mesh, int uv const bool *ED_mesh_uv_map_pin_layer_get(const struct Mesh *mesh, int uv_map_index); bool ED_mesh_edge_is_loose(const struct Mesh *mesh, int index); -int ED_mesh_normal_domain_all_info_get(const struct Mesh *mesh); void ED_mesh_uv_ensure(struct Mesh *me, const char *name); int ED_mesh_uv_add( diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index be8bf58095d..44981873070 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -806,11 +806,6 @@ bool ED_mesh_edge_is_loose(const Mesh *mesh, const int index) return loose_edges.count > 0 && loose_edges.is_loose_bits[index]; } -int ED_mesh_normal_domain_all_info_get(const Mesh *mesh) -{ - return mesh->normal_domain_all_info(); -} - static void mesh_add_verts(Mesh *mesh, int len) { using namespace blender; diff --git a/source/blender/makesrna/intern/rna_mesh.cc b/source/blender/makesrna/intern/rna_mesh.cc index 772361cfa0c..1fcd49d0419 100644 --- a/source/blender/makesrna/intern/rna_mesh.cc +++ b/source/blender/makesrna/intern/rna_mesh.cc @@ -478,8 +478,7 @@ static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); - const blender::Span loop_normals = me->corner_normals(); - copy_v3_v3(values, loop_normals[index]); + copy_v3_v3(values, me->corner_normals()[index]); } static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values) @@ -511,12 +510,11 @@ static void rna_MeshLoop_bitangent_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); const int index = rna_MeshLoop_index_get(ptr); - const blender::Span loop_normals = me->corner_normals(); const float(*vec)[4] = static_cast( CustomData_get_layer(&me->ldata, CD_MLOOPTANGENT)); if (vec) { - cross_v3_v3v3(values, loop_normals[index], vec[index]); + cross_v3_v3v3(values, me->corner_normals()[index], vec[index]); mul_v3_fl(values, vec[index][3]); } else { @@ -1619,8 +1617,7 @@ int rna_Mesh_loops_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) static int rna_Mesh_normal_domain_all_info_get(PointerRNA *ptr) { - const Mesh *mesh = rna_mesh(ptr); - return ED_mesh_normal_domain_all_info_get(mesh); + return rna_mesh(ptr)->normal_domain_all_info(); } static void rna_Mesh_vertex_normals_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) -- 2.30.2 From 6e77c05f4eccec37dd115b49d73e19598a7de034 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 21 Jun 2023 15:40:46 -0400 Subject: [PATCH 40/85] Cleanup --- source/blender/editors/include/ED_mesh.h | 5 ---- source/blender/editors/mesh/mesh_data.cc | 7 ------ .../blender/makesrna/intern/rna_mesh_api.cc | 25 ++++++++++++++++--- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 84add5967ee..0828a883ff6 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -608,11 +608,6 @@ struct Mesh *ED_mesh_context(struct bContext *C); */ void ED_mesh_split_faces(struct Mesh *mesh); -/** - * Reset and fill the "sharp_edge" attribute based on the angle of manifold edges. - */ -void ED_mesh_sharp_from_angle_set(struct Mesh *mesh, float angle); - /* mesh backup */ typedef struct BMBackup { struct BMesh *bmcopy; diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index da3b9d371e3..3247fb6794f 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1150,10 +1150,3 @@ void ED_mesh_split_faces(Mesh *mesh) geometry::split_edges(*mesh, split_mask, {}); } -void ED_mesh_sharp_from_angle_set(Mesh *mesh, const float angle) -{ - mesh->attributes_for_write().remove("sharp_edge"); - mesh->attributes_for_write().remove("sharp_face"); - BKE_mesh_sharp_edges_set_from_angle(mesh, angle); - DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY); -} diff --git a/source/blender/makesrna/intern/rna_mesh_api.cc b/source/blender/makesrna/intern/rna_mesh_api.cc index b4bcfa1e337..cde969969cd 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.cc +++ b/source/blender/makesrna/intern/rna_mesh_api.cc @@ -47,6 +47,14 @@ static const char *rna_Mesh_unit_test_compare(Mesh *mesh, Mesh *mesh2, float thr return ret; } +static void rna_Mesh_sharp_from_angle_set(Mesh *mesh, const float angle) +{ + mesh->attributes_for_write().remove("sharp_edge"); + mesh->attributes_for_write().remove("sharp_face"); + BKE_mesh_sharp_edges_set_from_angle(mesh, angle); + DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY); +} + static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *uvmap) { float(*r_looptangents)[4]; @@ -219,10 +227,19 @@ void RNA_api_mesh(StructRNA *srna) "Invert winding of all polygons " "(clears tessellation, does not handle custom normals)"); - func = RNA_def_function(srna, "set_sharp_from_angle", "ED_mesh_sharp_from_angle_set"); - RNA_def_function_ui_description( - func, "Set the sharp edge status for edges based on the angle of incident faces"); - RNA_def_float(func, "angle", M_PI, 0.0f, M_PI, "Angle", "", 0.0f, M_PI); + func = RNA_def_function(srna, "set_sharp_from_angle", "rna_Mesh_sharp_from_angle_set"); + RNA_def_function_ui_description(func, + "Reset and fill the \"sharp_edge\" attribute based on the angle " + "of faces neighboring manifold edges"); + RNA_def_float(func, + "angle", + M_PI, + 0.0f, + M_PI, + "Angle", + "Angle between faces beyond which edges are marked sharp", + 0.0f, + M_PI); func = RNA_def_function(srna, "split_faces", "ED_mesh_split_faces"); RNA_def_function_ui_description(func, "Split faces based on the edge angle"); -- 2.30.2 From 7f8c25761882efb4bbff27ba1c98a1ed8086bc52 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 21 Jun 2023 15:46:11 -0400 Subject: [PATCH 41/85] Add back multrithreading to distribute points node normal sampling --- .../node_geo_distribute_points_on_faces.cc | 37 ++++++++++--------- source/blender/render/intern/multires_bake.cc | 2 +- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 54ff162fa47..7b61946546d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -336,30 +336,31 @@ static void compute_normal_outputs(const Mesh &mesh, { switch (mesh.normal_domain_all_info()) { case ATTR_DOMAIN_POINT: { - bke::mesh_surface_sample::sample_point_normals(mesh.corner_verts(), - mesh.looptris(), - looptri_indices, - bary_coords, - mesh.vert_normals(), - IndexMask(looptri_indices.index_range()), - r_normals); + const Span corner_verts = mesh.corner_verts(); + const Span looptris = mesh.looptris(); + const Span vert_normals = mesh.vert_normals(); + threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) { + bke::mesh_surface_sample::sample_point_normals( + corner_verts, looptris, looptri_indices, bary_coords, vert_normals, range, r_normals); + }); break; } case ATTR_DOMAIN_FACE: { - bke::mesh_surface_sample::sample_face_attribute(mesh.looptri_polys(), - looptri_indices, - VArray::ForSpan(mesh.poly_normals()), - IndexMask(looptri_indices.index_range()), - r_normals); + const Span looptri_polys = mesh.looptri_polys(); + VArray poly_normals = VArray::ForSpan(mesh.poly_normals()); + threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) { + bke::mesh_surface_sample::sample_face_attribute( + looptri_polys, looptri_indices, poly_normals, range, r_normals); + }); break; } case ATTR_DOMAIN_CORNER: { - bke::mesh_surface_sample::sample_corner_normals(mesh.looptris(), - looptri_indices, - bary_coords, - mesh.corner_normals(), - IndexMask(looptri_indices.index_range()), - r_normals); + const Span looptris = mesh.looptris(); + const Span corner_normals = mesh.corner_normals(); + threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) { + bke::mesh_surface_sample::sample_corner_normals( + looptris, looptri_indices, bary_coords, corner_normals, range, r_normals); + }); break; } default: diff --git a/source/blender/render/intern/multires_bake.cc b/source/blender/render/intern/multires_bake.cc index 2da35239353..59e4ac02f7a 100644 --- a/source/blender/render/intern/multires_bake.cc +++ b/source/blender/render/intern/multires_bake.cc @@ -512,12 +512,12 @@ static void do_multires_bake(MultiresBakeRender *bkr, const blender::Span corner_verts = temp_mesh->corner_verts(); const blender::Span vert_normals = temp_mesh->vert_normals(); const blender::Span poly_normals = temp_mesh->poly_normals(); - const blender::Span corner_normals = temp_mesh->corner_normals(); const blender::Span looptris = temp_mesh->looptris(); const blender::Span looptri_polys = temp_mesh->looptri_polys(); if (require_tangent) { if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { + const blender::Span corner_normals = temp_mesh->corner_normals(); BKE_mesh_calc_loop_tangent_ex( reinterpret_cast(positions.data()), polys, -- 2.30.2 From 0bc9a7e78b80838f980e0c043f80e70176414163 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 21 Jun 2023 15:50:37 -0400 Subject: [PATCH 42/85] Fix build --- source/blender/makesrna/intern/rna_mesh_api.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/makesrna/intern/rna_mesh_api.cc b/source/blender/makesrna/intern/rna_mesh_api.cc index cde969969cd..b592622f758 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.cc +++ b/source/blender/makesrna/intern/rna_mesh_api.cc @@ -24,6 +24,7 @@ # include "DNA_mesh_types.h" # include "BKE_anim_data.h" +# include "BKE_attribute.hh" # include "BKE_mesh.h" # include "BKE_mesh_mapping.h" # include "BKE_mesh_runtime.h" -- 2.30.2 From d0d29dd21d85dade78e9f0cb1a38ab81369cd82b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 26 Jul 2023 16:29:34 -0400 Subject: [PATCH 43/85] Fix --- source/blender/modifiers/intern/MOD_weighted_normal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index dc6f312aef9..4dbf747cc9c 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -86,7 +86,7 @@ struct WeightedNormalData { blender::OffsetIndices faces; blender::Span face_normals; blender::VArray sharp_faces; - const int *poly_strength; + const int *face_strength; const MDeformVert *dvert; int defgrp_index; -- 2.30.2 From 2a147d27d1ddc90d5e75e49064dd2e421c20bbc5 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 4 Aug 2023 10:11:16 -0400 Subject: [PATCH 44/85] Progress --- source/blender/makesdna/DNA_mesh_types.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 07ec5333e06..2d01da6fd9b 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -19,8 +19,6 @@ # include -# include "BKE_attribute.h" - # include "BLI_bounds_types.hh" # include "BLI_math_vector_types.hh" # include "BLI_offset_indices.hh" -- 2.30.2 From 953919aee15b3e173fbf2a6d88ae5b9b0b0ce9ac Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 20 Aug 2023 22:15:40 -0400 Subject: [PATCH 45/85] Move versioning code, more cleanup --- source/blender/blenkernel/BKE_mesh.hh | 13 +- .../blenkernel/BKE_mesh_legacy_convert.hh | 3 + .../blenkernel/intern/data_transfer.cc | 4 +- source/blender/blenkernel/intern/key.cc | 10 +- source/blender/blenkernel/intern/mesh.cc | 10 +- .../blenkernel/intern/mesh_legacy_convert.cc | 126 ++++++++++++++++++ .../blender/blenkernel/intern/mesh_mirror.cc | 9 +- .../blender/blenkernel/intern/mesh_normals.cc | 77 ++++++----- .../blenkernel/intern/subdiv_modifier.cc | 1 + .../blenloader/intern/versioning_400.cc | 126 ------------------ .../blenloader/intern/versioning_common.cc | 5 + .../blenloader/intern/versioning_defaults.cc | 2 - .../intern/shaders/common_debug_draw_lib.glsl | 4 + .../shaders/common_debug_print_lib.glsl | 19 ++- .../draw/intern/shaders/draw_debug_info.hh | 2 + source/blender/editors/mesh/mesh_data.cc | 11 +- source/blender/editors/transform/transform.cc | 2 +- .../blender_interface/BlenderFileLoader.cpp | 9 +- .../io/alembic/exporter/abc_writer_mesh.cc | 2 +- .../blender/io/collada/GeometryExporter.cpp | 10 +- source/blender/makesdna/DNA_mesh_types.h | 7 +- .../modifiers/intern/MOD_normal_edit.cc | 19 +-- .../modifiers/intern/MOD_weighted_normal.cc | 14 +- 23 files changed, 256 insertions(+), 229 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.hh b/source/blender/blenkernel/BKE_mesh.hh index cd417d70a90..526688c43c0 100644 --- a/source/blender/blenkernel/BKE_mesh.hh +++ b/source/blender/blenkernel/BKE_mesh.hh @@ -9,7 +9,6 @@ */ #include "BLI_index_mask.hh" -#include "BLI_virtual_array.hh" #include "BKE_mesh.h" #include "BKE_mesh_types.hh" @@ -158,9 +157,9 @@ void normals_calc_loop(Span vert_positions, Span loop_to_face_map, Span vert_normals, Span face_normals, - const VArray &sharp_edges, - const VArray &sharp_faces, - const short2 *custom_normals_data, + const bool *sharp_edges, + const bool *sharp_faces, + const short2 *clnors_data, CornerNormalSpaceArray *r_lnors_spacearr, MutableSpan r_loop_normals); @@ -171,7 +170,7 @@ void normals_loop_custom_set(Span vert_positions, Span corner_edges, Span vert_normals, Span face_normals, - const VArray &sharp_faces, + const bool *sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_loop_normals, MutableSpan r_clnors_data); @@ -183,7 +182,7 @@ void normals_loop_custom_set_from_verts(Span vert_positions, Span corner_edges, Span vert_normals, Span face_normals, - const VArray &sharp_faces, + const bool *sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_vert_normals, MutableSpan r_clnors_data); @@ -200,7 +199,7 @@ void edges_sharp_from_angle_set(OffsetIndices faces, Span corner_verts, Span corner_edges, Span face_normals, - const VArray &sharp_faces, + const bool *sharp_faces, const float split_angle, MutableSpan sharp_edges); diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.hh b/source/blender/blenkernel/BKE_mesh_legacy_convert.hh index e23221eea31..d517136d0cf 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.hh +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.hh @@ -13,6 +13,7 @@ #include "BLI_utildefines.h" struct CustomData; +struct Main; struct Mesh; struct MFace; @@ -108,6 +109,8 @@ void BKE_mesh_calc_edges_legacy(Mesh *me); void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh); +void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain); + /* Inlines */ /* NOTE(@sybren): Instead of -1 that function uses ORIGINDEX_NONE as defined in BKE_customdata.h, diff --git a/source/blender/blenkernel/intern/data_transfer.cc b/source/blender/blenkernel/intern/data_transfer.cc index ebb52e4163b..26b175f05d4 100644 --- a/source/blender/blenkernel/intern/data_transfer.cc +++ b/source/blender/blenkernel/intern/data_transfer.cc @@ -378,8 +378,8 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst, bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write(); bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&me_dst->face_data, CD_PROP_BOOL, "sharp_face")); /* Note loop_nors_dst contains our custom normals as transferred from source... */ blender::bke::mesh::normals_loop_custom_set(me_dst->vert_positions(), me_dst->edges(), diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index 1b0c6936a53..8b161ffc465 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -34,7 +34,6 @@ #include "DNA_scene_types.h" #include "BKE_anim_data.h" -#include "BKE_attribute.hh" #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -2269,13 +2268,12 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, {reinterpret_cast(vert_normals), mesh->totvert}); } if (loop_normals_needed) { - const blender::bke::AttributeAccessor attributes = mesh->attributes(); - const blender::VArray sharp_edges = *attributes.lookup_or_default( - "sharp_edge", ATTR_DOMAIN_EDGE, false); - const blender::VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); const blender::short2 *clnors = static_cast( CustomData_get_layer(&mesh->loop_data, CD_CUSTOMLOOPNORMAL)); + const bool *sharp_edges = static_cast( + CustomData_get_layer_named(&mesh->edge_data, CD_PROP_BOOL, "sharp_edge")); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, "sharp_face")); blender::bke::mesh::normals_calc_loop( positions, edges, diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index ede8c70b59a..c55776909e4 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1478,12 +1478,14 @@ void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle) } bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); - bke::mesh::edges_sharp_from_angle_set(me->polys(), + const bool *sharp_edges = static_cast( + CustomData_get_layer_named(&me->edge_data, CD_PROP_BOOL, "sharp_edge")); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&me->face_data, CD_PROP_BOOL, "sharp_face")); + bke::mesh::edges_sharp_from_angle_set(me->faces(), me->corner_verts(), me->corner_edges(), - me->poly_normals(), + me->face_normals(), sharp_faces, angle, sharp_edges.span); diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 5695ab7cf12..85f006bc715 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -29,9 +29,15 @@ #include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_global.h" +#include "BKE_idprop.hh" +#include "BKE_main.h" #include "BKE_mesh.hh" #include "BKE_mesh_legacy_convert.hh" +#include "BKE_modifier.h" #include "BKE_multires.hh" +#include "BKE_node.hh" + +#include "BLT_translation.h" using blender::MutableSpan; using blender::Span; @@ -2075,3 +2081,123 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Auto Smooth Conversion + * \{ */ + +static bNodeTree *add_auto_smooth_node_tree(Main &bmain) +{ + bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth"), "GeometryNodeTree"); + + ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", DATA_("Geometry")); + ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketFloatAngle", DATA_("Angle")); + ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", DATA_("Geometry")); + + bNode *group_input = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_INPUT); + group_input->locx = -380.0f; + bNode *group_output = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_OUTPUT); + group_output->locx = 260.0f; + group_output->flag |= NODE_DO_OUTPUT; + + bNode *shade_smooth = nodeAddNode(nullptr, node_tree, "GeometryNodeSetShadeSmooth"); + shade_smooth->locx = -160.0f; + shade_smooth->locy = 40.0f; + + bNode *store_node = nodeAddNode(nullptr, node_tree, "GeometryNodeStoreNamedAttribute"); + store_node->locx = 40.0f; + store_node->locy = 40.0f; + static_cast(store_node->storage)->data_type = CD_PROP_BOOL; + static_cast(store_node->storage)->domain = ATTR_DOMAIN_EDGE; + bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); + STRNCPY(name->default_value_typed()->value, "sharp_edge"); + + bNode *greater_node = nodeAddNode(nullptr, node_tree, "FunctionNodeCompare"); + greater_node->locx = -160.0f; + greater_node->locy = -100.0f; + static_cast(greater_node->storage)->operation = NODE_COMPARE_GREATER_THAN; + static_cast(greater_node->storage)->data_type = SOCK_FLOAT; + + bNode *edge_angle_node = nodeAddNode(nullptr, node_tree, "GeometryNodeInputMeshEdgeAngle"); + edge_angle_node->locx = -380.0f; + edge_angle_node->locy = -180.0f; + + nodeAddLink(node_tree, + group_input, + static_cast(group_input->outputs.first), + shade_smooth, + nodeFindSocket(shade_smooth, SOCK_IN, "Geometry")); + nodeAddLink(node_tree, + shade_smooth, + nodeFindSocket(shade_smooth, SOCK_OUT, "Geometry"), + store_node, + nodeFindSocket(store_node, SOCK_IN, "Geometry")); + nodeAddLink(node_tree, + edge_angle_node, + nodeFindSocket(edge_angle_node, SOCK_OUT, "Unsigned Angle"), + greater_node, + nodeFindSocket(greater_node, SOCK_IN, "A")); + nodeAddLink(node_tree, + group_input, + static_cast(BLI_findlink(&group_input->outputs, 1)), + greater_node, + nodeFindSocket(greater_node, SOCK_IN, "B")); + nodeAddLink(node_tree, + greater_node, + nodeFindSocket(greater_node, SOCK_OUT, "Result"), + store_node, + nodeFindSocket(store_node, SOCK_IN, "Value_Bool")); + nodeAddLink(node_tree, + store_node, + nodeFindSocket(store_node, SOCK_OUT, "Geometry"), + group_output, + static_cast(group_output->inputs.first)); + + LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { + nodeSetSelected(node, false); + } + + return node_tree; +} + +void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) +{ + using namespace blender; + bNodeTree *auto_smooth_node_tree = nullptr; + LISTBASE_FOREACH (Object *, object, &bmain.objects) { + if (object->type != OB_MESH) { + continue; + } + Mesh *mesh = static_cast(object->data); + if (!(mesh->flag & ME_AUTOSMOOTH)) { + continue; + } + if (CustomData_has_layer(&mesh->loop_data, CD_CUSTOMLOOPNORMAL)) { + continue; + } + if (!auto_smooth_node_tree) { + auto_smooth_node_tree = add_auto_smooth_node_tree(bmain); + } + auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); + STRNCPY(md->modifier.name, DATA_("Auto Smooth")); + BKE_modifier_unique_name(&object->modifiers, &md->modifier); + md->node_group = auto_smooth_node_tree; + if (!BLI_listbase_is_empty(&object->modifiers) && + static_cast(object->modifiers.last)->type == eModifierType_Subsurf) + { + /* Add the auto smooth node group before the last subdivision surface modifier if possible. + * Subdivision surface modifiers have special handling for interpolating face corner normals, + * and recalculating them afterwards isn't usually helpful and can be much slower. */ + BLI_insertlinkbefore(&object->modifiers, object->modifiers.last, md); + } + else { + BLI_addtail(&object->modifiers, md); + } + + md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); + IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); + IDP_AddToGroup(md->settings.properties, angle_prop); + } +} + +/** \} */ \ No newline at end of file diff --git a/source/blender/blenkernel/intern/mesh_mirror.cc b/source/blender/blenkernel/intern/mesh_mirror.cc index 6b8a2a1baa5..971d91ce5c0 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.cc +++ b/source/blender/blenkernel/intern/mesh_mirror.cc @@ -406,11 +406,10 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, /* calculate custom normals into loop_normals, then mirror first half into second half */ - const blender::bke::AttributeAccessor attributes = result->attributes(); - const blender::VArray sharp_edges = *attributes.lookup_or_default( - "sharp_edge", ATTR_DOMAIN_EDGE, false); - const blender::VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_edges = static_cast( + CustomData_get_layer_named(&result->edge_data, CD_PROP_BOOL, "sharp_edge")); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&result->face_data, CD_PROP_BOOL, "sharp_face")); blender::bke::mesh::normals_calc_loop(result->vert_positions(), result_edges, result_faces, diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 5129e8d7285..ffbc6da8e1f 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -437,14 +437,12 @@ blender::Span Mesh::corner_normals() const break; } case ATTR_DOMAIN_CORNER: { - const AttributeAccessor attributes = this->attributes(); - const VArray sharp_edges = *attributes.lookup_or_default( - "sharp_edge", ATTR_DOMAIN_EDGE, false); - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_edges = static_cast( + CustomData_get_layer_named(&this->edge_data, CD_PROP_BOOL, "sharp_edge")); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&this->face_data, CD_PROP_BOOL, "sharp_face")); const short2 *custom_normals = static_cast( CustomData_get_layer(&this->loop_data, CD_CUSTOMLOOPNORMAL)); - bke::mesh::normals_calc_loop(this->vert_positions(), this->edges(), this->faces(), @@ -821,14 +819,17 @@ static void mesh_edges_sharp_tag(const OffsetIndices faces, const Span corner_edges, const Span loop_to_face_map, const Span face_normals, - const VArray &sharp_faces, - const VArray &sharp_edges, + const Span sharp_faces, + const Span sharp_edges, const bool check_angle, const float split_angle, MutableSpan edge_to_loops, MutableSpan r_sharp_edges) { const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; + auto face_is_smooth = [&](const int face_i) { + return sharp_faces.is_empty() || !sharp_faces[face_i]; + }; for (const int face_i : faces.index_range()) { for (const int loop_index : faces[face_i]) { @@ -842,7 +843,7 @@ static void mesh_edges_sharp_tag(const OffsetIndices faces, /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */ e2l[0] = loop_index; /* We have to check this here too, else we might miss some flat faces!!! */ - e2l[1] = sharp_faces[face_i] ? INDEX_INVALID : INDEX_UNSET; + e2l[1] = face_is_smooth(face_i) ? INDEX_UNSET : INDEX_INVALID; } else if (e2l[1] == INDEX_UNSET) { const bool is_angle_sharp = (check_angle && @@ -854,14 +855,15 @@ static void mesh_edges_sharp_tag(const OffsetIndices faces, * or both faces have opposed (flipped) normals, i.e. both loops on the same edge share the * same vertex, or angle between both its faces' normals is above split_angle value. */ - if (sharp_faces[face_i] || sharp_edges[edge_i] || vert_i == corner_verts[e2l[0]] || - is_angle_sharp) { + if (!face_is_smooth(face_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) || + vert_i == corner_verts[e2l[0]] || is_angle_sharp) + { /* NOTE: we are sure that loop != 0 here ;). */ e2l[1] = INDEX_INVALID; /* We want to avoid tagging edges as sharp when it is already defined as such by * other causes than angle threshold. */ - if (is_angle_sharp) { + if (!r_sharp_edges.is_empty() && is_angle_sharp) { r_sharp_edges[edge_i] = true; } } @@ -885,10 +887,13 @@ static void mesh_edges_sharp_tag(const OffsetIndices faces, static void build_edge_to_loop_map(const OffsetIndices faces, const Span corner_verts, const Span corner_edges, - const VArray &sharp_faces, - const VArray &sharp_edges, + const Span sharp_faces, + const Span sharp_edges, MutableSpan edge_to_loops) { + auto face_is_smooth = [&](const int face_i) { + return sharp_faces.is_empty() || !sharp_faces[face_i]; + }; for (const int face_i : faces.index_range()) { for (const int loop_index : faces[face_i]) { @@ -902,14 +907,16 @@ static void build_edge_to_loop_map(const OffsetIndices faces, /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */ e2l[0] = loop_index; /* We have to check this here too, else we might miss some flat faces!!! */ - e2l[1] = sharp_faces[face_i] ? INDEX_INVALID : INDEX_UNSET; + e2l[1] = !face_is_smooth(face_i) ? INDEX_INVALID : INDEX_UNSET; } else if (e2l[1] == INDEX_UNSET) { /* Second loop using this edge, time to test its sharpness. * An edge is sharp if it is tagged as such, or its face is not smooth, * or both face have opposed (flipped) normals, i.e. both loops on the same edge share the * same vertex. */ - if (sharp_faces[face_i] || sharp_edges[edge_i] || vert_i == corner_verts[e2l[0]]) { + if (!face_is_smooth(face_i) || (!sharp_edges.is_empty() && sharp_edges[edge_i]) || + vert_i == corner_verts[e2l[0]]) + { /* NOTE: we are sure that loop != 0 here ;). */ e2l[1] = INDEX_INVALID; } @@ -930,7 +937,7 @@ void edges_sharp_from_angle_set(const OffsetIndices faces, const Span corner_verts, const Span corner_edges, const Span face_normals, - const VArray &sharp_faces, + const bool *sharp_faces, const float split_angle, MutableSpan sharp_edges) { @@ -950,8 +957,8 @@ void edges_sharp_from_angle_set(const OffsetIndices faces, corner_edges, loop_to_face, face_normals, - sharp_faces, - VArray::ForSpan(sharp_edges), + Span(sharp_faces, sharp_faces ? faces.size() : 0), + sharp_edges, true, split_angle, edge_to_loops, @@ -1347,9 +1354,9 @@ void normals_calc_loop(const Span vert_positions, const Span loop_to_face_map, const Span vert_normals, const Span face_normals, - const VArray &sharp_edges, - const VArray &sharp_faces, - const short2 *custom_normals_data, + const bool *sharp_edges, + const bool *sharp_faces, + const short2 *clnors_data, CornerNormalSpaceArray *r_lnors_spacearr, MutableSpan r_loop_normals) { @@ -1386,7 +1393,7 @@ void normals_calc_loop(const Span vert_positions, SCOPED_TIMER_AVERAGED(__func__); #endif - if (!r_lnors_spacearr && custom_normals_data) { + if (!r_lnors_spacearr && clnors_data) { /* We need to compute lnor spacearr if some custom lnor data are given to us! */ r_lnors_spacearr = &_lnors_spacearr; } @@ -1395,7 +1402,7 @@ void normals_calc_loop(const Span vert_positions, LoopSplitTaskDataCommon common_data; common_data.lnors_spacearr = r_lnors_spacearr; common_data.loop_normals = r_loop_normals; - common_data.clnors_data = {custom_normals_data, custom_normals_data ? corner_verts.size() : 0}; + common_data.clnors_data = {clnors_data, clnors_data ? corner_verts.size() : 0}; common_data.positions = vert_positions; common_data.edges = edges; common_data.faces = faces; @@ -1411,8 +1418,12 @@ void normals_calc_loop(const Span vert_positions, array_utils::gather(vert_normals, corner_verts, r_loop_normals, 1024); /* This first loop check which edges are actually smooth, and compute edge vectors. */ - build_edge_to_loop_map( - faces, corner_verts, corner_edges, sharp_faces, sharp_edges, edge_to_loops); + build_edge_to_loop_map(faces, + corner_verts, + corner_edges, + Span(sharp_faces, sharp_faces ? faces.size() : 0), + Span(sharp_edges, sharp_edges ? edges.size() : 0), + edge_to_loops); Vector single_corners; Vector fan_corners; @@ -1464,7 +1475,7 @@ static void mesh_normals_loop_custom_set(Span positions, Span corner_edges, Span vert_normals, Span face_normals, - const VArray &sharp_faces, + const bool *sharp_faces, const bool use_vertices, MutableSpan r_custom_loop_normals, MutableSpan sharp_edges, @@ -1490,7 +1501,7 @@ static void mesh_normals_loop_custom_set(Span positions, loop_to_face, vert_normals, face_normals, - VArray::ForSpan(sharp_edges), + sharp_edges.data(), sharp_faces, r_clnors_data.data(), &lnors_spacearr, @@ -1610,7 +1621,7 @@ static void mesh_normals_loop_custom_set(Span positions, loop_to_face, vert_normals, face_normals, - VArray::ForSpan(sharp_edges), + sharp_edges.data(), sharp_faces, r_clnors_data.data(), &lnors_spacearr, @@ -1668,7 +1679,7 @@ void normals_loop_custom_set(const Span vert_positions, const Span corner_edges, const Span vert_normals, const Span face_normals, - const VArray &sharp_faces, + const bool *sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_loop_normals, MutableSpan r_clnors_data) @@ -1694,7 +1705,7 @@ void normals_loop_custom_set_from_verts(const Span vert_positions, const Span corner_edges, const Span vert_normals, const Span face_normals, - const VArray &sharp_faces, + const bool *sharp_faces, MutableSpan sharp_edges, MutableSpan r_custom_vert_normals, MutableSpan r_clnors_data) @@ -1727,8 +1738,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const MutableAttributeAccessor attributes = mesh->attributes_for_write(); SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, "sharp_face")); mesh_normals_loop_custom_set( mesh->vert_positions(), diff --git a/source/blender/blenkernel/intern/subdiv_modifier.cc b/source/blender/blenkernel/intern/subdiv_modifier.cc index d6e99525e13..2490e8936fd 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.cc +++ b/source/blender/blenkernel/intern/subdiv_modifier.cc @@ -2,6 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BKE_attribute.h" #include "BKE_subdiv_modifier.hh" #include "MEM_guardedalloc.h" diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 9cd7c45e56b..a386ab6401e 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -15,7 +15,6 @@ #include "DNA_brush_types.h" #include "DNA_light_types.h" #include "DNA_lightprobe_types.h" -#include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" @@ -31,16 +30,13 @@ #include "BLI_set.hh" #include "BLI_string_ref.hh" -#include "BKE_attribute.hh" #include "BKE_effect.h" #include "BKE_grease_pencil.hh" #include "BKE_idprop.hh" #include "BKE_main.h" #include "BKE_mesh_legacy_convert.hh" -#include "BKE_modifier.h" #include "BKE_node.hh" #include "BKE_node_runtime.hh" -#include "BKE_node_tree_update.h" #include "BKE_scene.h" #include "BKE_tracking.h" @@ -49,130 +45,12 @@ #include "BLO_read_write.h" #include "BLO_readfile.h" -#include "BLT_translation.h" - #include "readfile.h" #include "versioning_common.h" // static CLG_LogRef LOG = {"blo.readfile.doversion"}; -static bNodeTree *add_auto_smooth_node_tree(Main &bmain) -{ - bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth"), "GeometryNodeTree"); - - ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", DATA_("Geometry")); - ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketFloatAngle", DATA_("Angle")); - ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", DATA_("Geometry")); - - bNode *group_input = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_INPUT); - group_input->locx = -380.0f; - bNode *group_output = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_OUTPUT); - group_output->locx = 260.0f; - group_output->flag |= NODE_DO_OUTPUT; - - bNode *shade_smooth = nodeAddNode(nullptr, node_tree, "GeometryNodeSetShadeSmooth"); - shade_smooth->locx = -160.0f; - shade_smooth->locy = 40.0f; - - bNode *store_node = nodeAddNode(nullptr, node_tree, "GeometryNodeStoreNamedAttribute"); - store_node->locx = 40.0f; - store_node->locy = 40.0f; - static_cast(store_node->storage)->data_type = CD_PROP_BOOL; - static_cast(store_node->storage)->domain = ATTR_DOMAIN_EDGE; - bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); - STRNCPY(name->default_value_typed()->value, "sharp_edge"); - - bNode *greater_node = nodeAddNode(nullptr, node_tree, "FunctionNodeCompare"); - greater_node->locx = -160.0f; - greater_node->locy = -100.0f; - static_cast(greater_node->storage)->operation = NODE_COMPARE_GREATER_THAN; - static_cast(greater_node->storage)->data_type = SOCK_FLOAT; - - bNode *edge_angle_node = nodeAddNode(nullptr, node_tree, "GeometryNodeInputMeshEdgeAngle"); - edge_angle_node->locx = -380.0f; - edge_angle_node->locy = -180.0f; - - nodeAddLink(node_tree, - group_input, - static_cast(group_input->outputs.first), - shade_smooth, - nodeFindSocket(shade_smooth, SOCK_IN, "Geometry")); - nodeAddLink(node_tree, - shade_smooth, - nodeFindSocket(shade_smooth, SOCK_OUT, "Geometry"), - store_node, - nodeFindSocket(store_node, SOCK_IN, "Geometry")); - nodeAddLink(node_tree, - edge_angle_node, - nodeFindSocket(edge_angle_node, SOCK_OUT, "Unsigned Angle"), - greater_node, - nodeFindSocket(greater_node, SOCK_IN, "A")); - nodeAddLink(node_tree, - group_input, - static_cast(BLI_findlink(&group_input->outputs, 1)), - greater_node, - nodeFindSocket(greater_node, SOCK_IN, "B")); - nodeAddLink(node_tree, - greater_node, - nodeFindSocket(greater_node, SOCK_OUT, "Result"), - store_node, - nodeFindSocket(store_node, SOCK_IN, "Value_Bool")); - nodeAddLink(node_tree, - store_node, - nodeFindSocket(store_node, SOCK_OUT, "Geometry"), - group_output, - static_cast(group_output->inputs.first)); - - LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { - nodeSetSelected(node, false); - } - - version_socket_update_is_used(node_tree); - - return node_tree; -} - -static void version_mesh_objects_replace_auto_smooth(Main &bmain) -{ - using namespace blender; - bNodeTree *auto_smooth_node_tree = nullptr; - LISTBASE_FOREACH (Object *, object, &bmain.objects) { - if (object->type != OB_MESH) { - continue; - } - Mesh *mesh = static_cast(object->data); - if (!(mesh->flag & ME_AUTOSMOOTH)) { - continue; - } - if (CustomData_has_layer(&mesh->loop_data, CD_CUSTOMLOOPNORMAL)) { - continue; - } - if (!auto_smooth_node_tree) { - auto_smooth_node_tree = add_auto_smooth_node_tree(bmain); - } - auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); - STRNCPY(md->modifier.name, DATA_("Auto Smooth")); - BKE_modifier_unique_name(&object->modifiers, &md->modifier); - md->node_group = auto_smooth_node_tree; - if (!BLI_listbase_is_empty(&object->modifiers) && - static_cast(object->modifiers.last)->type == eModifierType_Subsurf) - { - /* Add the auto smooth node group before the last subdivision surface modifier if possible. - * Subdivision surface modifiers have special handling for interpolating face corner normals, - * and recalculating them afterwards isn't usually helpful and can be much slower. */ - BLI_insertlinkbefore(&object->modifiers, object->modifiers.last, md); - } - else { - BLI_addtail(&object->modifiers, md); - } - - md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); - IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); - IDP_AddToGroup(md->settings.properties, angle_prop); - } -} - static void version_composite_nodetree_null_id(bNodeTree *ntree, Scene *scene) { for (bNode *node : ntree->all_nodes()) { @@ -244,10 +122,6 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain) } } - if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 16)) { - version_mesh_objects_replace_auto_smooth(*bmain); - } - /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index 05d85be73db..1471e8631cb 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -25,6 +25,7 @@ #include "BKE_lib_override.hh" #include "BKE_main.h" #include "BKE_main_namemap.h" +#include "BKE_mesh_legacy_convert.hh" #include "BKE_node.hh" #include "BKE_node_runtime.hh" @@ -525,4 +526,8 @@ void do_versions_after_setup(Main *new_bmain, BlendFileReadReport *reports) /* Does not add any new IDs, but needs the full Main data-base. */ BKE_lib_override_library_main_hierarchy_root_ensure(new_bmain); } + + if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 16)) { + BKE_main_mesh_legacy_convert_auto_smooth(*new_bmain); + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index e0cfea70046..3b97caefb80 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -13,8 +13,6 @@ * To update preference defaults see `userdef_default.c`. */ -#define DNA_DEPRECATED_ALLOW - #include "MEM_guardedalloc.h" #include "BLI_listbase.h" diff --git a/source/blender/draw/intern/shaders/common_debug_draw_lib.glsl b/source/blender/draw/intern/shaders/common_debug_draw_lib.glsl index 010b486b49f..030a5303032 100644 --- a/source/blender/draw/intern/shaders/common_debug_draw_lib.glsl +++ b/source/blender/draw/intern/shaders/common_debug_draw_lib.glsl @@ -6,6 +6,8 @@ * will be rendered in the default view. No additional setup required. */ +#ifdef DRW_DEBUG_DRAW + /** Global switch option. */ bool drw_debug_draw_enable = true; const vec4 drw_debug_default_color = vec4(1.0, 0.0, 0.0, 1.0); @@ -212,4 +214,6 @@ void drw_debug_matrix_as_bbox(mat4 mat) drw_debug_matrix_as_bbox(mat, drw_debug_default_color); } +#endif + /** \} */ diff --git a/source/blender/draw/intern/shaders/common_debug_print_lib.glsl b/source/blender/draw/intern/shaders/common_debug_print_lib.glsl index 157f3133a7c..77302b46d0e 100644 --- a/source/blender/draw/intern/shaders/common_debug_print_lib.glsl +++ b/source/blender/draw/intern/shaders/common_debug_print_lib.glsl @@ -30,6 +30,8 @@ * in sync to write the same data. */ +#ifdef DRW_DEBUG_PRINT + /** Global switch option when you want to silence all prints from all shaders at once. */ bool drw_debug_print_enable = true; @@ -202,7 +204,7 @@ void drw_print_value(int value) drw_print_value_uint(uint(abs(value)), false, (value < 0), false); } -#ifndef GPU_METAL +# ifndef GPU_METAL void drw_print_value(bool value) { @@ -214,7 +216,7 @@ void drw_print_value(bool value) } } -#endif +# endif /* NOTE(@fclem): This is homebrew and might not be 100% accurate (accuracy has * not been tested and might dependent on compiler implementation). If unsure, @@ -246,6 +248,12 @@ void drw_print_value(float val) bool display_exponent = exponent >= (significant_digits) || exponent <= (-significant_digits + 1.0); + if (exponent < -1.0) { + /* FIXME(fclem): Display of values with exponent from -1 to -5 is broken. Force scientific + * notation in these cases. */ + display_exponent = true; + } + float int_significant_digits = min(exponent + 1.0, significant_digits); float dec_significant_digits = max(0.0, significant_digits - int_significant_digits); /* Power to get to the rounding point. */ @@ -290,8 +298,7 @@ void drw_print_value(float val) } /* Decimal part. */ value = uint(abs(dec_part)); -#if 0 /* We don't do that because it makes unstable values really hard to \ - read. */ +# if 0 /* We don't do that because it makes unstable values really hard to read. */ /* Trim trailing zeros. */ while ((value % base) == 0u) { value /= base; @@ -299,7 +306,7 @@ void drw_print_value(float val) break; } } -#endif +# endif if (value != 0u) { for (int i = 0; value != 0u || i == 0; i++, value /= base) { drw_print_append_digit(value % base, digits[digit / 4u]); @@ -409,3 +416,5 @@ void drw_print_value(mat3 value) drw_print(" ", value[2]); drw_print(")"); } + +#endif diff --git a/source/blender/draw/intern/shaders/draw_debug_info.hh b/source/blender/draw/intern/shaders/draw_debug_info.hh index 828a7c04504..105cd24483c 100644 --- a/source/blender/draw/intern/shaders/draw_debug_info.hh +++ b/source/blender/draw/intern/shaders/draw_debug_info.hh @@ -12,6 +12,7 @@ * \{ */ GPU_SHADER_CREATE_INFO(draw_debug_print) + .define("DRW_DEBUG_PRINT") .typedef_source("draw_shader_shared.h") .storage_buf(DRW_DEBUG_PRINT_SLOT, Qualifier::READ_WRITE, "uint", "drw_debug_print_buf[]"); @@ -37,6 +38,7 @@ GPU_SHADER_CREATE_INFO(draw_debug_print_display) * \{ */ GPU_SHADER_CREATE_INFO(draw_debug_draw) + .define("DRW_DEBUG_DRAW") .typedef_source("draw_shader_shared.h") .storage_buf(DRW_DEBUG_DRAW_SLOT, Qualifier::READ_WRITE, diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 563d7fa4969..7b546e7a602 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1124,21 +1124,22 @@ Mesh *ED_mesh_context(bContext *C) void ED_mesh_split_faces(Mesh *mesh) { using namespace blender; - const OffsetIndices faces = mesh->faces(); + const OffsetIndices polys = mesh->faces(); + const Span corner_verts = mesh->corner_verts(); const Span corner_edges = mesh->corner_edges(); const bke::AttributeAccessor attributes = mesh->attributes(); const VArray mesh_sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, "sharp_face")); Array sharp_edges(mesh->totedge); mesh_sharp_edges.materialize(sharp_edges); - threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) { + threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { for (const int face_i : range) { if (sharp_faces && sharp_faces[face_i]) { - for (const int edge : corner_edges.slice(faces[face_i])) { + for (const int edge : corner_edges.slice(polys[face_i])) { sharp_edges[edge] = true; } } diff --git a/source/blender/editors/transform/transform.cc b/source/blender/editors/transform/transform.cc index 62d84ca7f7a..65b34c35d4d 100644 --- a/source/blender/editors/transform/transform.cc +++ b/source/blender/editors/transform/transform.cc @@ -2064,7 +2064,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - BMEditMesh *em = NULL; /* BKE_editmesh_from_object(t->obedit); */ + BMEditMesh *em = nullptr; /* BKE_editmesh_from_object(t->obedit); */ bool do_skip = false; /* Currently only used for two of three most frequent transform ops, diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 286b9a6a180..4f00f8c20fb 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -422,8 +422,7 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) MLoopTri *mlooptri = (MLoopTri *)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__); blender::bke::mesh::looptris_calc(vert_positions, mesh_polys, corner_verts, {mlooptri, tottri}); const blender::Span looptri_faces = me->looptri_faces(); - - const blender::Span corner_normals = me->corner_normals(); + const blender::Span lnors = me->corner_normals(); // Get other mesh data const FreestyleEdge *fed = (const FreestyleEdge *)CustomData_get_layer(&me->edge_data, @@ -541,9 +540,9 @@ void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) v3[2] += _z_offset; if (_smooth && (!sharp_faces[poly_i])) { - copy_v3_v3(n1, corner_normals[lt->tri[0]]); - copy_v3_v3(n2, corner_normals[lt->tri[1]]); - copy_v3_v3(n3, corner_normals[lt->tri[2]]); + copy_v3_v3(n1, lnors[lt->tri[0]]); + copy_v3_v3(n2, lnors[lt->tri[1]]); + copy_v3_v3(n3, lnors[lt->tri[2]]); mul_mat3_m4_v3(nmat, n1); mul_mat3_m4_v3(nmat, n2); diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index c9646782ca8..533f28338d4 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -556,7 +556,7 @@ static void get_loop_normals(const Mesh *mesh, std::vector &normals) threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { const IndexRange face = faces[i]; - for (const int i : IndexRange(face.size())) { + for (const int i : face.index_range()) { copy_yup_from_zup(dst_normals[face.last(i)], corner_normals[face[i]]); } } diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index bb3854477fd..be92c21bf00 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -625,12 +625,14 @@ void GeometryExporter::create_normals(std::vector &normals, const VArray sharp_faces = *attributes.lookup_or_default( "sharp_face", ATTR_DOMAIN_FACE, false); - const blender::Span corner_normals = me->corner_normals(); - bool use_custom_normals = true; + blender::Span corner_normals; + if (me->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + corner_normals = me->corner_normals(); + } for (const int face_index : faces.index_range()) { const IndexRange face = faces[face_index]; - bool use_vert_normals = use_custom_normals || !sharp_faces[face_index]; + bool use_vert_normals = !corner_normals.is_empty() || !sharp_faces[face_index]; if (!use_vert_normals) { /* For flat faces use face normal as vertex normal: */ @@ -648,7 +650,7 @@ void GeometryExporter::create_normals(std::vector &normals, if (use_vert_normals) { float normalized[3]; - if (use_custom_normals) { + if (!corner_normals.is_empty()) { normalize_v3_v3(normalized, corner_normals[corner]); } else { diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 2d01da6fd9b..c83512ed497 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -153,9 +153,6 @@ typedef struct Mesh { /** Mostly more flags used when editing or displaying the mesh. */ uint16_t flag; - /** - * The angle for auto smooth in radians. `M_PI` (180 degrees) causes all edges to be smooth. - */ float smoothresh DNA_DEPRECATED; /** Per-mesh settings for voxel remesh. */ @@ -356,7 +353,7 @@ typedef struct Mesh { * face corner normals, since there is a 2-4x performance cost increase for each more complex * domain. */ - eAttrDomain normal_domain_all_info() const; + int normal_domain_all_info() const; /** * Normal direction of polygons, defined by positions and the winding direction of face corners. */ @@ -371,7 +368,7 @@ typedef struct Mesh { * normals, the `sharp_edge` and `sharp_face` attributes, and potentially by custom normals. * * \note Because of the large memory requirements of storing normals per face corner, prefer - * using #poly_normals() or #vert_normals() when possible (see #normal_domain_all_info()). + * using #face_normals() or #vert_normals() when possible (see #normal_domain_all_info()). */ blender::Span corner_normals() const; #endif diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index e971b366bd3..cbfa1fe2de9 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -232,9 +232,6 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, blender::MutableSpan corner_edges, const blender::OffsetIndices faces) { - using namespace blender; - const bke::AttributeAccessor attributes = mesh->attributes(); - Object *ob_target = enmd->target; const bool do_facenors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; @@ -324,8 +321,8 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd, if (do_facenors_fix) { faces_check_flip(*mesh, nos, mesh->face_normals()); } - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, "sharp_face")); blender::bke::mesh::normals_loop_custom_set(vert_positions, edges, faces, @@ -361,8 +358,6 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, blender::MutableSpan corner_edges, const blender::OffsetIndices faces) { - using namespace blender; - const bke::AttributeAccessor attributes = mesh->attributes(); Object *ob_target = enmd->target; const bool do_facenors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0; @@ -431,8 +426,8 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd, if (do_facenors_fix) { faces_check_flip(*mesh, nos, mesh->face_normals()); } - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, "sharp_face")); blender::bke::mesh::normals_loop_custom_set(positions, edges, faces, @@ -516,8 +511,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, clnors = static_cast( CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); loop_normals.reinitialize(corner_verts.size()); - const VArray sharp_faces = *attributes.lookup_or_default( - "sharp_face", ATTR_DOMAIN_FACE, false); + const bool *sharp_faces = static_cast( + CustomData_get_layer_named(&result->face_data, CD_PROP_BOOL, "sharp_face")); blender::bke::mesh::normals_calc_loop(positions, edges, faces, @@ -526,7 +521,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, {}, result->vert_normals(), result->face_normals(), - VArray::ForSpan(sharp_edges.span), + sharp_edges.span.data(), sharp_faces, clnors, nullptr, diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index 379dd4ab7c9..219f31f4ca3 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -85,7 +85,7 @@ struct WeightedNormalData { blender::OffsetIndices faces; blender::Span face_normals; - blender::VArray sharp_faces; + const bool *sharp_faces; const int *face_strength; const MDeformVert *dvert; @@ -227,7 +227,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, loop_to_face, wn_data->vert_normals, wn_data->face_normals, - blender::VArray::ForSpan(wn_data->sharp_edges), + wn_data->sharp_edges.data(), wn_data->sharp_faces, has_clnors ? clnors.data() : nullptr, &lnors_spacearr, @@ -356,7 +356,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd, loop_to_face, wn_data->vert_normals, face_normals, - blender::VArray::ForSpan(wn_data->sharp_edges), + wn_data->sharp_edges.data(), wn_data->sharp_faces, has_clnors ? clnors.data() : nullptr, nullptr, @@ -477,7 +477,8 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh using namespace blender; WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md; - Mesh *result = (Mesh *)BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE); + Mesh *result; + result = (Mesh *)BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE); const int verts_num = result->totvert; const blender::Span positions = mesh->vert_positions(); @@ -540,8 +541,9 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh wn_data.faces = faces; wn_data.face_normals = mesh->face_normals(); - wn_data.sharp_faces = *attributes.lookup_or_default("sharp_face", ATTR_DOMAIN_FACE, false); - wn_data.poly_strength = static_cast(CustomData_get_layer_named( + wn_data.sharp_faces = static_cast( + CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, "sharp_face")); + wn_data.face_strength = static_cast(CustomData_get_layer_named( &result->face_data, CD_PROP_INT32, MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID)); wn_data.dvert = dvert; -- 2.30.2 From 32fa37bf83f15d3a574d6c45be5b8a52e8dccc03 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 20 Aug 2023 23:00:05 -0400 Subject: [PATCH 46/85] Fix build errors --- source/blender/blenkernel/intern/DerivedMesh.cc | 4 ++-- source/blender/blenkernel/intern/mesh.cc | 2 -- source/blender/blenkernel/intern/mesh_legacy_convert.cc | 1 + source/blender/blenkernel/intern/mesh_normals.cc | 2 +- source/blender/blenkernel/intern/shrinkwrap.cc | 1 + source/blender/blenloader/intern/versioning_defaults.cc | 2 ++ source/blender/io/usd/hydra/mesh.cc | 8 +++++--- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index c02c837ff07..fce8c2d0752 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -443,7 +443,7 @@ static void add_orco_mesh( static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *mesh_final) { - const eAttrDomain domain = mesh_final->normal_domain_all_info(); + const eAttrDomain domain = eAttrDomain(mesh_final->normal_domain_all_info()); /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; @@ -1056,7 +1056,7 @@ bool editbmesh_modifier_is_enabled(const Scene *scene, static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final) { - const eAttrDomain domain = mesh_final->normal_domain_all_info(); + const eAttrDomain domain = eAttrDomain(mesh_final->normal_domain_all_info()); SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; if (subsurf_runtime_data) { diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index c55776909e4..3005352d2bb 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1478,8 +1478,6 @@ void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle) } bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( "sharp_edge", ATTR_DOMAIN_EDGE); - const bool *sharp_edges = static_cast( - CustomData_get_layer_named(&me->edge_data, CD_PROP_BOOL, "sharp_edge")); const bool *sharp_faces = static_cast( CustomData_get_layer_named(&me->face_data, CD_PROP_BOOL, "sharp_face")); bke::mesh::edges_sharp_from_angle_set(me->faces(), diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 85f006bc715..bb07833e325 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -36,6 +36,7 @@ #include "BKE_modifier.h" #include "BKE_multires.hh" #include "BKE_node.hh" +#include "BKE_node_runtime.hh" #include "BLT_translation.h" diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index ffbc6da8e1f..eceb1e800a3 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -299,7 +299,7 @@ void normals_calc_face_vert(const Span positions, /** \name Mesh Normal Calculation * \{ */ -eAttrDomain Mesh::normal_domain_all_info() const +int Mesh::normal_domain_all_info() const { using namespace blender; using namespace blender::bke; diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index c6dfc925cd4..35039d0c6cd 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -27,6 +27,7 @@ #include "BLI_utildefines.h" #include "BKE_DerivedMesh.h" +#include "BKE_attribute.h" #include "BKE_cdderivedmesh.h" #include "BKE_context.h" #include "BKE_lattice.h" diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index 3b97caefb80..e0cfea70046 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -13,6 +13,8 @@ * To update preference defaults see `userdef_default.c`. */ +#define DNA_DEPRECATED_ALLOW + #include "MEM_guardedalloc.h" #include "BLI_listbase.h" diff --git a/source/blender/io/usd/hydra/mesh.cc b/source/blender/io/usd/hydra/mesh.cc index 04d24f4ef36..91f87fd0126 100644 --- a/source/blender/io/usd/hydra/mesh.cc +++ b/source/blender/io/usd/hydra/mesh.cc @@ -6,6 +6,7 @@ #include #include +#include "BKE_attribute.h" #include "BKE_material.h" #include "BKE_mesh.hh" #include "BKE_mesh_runtime.hh" @@ -233,9 +234,10 @@ void MeshData::write_submeshes(const Mesh *mesh) const Span corner_verts = mesh->corner_verts(); const Span looptris = mesh->looptris(); - Array corner_normals(mesh->totloop); - BKE_mesh_calc_normals_split_ex( - mesh, nullptr, reinterpret_cast(corner_normals.data())); + Span corner_normals; + if (mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + corner_normals = mesh->corner_normals(); + } const float2 *uv_map = static_cast( CustomData_get_layer(&mesh->loop_data, CD_PROP_FLOAT2)); -- 2.30.2 From 49d3dddae8faf3255ba158b8a67bd28ea2d42460 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 21 Aug 2023 11:38:34 -0400 Subject: [PATCH 47/85] Fixes --- source/blender/blenkernel/intern/mesh_legacy_convert.cc | 8 ++++++++ source/blender/blenloader/intern/versioning_common.cc | 2 +- .../draw/intern/draw_cache_extract_mesh_render_data.cc | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index bb07833e325..c2b2b532344 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -37,6 +37,7 @@ #include "BKE_multires.hh" #include "BKE_node.hh" #include "BKE_node_runtime.hh" +#include "BKE_node_tree_update.h" #include "BLT_translation.h" @@ -2178,6 +2179,7 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) } if (!auto_smooth_node_tree) { auto_smooth_node_tree = add_auto_smooth_node_tree(bmain); + BKE_ntree_update_main_tree(&bmain, auto_smooth_node_tree, nullptr); } auto *md = reinterpret_cast(BKE_modifier_new(eModifierType_Nodes)); STRNCPY(md->modifier.name, DATA_("Auto Smooth")); @@ -2197,7 +2199,13 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); + auto *ui_data = reinterpret_cast(IDP_ui_data_ensure(angle_prop)); + ui_data->base.rna_subtype = PROP_ANGLE; IDP_AddToGroup(md->settings.properties, angle_prop); + IDP_AddToGroup(md->settings.properties, + bke::idprop::create(DATA_("Input_1_use_attribute"), 0).release()); + IDP_AddToGroup(md->settings.properties, + bke::idprop::create(DATA_("Input_1_attribute_name"), "").release()); } } diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index 1471e8631cb..bff8a273b4c 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -527,7 +527,7 @@ void do_versions_after_setup(Main *new_bmain, BlendFileReadReport *reports) BKE_lib_override_library_main_hierarchy_root_ensure(new_bmain); } - if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 16)) { + if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 17)) { BKE_main_mesh_legacy_convert_auto_smooth(*new_bmain); } } diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index 810886aa740..e394526f153 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -343,7 +343,7 @@ void mesh_render_data_update_normals(MeshRenderData &mr, const eMRDataType data_ mr.face_normals = mr.me->face_normals(); } if (((data_flag & MR_DATA_LOOP_NOR) && - mr.me->normal_domain_all_info() == ATTR_DOMAIN_CORNER) || + ELEM(mr.me->normal_domain_all_info(), ATTR_DOMAIN_CORNER, ATTR_DOMAIN_FACE)) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { mr.loop_normals = mr.me->corner_normals(); -- 2.30.2 From 7577e5d0ae94d0a6ce808b1e18c7a34dab4171d4 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 25 Aug 2023 17:16:17 -0400 Subject: [PATCH 48/85] Bump file subversion --- source/blender/blenloader/intern/versioning_common.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index bff8a273b4c..a9c3b948329 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -527,7 +527,7 @@ void do_versions_after_setup(Main *new_bmain, BlendFileReadReport *reports) BKE_lib_override_library_main_hierarchy_root_ensure(new_bmain); } - if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 17)) { + if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 19)) { BKE_main_mesh_legacy_convert_auto_smooth(*new_bmain); } } -- 2.30.2 From 0c0a5c95261153527b918d227ccfb408de7b64de Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 25 Aug 2023 17:20:09 -0400 Subject: [PATCH 49/85] Use shared cache for corner normals --- .../blender/blenkernel/intern/mesh_normals.cc | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 6fe496f0f00..0d81ef9c8f4 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -387,34 +387,19 @@ blender::Span Mesh::face_normals() const blender::Span Mesh::corner_normals() const { using namespace blender; - using namespace blender::bke; - if (!this->runtime->corner_normals_dirty) { - BLI_assert(this->runtime->corner_normals.size() == this->totloop); - return this->runtime->corner_normals; - } - - const Span vert_normals = this->vert_normals(); - const Span face_normals = this->face_normals(); - std::lock_guard lock{this->runtime->normals_mutex}; - if (!this->runtime->corner_normals_dirty) { - BLI_assert(this->runtime->corner_normals.size() == this->totloop); - return this->runtime->corner_normals; - } - - /* Isolate task because a mutex is locked and computing normals is multi-threaded. */ - threading::isolate_task([&]() { + this->runtime->corner_normals_cache.ensure([&](Vector &r_data) { const OffsetIndices faces = this->faces(); - this->runtime->corner_normals.reinitialize(this->totloop); - MutableSpan corner_normals = this->runtime->corner_normals; + r_data.reinitialize(faces.total_size()); switch (this->normal_domain_all_info()) { case ATTR_DOMAIN_POINT: { - array_utils::gather(vert_normals, this->corner_verts(), corner_normals); + array_utils::gather(this->vert_normals(), this->corner_verts(), r_data.as_mutable_span()); break; } case ATTR_DOMAIN_FACE: { - threading::parallel_for(face_normals.index_range(), 1024, [&](const IndexRange range) { + const Span face_normals = this->face_normals(); + threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { - corner_normals.slice(faces[i]).fill(face_normals[i]); + r_data.as_mutable_span().slice(faces[i]).fill(face_normals[i]); } }); break; @@ -432,23 +417,20 @@ blender::Span Mesh::corner_normals() const this->corner_verts(), this->corner_edges(), {}, - vert_normals, - face_normals, + this->vert_normals(), + this->face_normals(), sharp_edges, sharp_faces, custom_normals, nullptr, - this->runtime->corner_normals); + r_data); break; } default: BLI_assert_unreachable(); } - - this->runtime->corner_normals_dirty = false; }); - - return this->runtime->corner_normals; + return this->runtime->corner_normals_cache.data(); } void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, -- 2.30.2 From 5d336ebbdfffad9a71d93ea85ae8d14a996e8876 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 25 Aug 2023 21:48:48 -0400 Subject: [PATCH 50/85] Fix geometry component --- source/blender/blenkernel/intern/geometry_component_mesh.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 6346bd8eabc..036f01184f6 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -861,7 +861,7 @@ static void tag_component_positions_changed(void *owner) static void tag_component_corner_normals_dirty(void *owner) { if (Mesh *mesh = static_cast(owner)) { - mesh->runtime->corner_normals_dirty = true; + mesh->runtime->corner_normals_cache.tag_dirty(); } } -- 2.30.2 From 693875c078fefdf141747a64643a1e5cb5947fc7 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 25 Aug 2023 21:50:46 -0400 Subject: [PATCH 51/85] Move "add split normals" back to geometry data panel --- scripts/startup/bl_ui/properties_data_mesh.py | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/scripts/startup/bl_ui/properties_data_mesh.py b/scripts/startup/bl_ui/properties_data_mesh.py index 507de248ce0..265dd508fa4 100644 --- a/scripts/startup/bl_ui/properties_data_mesh.py +++ b/scripts/startup/bl_ui/properties_data_mesh.py @@ -178,23 +178,6 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel): layout.template_ID(space, "pin_id") -class DATA_PT_normals(MeshButtonsPanel, Panel): - bl_label = "Normals" - bl_options = {'DEFAULT_CLOSED'} - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'} - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - - mesh = context.mesh - - if mesh.has_custom_normals: - layout.operator("mesh.customdata_custom_splitnormals_clear", icon='X') - else: - layout.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') - - class DATA_PT_texture_space(MeshButtonsPanel, Panel): bl_label = "Texture Space" bl_options = {'DEFAULT_CLOSED'} @@ -434,6 +417,11 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel): col.operator("mesh.customdata_mask_clear", icon='X') col.operator("mesh.customdata_skin_clear", icon='X') + if me.has_custom_normals: + col.operator("mesh.customdata_custom_splitnormals_clear", icon='X') + else: + col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') + class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'} @@ -655,7 +643,6 @@ classes = ( DATA_PT_uv_texture, DATA_PT_vertex_colors, DATA_PT_mesh_attributes, - DATA_PT_normals, DATA_PT_texture_space, DATA_PT_remesh, DATA_PT_customdata, -- 2.30.2 From e4b0d32b2378367305bd0dbe62f7a10e2b50f793 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 28 Aug 2023 23:39:45 -0400 Subject: [PATCH 52/85] Separate old auto smooth operator option to "shade_smooth_by_angle" operator --- scripts/startup/bl_ui/space_view3d.py | 6 +-- source/blender/editors/mesh/mesh_data.cc | 1 - source/blender/editors/object/object_edit.cc | 40 +++++++++---------- source/blender/editors/object/object_intern.h | 1 + source/blender/editors/object/object_ops.cc | 1 + 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 2dc86fbb9cb..1a3ded89afb 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -2573,7 +2573,7 @@ class VIEW3D_MT_object(Menu): layout.separator() layout.operator("object.shade_smooth") - layout.operator("object.shade_smooth", text="Shade Auto Smooth").use_auto_smooth = True + layout.operator("object.shade_smooth_by_angle") layout.operator("object.shade_flat") layout.separator() @@ -2817,8 +2817,8 @@ class VIEW3D_MT_object_context_menu(Menu): if obj is not None: if obj.type in {'MESH', 'CURVE', 'SURFACE'}: layout.operator("object.shade_smooth") - layout.operator("object.shade_smooth", text="Shade Auto Smooth").use_auto_smooth = True - layout.operator("object.shade_flat", text="Shade Flat") + layout.operator("object.shade_smooth_by_angle") + layout.operator("object.shade_flat") layout.separator() diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 7b546e7a602..0b758f89111 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1125,7 +1125,6 @@ void ED_mesh_split_faces(Mesh *mesh) { using namespace blender; const OffsetIndices polys = mesh->faces(); - const Span corner_verts = mesh->corner_verts(); const Span corner_edges = mesh->corner_edges(); const bke::AttributeAccessor attributes = mesh->attributes(); const VArray mesh_sharp_edges = *attributes.lookup_or_default( diff --git a/source/blender/editors/object/object_edit.cc b/source/blender/editors/object/object_edit.cc index 8bd9a04f39d..cc8ac1f68de 100644 --- a/source/blender/editors/object/object_edit.cc +++ b/source/blender/editors/object/object_edit.cc @@ -1556,6 +1556,7 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot) static int shade_smooth_exec(bContext *C, wmOperator *op) { const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth"); + const bool use_smooth_by_angle = STREQ(op->idname, "OBJECT_OT_shade_smooth_by_angle"); bool changed_multi = false; bool has_linked_data = false; @@ -1604,12 +1605,11 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) bool changed = false; if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(static_cast(ob->data), use_smooth); - if (use_smooth) { - const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth"); - if (use_auto_smooth) { - const float auto_smooth_angle = RNA_float_get(op->ptr, "auto_smooth_angle"); - BKE_mesh_sharp_edges_set_from_angle(static_cast(ob->data), auto_smooth_angle); + BKE_mesh_smooth_flag_set(static_cast(ob->data), use_smooth || use_smooth_by_angle); + if (use_smooth || use_smooth_by_angle) { + if (use_smooth_by_angle) { + const float angle = RNA_float_get(op->ptr, "angle"); + BKE_mesh_sharp_edges_set_from_angle(static_cast(ob->data), angle); } } BKE_mesh_batch_cache_dirty_tag(static_cast(ob->data), BKE_MESH_BATCH_DIRTY_ALL); @@ -1684,25 +1684,25 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} - /* properties */ - PropertyRNA *prop; +void OBJECT_OT_shade_smooth_by_angle(wmOperatorType *ot) +{ + ot->name = "Shade Smooth by Angle"; + ot->description = + "Set the sharpness of mesh edges based on the angle between the neighboring faces"; + ot->idname = "OBJECT_OT_shade_smooth_by_angle"; - prop = RNA_def_boolean( - ot->srna, - "use_auto_smooth", - false, - "Auto Smooth", - "Enable automatic smooth based on smooth/sharp faces/edges and angle between faces"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->poll = shade_poll; + ot->exec = shade_smooth_exec; - prop = RNA_def_property(ot->srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE); + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + PropertyRNA *prop = RNA_def_property(ot->srna, "angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f)); RNA_def_property_float_default(prop, DEG2RADF(30.0f)); - RNA_def_property_ui_text(prop, - "Angle", - "Maximum angle between face normals that will be considered as smooth " - "(unused if custom split normals data are available)"); + RNA_def_property_ui_text( + prop, "Angle", "Maximum angle between face normals that will be considered as smooth"); } /** \} */ diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index dd24e8804d1..841075f64de 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -83,6 +83,7 @@ void OBJECT_OT_mode_set_with_submode(struct wmOperatorType *ot); void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot); void OBJECT_OT_posemode_toggle(struct wmOperatorType *ot); void OBJECT_OT_shade_smooth(struct wmOperatorType *ot); +void OBJECT_OT_shade_smooth_by_angle(struct wmOperatorType *ot); void OBJECT_OT_shade_flat(struct wmOperatorType *ot); void OBJECT_OT_paths_calculate(struct wmOperatorType *ot); void OBJECT_OT_paths_update(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.cc b/source/blender/editors/object/object_ops.cc index 998e21ff1d9..35f0095de30 100644 --- a/source/blender/editors/object/object_ops.cc +++ b/source/blender/editors/object/object_ops.cc @@ -43,6 +43,7 @@ void ED_operatortypes_object() WM_operatortype_append(OBJECT_OT_editmode_toggle); WM_operatortype_append(OBJECT_OT_posemode_toggle); WM_operatortype_append(OBJECT_OT_shade_smooth); + WM_operatortype_append(OBJECT_OT_shade_smooth_by_angle); WM_operatortype_append(OBJECT_OT_shade_flat); WM_operatortype_append(OBJECT_OT_paths_calculate); WM_operatortype_append(OBJECT_OT_paths_update); -- 2.30.2 From 13c54a9aac40988c1483ef3e074e6b02d2232be8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 30 Aug 2023 08:33:33 -0400 Subject: [PATCH 53/85] Fix for new node tree interface UI --- .../blender/blenkernel/intern/mesh_legacy_convert.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 7c39b7e51b9..ba1daf113eb 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2088,9 +2088,13 @@ static bNodeTree *add_auto_smooth_node_tree(Main &bmain) { bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth"), "GeometryNodeTree"); - ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketGeometry", DATA_("Geometry")); - ntreeAddSocketInterface(node_tree, SOCK_IN, "NodeSocketFloatAngle", DATA_("Angle")); - ntreeAddSocketInterface(node_tree, SOCK_OUT, "NodeSocketGeometry", DATA_("Geometry")); + node_tree->tree_interface.add_socket(DATA_("Geometry"), + "", + "NodeSocketGeometry", + NODE_INTERFACE_SOCKET_INPUT | NODE_INTERFACE_SOCKET_OUTPUT, + nullptr); + node_tree->tree_interface.add_socket( + DATA_("Angle"), "", "NodeSocketFloatAngle", NODE_INTERFACE_SOCKET_INPUT, nullptr); bNode *group_input = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_INPUT); group_input->locx = -380.0f; @@ -2205,4 +2209,4 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) } } -/** \} */ \ No newline at end of file +/** \} */ -- 2.30.2 From be5de2b28d38bcc8c380712664445909b50ce43c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 30 Aug 2023 08:53:50 -0400 Subject: [PATCH 54/85] Replace incorrect / unhelpful comment --- source/blender/blenkernel/intern/DerivedMesh.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 55d84d8a921..cb392e95859 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -466,11 +466,7 @@ static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *me } else { if (sculpt_dyntopo == false) { - /* without this, drawing ngon tri's faces will show ugly tessellated face - * normals and will also have to calculate normals on the fly, try avoid - * this where possible since calculating face normals isn't fast, - * note that this isn't a problem for subsurf (only quads) or edit-mode - * which deals with drawing differently. */ + /* Eager normal calculation can potentially be faster than deferring the to drawing code. */ if (domain == ATTR_DOMAIN_FACE) { mesh_final->face_normals(); } -- 2.30.2 From bc3bd71f56aea27f1c38be456e600d6a624cc0d4 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 30 Aug 2023 12:45:55 -0400 Subject: [PATCH 55/85] Fix issues with wrapper system and deferred normal calculation --- .../blender/blenkernel/intern/DerivedMesh.cc | 47 +++++-------------- .../blender/blenkernel/intern/mesh_wrapper.cc | 9 ++-- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index cb392e95859..035862ce117 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -1058,42 +1058,19 @@ bool editbmesh_modifier_is_enabled(const Scene *scene, static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final) { - const eAttrDomain domain = eAttrDomain(mesh_final->normal_domain_all_info()); - - SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; - if (subsurf_runtime_data) { - subsurf_runtime_data->calc_loop_normals = domain == ATTR_DOMAIN_CORNER; - } - - if (domain == ATTR_DOMAIN_CORNER) { - /* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the - * wrapper is generated. */ - if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { - mesh_final->corner_normals(); - } - } - else { - switch (mesh_final->runtime->wrapper_type) { - case ME_WRAPPER_TYPE_SUBD: - break; - case ME_WRAPPER_TYPE_MDATA: - /* Same as #mesh_calc_modifiers. */ - if (domain == ATTR_DOMAIN_FACE) { - mesh_final->face_normals(); - } - else if (domain == ATTR_DOMAIN_FACE) { - mesh_final->vert_normals(); - } - break; - case ME_WRAPPER_TYPE_BMESH: { - BMEditMesh *em = mesh_final->edit_mesh; - blender::bke::EditMeshData *emd = mesh_final->runtime->edit_data; - if (!emd->vertexCos.is_empty()) { - BKE_editmesh_cache_ensure_vert_normals(em, emd); - BKE_editmesh_cache_ensure_face_normals(em, emd); - } - return; + switch (mesh_final->runtime->wrapper_type) { + case ME_WRAPPER_TYPE_SUBD: + case ME_WRAPPER_TYPE_MDATA: + mesh_calc_modifier_final_normals(false, mesh_final); + break; + case ME_WRAPPER_TYPE_BMESH: { + BMEditMesh *em = mesh_final->edit_mesh; + blender::bke::EditMeshData *emd = mesh_final->runtime->edit_data; + if (!emd->vertexCos.is_empty()) { + BKE_editmesh_cache_ensure_vert_normals(em, emd); + BKE_editmesh_cache_ensure_face_normals(em, emd); } + return; } } } diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index aca8b4e8cfe..ebfd6b6c268 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -130,16 +130,17 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me) me->vert_positions_for_write().copy_from(edit_data->vertexCos); me->runtime->is_original_bmesh = false; } + + if (me->runtime->wrapper_type_finalize) { + BKE_mesh_wrapper_deferred_finalize_mdata(me); + } + MEM_delete(me->runtime->edit_data); me->runtime->edit_data = nullptr; break; } } - if (me->runtime->wrapper_type_finalize) { - BKE_mesh_wrapper_deferred_finalize_mdata(me); - } - /* Keep type assignment last, so that read-only access only uses the mdata code paths after all * the underlying data has been initialized. */ me->runtime->wrapper_type = ME_WRAPPER_TYPE_MDATA; -- 2.30.2 From 37a06cbffc005b62e120711c83af75643d311b5c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 30 Aug 2023 13:52:25 -0400 Subject: [PATCH 56/85] Check whether BMesh loop normals are required before accessing --- .../draw_cache_extract_mesh_render_data.cc | 108 +++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index e394526f153..13769ac8564 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -11,7 +11,9 @@ #include "MEM_guardedalloc.h" #include "BLI_array.hh" +#include "BLI_array_utils.hh" #include "BLI_enumerable_thread_specific.hh" +#include "BLI_index_mask.hh" #include "BLI_math_matrix.h" #include "BLI_task.hh" @@ -334,6 +336,108 @@ void mesh_render_data_update_looptris(MeshRenderData &mr, } } +namespace blender { + +class VArrayImpl_For_SharpFace : public VArrayImpl { + const BMFace *const *faces_; + + public: + VArrayImpl_For_SharpFace(const Span faces) + : VArrayImpl(faces.size()), faces_(faces.data()) + { + } + bool get(const int64_t index) const final + { + return !BM_elem_flag_test(faces_[index], BM_ELEM_SMOOTH); + } + void materialize(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + } + void materialize_to_uninitialized(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + } + void materialize_compressed(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); + } + void materialize_compressed_to_uninitialized(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); + } +}; + +class VArrayImpl_For_SharpEdge : public VArrayImpl { + const BMEdge *const *edges_; + + public: + VArrayImpl_For_SharpEdge(const Span edges) + : VArrayImpl(edges.size()), edges_(edges.data()) + { + } + bool get(const int64_t index) const final + { + return !BM_elem_flag_test(edges_[index], BM_ELEM_SMOOTH); + } + void materialize(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + } + void materialize_to_uninitialized(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + } + void materialize_compressed(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); + } + void materialize_compressed_to_uninitialized(const IndexMask &mask, bool *dst) const override + { + mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); + } +}; + +} // namespace blender + +/** + * Returns whether loop normals are required because of mixed sharp and smooth flags. + * Similar to #Mesh::normal_domain_all_info(). + */ +static bool bm_loop_normals_required(BMesh *bm) +{ + using namespace blender; + using namespace blender::bke; + if (bm->totface == 0) { + return false; + } + + if (CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) { + return true; + } + + BM_mesh_elem_table_ensure(bm, BM_FACE); + const VArrayImpl_For_SharpFace sharp_faces({bm->ftable, bm->totface}); + const array_utils::BooleanMix face_mix = array_utils::booleans_mix_calc(VArray(&sharp_faces)); + if (face_mix == array_utils::BooleanMix::AllTrue) { + return false; + } + + BM_mesh_elem_table_ensure(bm, BM_EDGE); + const VArrayImpl_For_SharpEdge sharp_edges({bm->etable, bm->totedge}); + const array_utils::BooleanMix edge_mix = array_utils::booleans_mix_calc(VArray(&sharp_edges)); + if (edge_mix == array_utils::BooleanMix::AllTrue) { + return false; + } + + if (edge_mix == array_utils::BooleanMix::AllFalse && + face_mix == array_utils::BooleanMix::AllFalse) { + return false; + } + + return true; +} + void mesh_render_data_update_normals(MeshRenderData &mr, const eMRDataType data_flag) { if (mr.extract_type != MR_EXTRACT_BMESH) { @@ -354,7 +458,9 @@ void mesh_render_data_update_normals(MeshRenderData &mr, const eMRDataType data_ if (data_flag & MR_DATA_POLY_NOR) { /* Use #BMFace.no instead. */ } - if (((data_flag & MR_DATA_LOOP_NOR)) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { + if (((data_flag & MR_DATA_LOOP_NOR) && bm_loop_normals_required(mr.bm)) || + (data_flag & MR_DATA_TAN_LOOP_NOR)) + { const float(*vert_coords)[3] = nullptr; const float(*vert_normals)[3] = nullptr; -- 2.30.2 From e2fc081882add2c66db8e53661247c034d8b2a4e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 30 Aug 2023 13:52:31 -0400 Subject: [PATCH 57/85] Reduce duplication --- .../draw/intern/draw_cache_extract_mesh_render_data.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index 13769ac8564..4591ee07204 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -356,7 +356,7 @@ class VArrayImpl_For_SharpFace : public VArrayImpl { } void materialize_to_uninitialized(const IndexMask &mask, bool *dst) const override { - mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + materialize(mask, dst); } void materialize_compressed(const IndexMask &mask, bool *dst) const override { @@ -364,7 +364,7 @@ class VArrayImpl_For_SharpFace : public VArrayImpl { } void materialize_compressed_to_uninitialized(const IndexMask &mask, bool *dst) const override { - mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); + materialize_compressed(mask, dst); } }; @@ -386,7 +386,7 @@ class VArrayImpl_For_SharpEdge : public VArrayImpl { } void materialize_to_uninitialized(const IndexMask &mask, bool *dst) const override { - mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + materialize(mask, dst); } void materialize_compressed(const IndexMask &mask, bool *dst) const override { @@ -394,7 +394,7 @@ class VArrayImpl_For_SharpEdge : public VArrayImpl { } void materialize_compressed_to_uninitialized(const IndexMask &mask, bool *dst) const override { - mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); + materialize_compressed(mask, dst); } }; -- 2.30.2 From db77fdd44be38569f28bcabfc82b91eafed29831 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 30 Aug 2023 14:03:14 -0400 Subject: [PATCH 58/85] Revert changes in BMesh normal calculation Now the changes are as simpe as possible-- in the entry point we just disable the tagging with the old magic number --- .../bmesh/intern/bmesh_mesh_normals.cc | 90 ++++++++++++++++--- 1 file changed, 77 insertions(+), 13 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.cc b/source/blender/bmesh/intern/bmesh_mesh_normals.cc index 5bfc12a9fd8..bd7d8fc90e5 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.cc @@ -876,6 +876,7 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors( const short (*clnors_data)[2], const int cd_loop_clnors_offset, const bool do_rebuild, + const float split_angle_cos, /* TLS */ MLoopNorSpaceArray *r_lnors_spacearr, blender::Vector *edge_vectors, @@ -894,6 +895,8 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors( const bool has_clnors = true; LinkNode *loops_of_vert = nullptr; int loops_of_vert_count = 0; + /* When false the caller must have already tagged the edges. */ + const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); /* The loop with the lowest index. */ { @@ -906,6 +909,10 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors( continue; } + if (do_edge_tag) { + bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); + } + do { /* Radial loops. */ if (l_curr->v != v) { continue; @@ -989,6 +996,7 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( const float (*fnos)[3], float (*r_lnos)[3], const bool do_rebuild, + const float split_angle_cos, /* TLS */ MLoopNorSpaceArray *r_lnors_spacearr, blender::Vector *edge_vectors, @@ -997,6 +1005,8 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( { const bool has_clnors = false; const short(*clnors_data)[2] = nullptr; + /* When false the caller must have already tagged the edges. */ + const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); const int cd_loop_clnors_offset = -1; BMEdge *e_curr_iter; @@ -1009,6 +1019,10 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( continue; } + if (do_edge_tag) { + bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); + } + do { /* Radial loops. */ if (l_curr->v != v) { continue; @@ -1061,11 +1075,14 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, MLoopNorSpaceArray *r_lnors_spacearr, const short (*clnors_data)[2], const int cd_loop_clnors_offset, - const bool do_rebuild) + const bool do_rebuild, + const float split_angle_cos) { BMIter fiter; BMFace *f_curr; const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); + /* When false the caller must have already tagged the edges. */ + const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); MLoopNorSpaceArray _lnors_spacearr = {nullptr}; @@ -1104,6 +1121,12 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, } bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); + /* Always tag edges based on winding & sharp edge flag + * (even when the auto-smooth angle doesn't need to be calculated). */ + if (do_edge_tag) { + bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? -1.0f : split_angle_cos, false); + } + /* We now know edges that can be smoothed (they are tagged), * and edges that will be hard (they aren't). * Now, time to generate the normals. @@ -1146,6 +1169,7 @@ struct BMLoopsCalcNormalsWithCoordsData { const short (*clnors_data)[2]; int cd_loop_clnors_offset; bool do_rebuild; + float split_angle_cos; /* Output. */ float (*r_lnos)[3]; @@ -1215,6 +1239,7 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors_fn( data->clnors_data, data->cd_loop_clnors_offset, data->do_rebuild, + data->split_angle_cos, /* Thread local. */ tls_data->lnors_spacearr, tls_data->edge_vectors, @@ -1237,6 +1262,7 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors_fn( data->r_lnos, data->do_rebuild, + data->split_angle_cos, /* Thread local. */ tls_data->lnors_spacearr, tls_data->edge_vectors, @@ -1251,7 +1277,8 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm, MLoopNorSpaceArray *r_lnors_spacearr, const short (*clnors_data)[2], const int cd_loop_clnors_offset, - const bool do_rebuild) + const bool do_rebuild, + const float split_angle_cos) { const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); MLoopNorSpaceArray _lnors_spacearr = {nullptr}; @@ -1302,6 +1329,7 @@ static void bm_mesh_loops_calc_normals__multi_threaded(BMesh *bm, data.clnors_data = clnors_data; data.cd_loop_clnors_offset = cd_loop_clnors_offset; data.do_rebuild = do_rebuild; + data.split_angle_cos = split_angle_cos; BM_iter_parallel(bm, BM_VERTS_OF_MESH, @@ -1324,15 +1352,30 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, MLoopNorSpaceArray *r_lnors_spacearr, const short (*clnors_data)[2], const int cd_loop_clnors_offset, - const bool do_rebuild) + const bool do_rebuild, + const float split_angle_cos) { if (bm->totloop < BM_OMP_LIMIT) { - bm_mesh_loops_calc_normals__single_threaded( - bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); + bm_mesh_loops_calc_normals__single_threaded(bm, + vcos, + fnos, + r_lnos, + r_lnors_spacearr, + clnors_data, + cd_loop_clnors_offset, + do_rebuild, + split_angle_cos); } else { - bm_mesh_loops_calc_normals__multi_threaded( - bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); + bm_mesh_loops_calc_normals__multi_threaded(bm, + vcos, + fnos, + r_lnos, + r_lnors_spacearr, + clnors_data, + cd_loop_clnors_offset, + do_rebuild, + split_angle_cos); } } @@ -1551,8 +1594,15 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm, /* Finish computing lnos by accumulating face normals * in each fan of faces defined by sharp edges. */ - bm_mesh_loops_calc_normals( - bm, vcos, fnos, cur_lnors, r_lnors_spacearr, r_clnors_data, cd_loop_clnors_offset, false); + bm_mesh_loops_calc_normals(bm, + vcos, + fnos, + cur_lnors, + r_lnors_spacearr, + r_clnors_data, + cd_loop_clnors_offset, + false, + EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); /* Extract new normals from the data layer if necessary. */ float(*custom_lnors)[3] = new_lnors; @@ -1586,8 +1636,15 @@ static void bm_mesh_loops_custom_normals_set(BMesh *bm, * spacearr/smooth fans matching the given custom lnors. */ BKE_lnor_spacearr_clear(r_lnors_spacearr); - bm_mesh_loops_calc_normals( - bm, vcos, fnos, cur_lnors, r_lnors_spacearr, r_clnors_data, cd_loop_clnors_offset, false); + bm_mesh_loops_calc_normals(bm, + vcos, + fnos, + cur_lnors, + r_lnors_spacearr, + r_clnors_data, + cd_loop_clnors_offset, + false, + EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); } /* And we just have to convert plain object-space custom normals to our @@ -1648,8 +1705,15 @@ void BM_loops_calc_normal_vcos(BMesh *bm, { if (use_split_normals) { - bm_mesh_loops_calc_normals( - bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); + bm_mesh_loops_calc_normals(bm, + vcos, + fnos, + r_lnos, + r_lnors_spacearr, + clnors_data, + cd_loop_clnors_offset, + do_rebuild, + -1.0f); } else { BLI_assert(!r_lnors_spacearr); -- 2.30.2 From 8baa21e981abc9b91489f191bc0d94a71014df48 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 30 Aug 2023 14:12:04 -0400 Subject: [PATCH 59/85] Fix versioning after change in main --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/mesh_legacy_convert.cc | 2 +- source/blender/blenloader/intern/versioning_common.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index c9803ccd4f2..9760b03448e 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 20 +#define BLENDER_FILE_SUBVERSION 21 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index ba1daf113eb..3e6886fbf9c 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2198,7 +2198,7 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) } md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); - IDProperty *angle_prop = bke::idprop::create(DATA_("Input_1"), mesh->smoothresh).release(); + IDProperty *angle_prop = bke::idprop::create(DATA_("Socket_1"), mesh->smoothresh).release(); auto *ui_data = reinterpret_cast(IDP_ui_data_ensure(angle_prop)); ui_data->base.rna_subtype = PROP_ANGLE; IDP_AddToGroup(md->settings.properties, angle_prop); diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index 98f80fa05a0..937022f30f9 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -528,7 +528,7 @@ void do_versions_after_setup(Main *new_bmain, BlendFileReadReport *reports) BKE_lib_override_library_main_hierarchy_root_ensure(new_bmain); } - if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 19)) { + if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 20)) { BKE_main_mesh_legacy_convert_auto_smooth(*new_bmain); } } -- 2.30.2 From 9011eeda95f0ca6f9de892fad32d1ac6c6e8f497 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 1 Sep 2023 08:40:34 -0400 Subject: [PATCH 60/85] Fix after topology cache change in main --- source/blender/blenkernel/intern/mesh.cc | 1 + source/blender/blenkernel/intern/mesh_normals.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index e797b56a7c6..3181b577e25 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1470,6 +1470,7 @@ void BKE_mesh_sharp_edges_set_from_angle(Mesh *me, const float angle) me->corner_verts(), me->corner_edges(), me->face_normals(), + me->corner_to_face_map(), sharp_faces, angle, sharp_edges.span); diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 20e208d621c..11453a0dbd8 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -416,7 +416,7 @@ blender::Span Mesh::corner_normals() const this->faces(), this->corner_verts(), this->corner_edges(), - {}, + this->corner_to_face_map(), this->vert_normals(), this->face_normals(), sharp_edges, -- 2.30.2 From 29d276b7213f33af811a294ccfc44e6ce823bd42 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 1 Sep 2023 08:40:39 -0400 Subject: [PATCH 61/85] Fix obj export --- source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 094e2de7aba..ad82def4796 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -374,7 +374,7 @@ void OBJMesh::store_normal_coords_and_indices() for (int face_index = 0; face_index < export_mesh_->faces_num; ++face_index) { const IndexRange face = mesh_faces_[face_index]; - bool need_per_loop_normals = !corner_normals.is_empty() && !(sharp_faces_[face_index]); + bool need_per_loop_normals = !corner_normals.is_empty() || !(sharp_faces_[face_index]); if (need_per_loop_normals) { for (const int corner : face) { float3 loop_normal; -- 2.30.2 From 08947d2b8e73da0d1e1c450baf9ba87c67e23e3b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 08:01:47 -0400 Subject: [PATCH 62/85] Only show "smooth by angle" operator when active object is a mesh --- scripts/startup/bl_ui/space_view3d.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 00b5abf2cdc..0a24d4465f4 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -2573,7 +2573,8 @@ class VIEW3D_MT_object(Menu): layout.separator() layout.operator("object.shade_smooth") - layout.operator("object.shade_smooth_by_angle") + if context.object and context.object.type == 'MESH': + layout.operator("object.shade_smooth_by_angle") layout.operator("object.shade_flat") layout.separator() @@ -2817,7 +2818,8 @@ class VIEW3D_MT_object_context_menu(Menu): if obj is not None: if obj.type in {'MESH', 'CURVE', 'SURFACE'}: layout.operator("object.shade_smooth") - layout.operator("object.shade_smooth_by_angle") + if obj.type == 'MESH': + layout.operator("object.shade_smooth_by_angle") layout.operator("object.shade_flat") layout.separator() -- 2.30.2 From b6d68f2345b3957e5a95c0bed3a178272e55411c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 08:02:51 -0400 Subject: [PATCH 63/85] Fix mistaken attribute domain check --- source/blender/blenkernel/intern/DerivedMesh.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 0497d1b3bfd..0ebcab9b968 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -470,7 +470,7 @@ static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *me if (domain == ATTR_DOMAIN_FACE) { mesh_final->face_normals(); } - else if (domain == ATTR_DOMAIN_FACE) { + else if (domain == ATTR_DOMAIN_POINT) { mesh_final->vert_normals(); } } -- 2.30.2 From 25f7a516fb54e68c26ce19ea165a267eb36aea6f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 08:05:42 -0400 Subject: [PATCH 64/85] Adjust "edge to loop map" name and add comment --- .../blender/blenkernel/intern/mesh_normals.cc | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 11453a0dbd8..aef5a852937 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -849,12 +849,16 @@ static void mesh_edges_sharp_tag(const OffsetIndices faces, } } -static void build_edge_to_loop_map(const OffsetIndices faces, - const Span corner_verts, - const Span corner_edges, - const Span sharp_faces, - const Span sharp_edges, - MutableSpan edge_to_loops) +/** + * Builds a simplified map from edges to face corners, marking special values when + * it encounters sharp edges or borders between faces with flipped winding orders. + */ +static void build_edge_to_loop_map_with_flip_and_sharp(const OffsetIndices faces, + const Span corner_verts, + const Span corner_edges, + const Span sharp_faces, + const Span sharp_edges, + MutableSpan edge_to_loops) { auto face_is_smooth = [&](const int face_i) { return sharp_faces.is_empty() || !sharp_faces[face_i]; @@ -1370,12 +1374,13 @@ void normals_calc_loop(const Span vert_positions, array_utils::gather(vert_normals, corner_verts, r_loop_normals, 1024); /* This first loop check which edges are actually smooth, and compute edge vectors. */ - build_edge_to_loop_map(faces, - corner_verts, - corner_edges, - Span(sharp_faces, sharp_faces ? faces.size() : 0), - Span(sharp_edges, sharp_edges ? edges.size() : 0), - edge_to_loops); + build_edge_to_loop_map_with_flip_and_sharp( + faces, + corner_verts, + corner_edges, + Span(sharp_faces, sharp_faces ? faces.size() : 0), + Span(sharp_edges, sharp_edges ? edges.size() : 0), + edge_to_loops); Vector single_corners; Vector fan_corners; -- 2.30.2 From 1f9d3596b7d449fd7233b529b7ad2ec84045eb29 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 08:11:54 -0400 Subject: [PATCH 65/85] Add legacy suffix to flag and float in DNA --- source/blender/blenkernel/intern/mesh_legacy_convert.cc | 5 +++-- source/blender/blenloader/intern/versioning_270.cc | 4 ++-- source/blender/blenloader/intern/versioning_defaults.cc | 2 +- source/blender/blenloader/intern/versioning_legacy.cc | 2 +- source/blender/makesdna/DNA_mesh_types.h | 4 ++-- source/blender/makesdna/intern/dna_rename_defs.h | 1 + 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 79132340b19..80724442260 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2172,7 +2172,7 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) continue; } Mesh *mesh = static_cast(object->data); - if (!(mesh->flag & ME_AUTOSMOOTH)) { + if (!(mesh->flag & ME_AUTOSMOOTH_LEGACY)) { continue; } if (CustomData_has_layer(&mesh->loop_data, CD_CUSTOMLOOPNORMAL)) { @@ -2199,7 +2199,8 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) } md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release(); - IDProperty *angle_prop = bke::idprop::create(DATA_("Socket_1"), mesh->smoothresh).release(); + IDProperty *angle_prop = + bke::idprop::create(DATA_("Socket_1"), mesh->smoothresh_legacy).release(); auto *ui_data = reinterpret_cast(IDP_ui_data_ensure(angle_prop)); ui_data->base.rna_subtype = PROP_ANGLE; IDP_AddToGroup(md->settings.properties, angle_prop); diff --git a/source/blender/blenloader/intern/versioning_270.cc b/source/blender/blenloader/intern/versioning_270.cc index c9194cbe90b..0ca4833c044 100644 --- a/source/blender/blenloader/intern/versioning_270.cc +++ b/source/blender/blenloader/intern/versioning_270.cc @@ -521,9 +521,9 @@ void blo_do_versions_270(FileData *fd, Library * /*lib*/, Main *bmain) } if (!MAIN_VERSION_FILE_ATLEAST(bmain, 270, 2)) { - /* Mesh smoothresh deg->rad. */ + /* Mesh smoothresh_legacy deg->rad. */ LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) { - me->smoothresh = DEG2RADF(me->smoothresh); + me->smoothresh_legacy = DEG2RADF(me->smoothresh_legacy); } } diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index 143b0ace3cf..d602e722d13 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -571,7 +571,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) { /* Match default for new meshes. */ - mesh->smoothresh = DEG2RADF(30); + mesh->smoothresh_legacy = DEG2RADF(30); /* Match voxel remesher options for all existing meshes in templates. */ mesh->flag |= ME_REMESH_REPROJECT_VOLUME | ME_REMESH_REPROJECT_PAINT_MASK | ME_REMESH_REPROJECT_SCULPT_FACE_SETS | ME_REMESH_REPROJECT_VERTEX_COLORS; diff --git a/source/blender/blenloader/intern/versioning_legacy.cc b/source/blender/blenloader/intern/versioning_legacy.cc index 701437a0795..7f86bf60985 100644 --- a/source/blender/blenloader/intern/versioning_legacy.cc +++ b/source/blender/blenloader/intern/versioning_legacy.cc @@ -635,7 +635,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) if (bmain->versionfile <= 164) { Mesh *me = static_cast(bmain->meshes.first); while (me) { - me->smoothresh = 30; + me->smoothresh_legacy = 30; me = static_cast(me->id.next); } } diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 1ca2f8706ca..c228189fa99 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -149,7 +149,7 @@ typedef struct Mesh { /** Mostly more flags used when editing or displaying the mesh. */ uint16_t flag; - float smoothresh DNA_DEPRECATED; + float smoothresh_legacy DNA_DEPRECATED; /** Per-mesh settings for voxel remesh. */ float remesh_voxel_size; @@ -438,7 +438,7 @@ enum { ME_FLAG_DEPRECATED_2 = 1 << 2, /* deprecated */ ME_FLAG_UNUSED_3 = 1 << 3, /* cleared */ ME_FLAG_UNUSED_4 = 1 << 4, /* cleared */ - ME_AUTOSMOOTH = 1 << 5, /* deprecated */ + ME_AUTOSMOOTH_LEGACY = 1 << 5, /* deprecated */ ME_FLAG_UNUSED_6 = 1 << 6, /* cleared */ ME_FLAG_UNUSED_7 = 1 << 7, /* cleared */ ME_REMESH_REPROJECT_VERTEX_COLORS = 1 << 8, diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index 3349879a804..d86a4a52e21 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -110,6 +110,7 @@ DNA_STRUCT_RENAME_ELEM(Mesh, ldata, loop_data) DNA_STRUCT_RENAME_ELEM(Mesh, pdata, face_data) DNA_STRUCT_RENAME_ELEM(Mesh, poly_offset_indices, face_offset_indices) DNA_STRUCT_RENAME_ELEM(Mesh, size, texspace_size) +DNA_STRUCT_RENAME_ELEM(Mesh, smoothresh, smoothresh_legacy) DNA_STRUCT_RENAME_ELEM(Mesh, texflag, texspace_flag) DNA_STRUCT_RENAME_ELEM(Mesh, totface, totface_legacy) DNA_STRUCT_RENAME_ELEM(Mesh, totpoly, faces_num) -- 2.30.2 From c3fa88c1f2e77c8542553a4b43217ed711e223da Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 16:21:47 -0400 Subject: [PATCH 66/85] Rename `normal_domain_all_info` to `normals_domain` --- intern/cycles/blender/mesh.cpp | 4 ++-- intern/cycles/blender/util.h | 4 ++-- source/blender/blenkernel/intern/DerivedMesh.cc | 2 +- source/blender/blenkernel/intern/mesh_normals.cc | 4 ++-- source/blender/blenkernel/intern/shrinkwrap.cc | 2 +- source/blender/blenkernel/intern/subdiv_modifier.cc | 2 +- .../draw/intern/draw_cache_extract_mesh_render_data.cc | 4 ++-- source/blender/draw/intern/draw_cache_impl_subdivision.cc | 2 +- source/blender/editors/object/object_bake_api.cc | 2 +- source/blender/io/alembic/exporter/abc_writer_mesh.cc | 2 +- source/blender/io/collada/GeometryExporter.cpp | 2 +- source/blender/io/usd/hydra/mesh.cc | 2 +- source/blender/io/usd/intern/usd_writer_mesh.cc | 2 +- .../blender/io/wavefront_obj/exporter/obj_export_mesh.cc | 2 +- source/blender/makesdna/DNA_mesh_types.h | 4 ++-- source/blender/makesrna/intern/rna_mesh.cc | 8 ++++---- source/blender/modifiers/intern/MOD_multires.cc | 2 +- .../geometry/nodes/node_geo_distribute_points_on_faces.cc | 2 +- 18 files changed, 26 insertions(+), 26 deletions(-) diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index df7b3c53056..c8c90c86030 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -1045,8 +1045,8 @@ static void create_mesh(Scene *scene, const int polys_num = b_mesh.polygons.length(); int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length(); const int numcorners = b_mesh.loops.length(); - bool use_loop_normals = b_mesh.normal_domain_all_info() == - BL::Mesh::normal_domain_all_info_CORNER && + bool use_loop_normals = b_mesh.normals_domain() == + BL::Mesh::normals_domain_CORNER && (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK); /* If no faces, create empty mesh. */ diff --git a/intern/cycles/blender/util.h b/intern/cycles/blender/util.h index 8e9724ed429..9dba6b5ae7a 100644 --- a/intern/cycles/blender/util.h +++ b/intern/cycles/blender/util.h @@ -93,7 +93,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, * Also in edit mode do we need to make a copy, to ensure data layers like * UV are not empty. */ if (mesh.is_editmode() || - (mesh.normal_domain_all_info() == BL::Mesh::normal_domain_all_info_CORNER && + (mesh.normals_domain() == BL::Mesh::normals_domain_CORNER && subdivision_type == Mesh::SUBDIVISION_NONE)) { BL::Depsgraph depsgraph(PointerRNA_NULL); @@ -119,7 +119,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, #endif if ((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) { - if (mesh.normal_domain_all_info() == BL::Mesh::normal_domain_all_info_CORNER) { + if (mesh.normals_domain() == BL::Mesh::normals_domain_CORNER) { mesh.split_faces(); } diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 0ebcab9b968..52900a79085 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -449,7 +449,7 @@ static void add_orco_mesh( static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *mesh_final) { - const eAttrDomain domain = eAttrDomain(mesh_final->normal_domain_all_info()); + const eAttrDomain domain = eAttrDomain(mesh_final->normals_domain()); /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index aef5a852937..48bd3fcf49b 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -299,7 +299,7 @@ static void normals_calc_faces_and_verts(const Span positions, /** \name Mesh Normal Calculation * \{ */ -int Mesh::normal_domain_all_info() const +int Mesh::normals_domain() const { using namespace blender; using namespace blender::bke; @@ -390,7 +390,7 @@ blender::Span Mesh::corner_normals() const this->runtime->corner_normals_cache.ensure([&](Vector &r_data) { const OffsetIndices faces = this->faces(); r_data.reinitialize(faces.total_size()); - switch (this->normal_domain_all_info()) { + switch (this->normals_domain()) { case ATTR_DOMAIN_POINT: { array_utils::gather(this->vert_normals(), this->corner_verts(), r_data.as_mutable_span()); break; diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index 35039d0c6cd..bfcf99fad86 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -142,7 +142,7 @@ bool BKE_shrinkwrap_init_tree( if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) { data->face_normals = reinterpret_cast(mesh->face_normals().data()); - if (mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + if (mesh->normals_domain() == ATTR_DOMAIN_CORNER) { data->clnors = reinterpret_cast(mesh->corner_normals().data()); } } diff --git a/source/blender/blenkernel/intern/subdiv_modifier.cc b/source/blender/blenkernel/intern/subdiv_modifier.cc index 2490e8936fd..69cefb7321d 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.cc +++ b/source/blender/blenkernel/intern/subdiv_modifier.cc @@ -87,7 +87,7 @@ static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene, bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh) { return smd->flags & eSubsurfModifierFlag_UseCustomNormals && - mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER; + mesh->normals_domain() == ATTR_DOMAIN_CORNER; } static bool is_subdivision_evaluation_possible_on_gpu() diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index 4591ee07204..f2b2afd2456 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -402,7 +402,7 @@ class VArrayImpl_For_SharpEdge : public VArrayImpl { /** * Returns whether loop normals are required because of mixed sharp and smooth flags. - * Similar to #Mesh::normal_domain_all_info(). + * Similar to #Mesh::normals_domain(). */ static bool bm_loop_normals_required(BMesh *bm) { @@ -447,7 +447,7 @@ void mesh_render_data_update_normals(MeshRenderData &mr, const eMRDataType data_ mr.face_normals = mr.me->face_normals(); } if (((data_flag & MR_DATA_LOOP_NOR) && - ELEM(mr.me->normal_domain_all_info(), ATTR_DOMAIN_CORNER, ATTR_DOMAIN_FACE)) || + ELEM(mr.me->normals_domain(), ATTR_DOMAIN_CORNER, ATTR_DOMAIN_FACE)) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { mr.loop_normals = mr.me->corner_normals(); diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 429b416c0fc..bcdad60b13a 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -2152,7 +2152,7 @@ static bool draw_subdiv_create_requested_buffers(Object *ob, runtime_data->stats_totloop = draw_cache.num_subdiv_loops; draw_cache.use_custom_loop_normals = (runtime_data->use_loop_normals) && - mesh_eval->normal_domain_all_info() == ATTR_DOMAIN_CORNER; + mesh_eval->normals_domain() == ATTR_DOMAIN_CORNER; if (DRW_ibo_requested(mbc.buff.ibo.tris)) { draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache.mat_len); diff --git a/source/blender/editors/object/object_bake_api.cc b/source/blender/editors/object/object_bake_api.cc index 9ed868758c3..83103b4182d 100644 --- a/source/blender/editors/object/object_bake_api.cc +++ b/source/blender/editors/object/object_bake_api.cc @@ -712,7 +712,7 @@ static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, { Mesh *me = BKE_mesh_new_from_object(depsgraph, object, false, preserve_origindex); - if (me->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + if (me->normals_domain() == ATTR_DOMAIN_CORNER) { ED_mesh_split_faces(me); } diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 533f28338d4..dbaaab9fcae 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -525,7 +525,7 @@ static void get_loop_normals(const Mesh *mesh, std::vector &normals) { normals.clear(); - switch (mesh->normal_domain_all_info()) { + switch (mesh->normals_domain()) { case ATTR_DOMAIN_POINT: { /* If all faces are smooth shaded, and there are no custom normals, we don't need to * export normals at all. This is also done by other software, see #71246. */ diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index be92c21bf00..69995be9b73 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -626,7 +626,7 @@ void GeometryExporter::create_normals(std::vector &normals, "sharp_face", ATTR_DOMAIN_FACE, false); blender::Span corner_normals; - if (me->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + if (me->normals_domain() == ATTR_DOMAIN_CORNER) { corner_normals = me->corner_normals(); } diff --git a/source/blender/io/usd/hydra/mesh.cc b/source/blender/io/usd/hydra/mesh.cc index d8fdb01ab04..3fc6ad57796 100644 --- a/source/blender/io/usd/hydra/mesh.cc +++ b/source/blender/io/usd/hydra/mesh.cc @@ -232,7 +232,7 @@ void MeshData::write_submeshes(const Mesh *mesh) const Span looptris = mesh->looptris(); Span corner_normals; - if (mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + if (mesh->normals_domain() == ATTR_DOMAIN_CORNER) { corner_normals = mesh->corner_normals(); } diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index d9c3c51acdd..55f5ae155d9 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -661,7 +661,7 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ MutableSpan dst_normals(reinterpret_cast(loop_normals.data()), loop_normals.size()); - switch (mesh->normal_domain_all_info()) { + switch (mesh->normals_domain()) { case ATTR_DOMAIN_POINT: { array_utils::gather(mesh->vert_normals(), mesh->corner_verts(), dst_normals); break; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index ad82def4796..ad0896eb61e 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -368,7 +368,7 @@ void OBJMesh::store_normal_coords_and_indices() loop_to_normal_index_.fill(-1); Span corner_normals; - if (export_mesh_->normal_domain_all_info() == ATTR_DOMAIN_CORNER) { + if (export_mesh_->normals_domain() == ATTR_DOMAIN_CORNER) { corner_normals = export_mesh_->corner_normals(); } diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index c228189fa99..dcf4a1ccb58 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -366,7 +366,7 @@ typedef struct Mesh { * face corner normals, since there is a 2-4x performance cost increase for each more complex * domain. */ - int normal_domain_all_info() const; + int normals_domain() const; /** * Normal direction of polygons, defined by positions and the winding direction of face corners. */ @@ -381,7 +381,7 @@ typedef struct Mesh { * normals, the `sharp_edge` and `sharp_face` attributes, and potentially by custom normals. * * \note Because of the large memory requirements of storing normals per face corner, prefer - * using #face_normals() or #vert_normals() when possible (see #normal_domain_all_info()). + * using #face_normals() or #vert_normals() when possible (see #normals_domain()). */ blender::Span corner_normals() const; #endif diff --git a/source/blender/makesrna/intern/rna_mesh.cc b/source/blender/makesrna/intern/rna_mesh.cc index 10ec1d7965c..e94df13ceaf 100644 --- a/source/blender/makesrna/intern/rna_mesh.cc +++ b/source/blender/makesrna/intern/rna_mesh.cc @@ -1611,9 +1611,9 @@ int rna_Mesh_loops_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) return true; } -static int rna_Mesh_normal_domain_all_info_get(PointerRNA *ptr) +static int rna_Mesh_normals_domain_get(PointerRNA *ptr) { - return rna_mesh(ptr)->normal_domain_all_info(); + return rna_mesh(ptr)->normals_domain(); } static void rna_Mesh_vertex_normals_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) @@ -2996,14 +2996,14 @@ static void rna_def_mesh(BlenderRNA *brna) rna_def_normal_layer_value(brna); - prop = RNA_def_property(srna, "normal_domain_all_info", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "normals_domain", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_domain_only_mesh_no_edge_items); RNA_def_property_ui_text( prop, "Normal Domain All Info", "The attribute domain that gives enough information to represent the mesh's normals"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_enum_funcs(prop, "rna_Mesh_normal_domain_all_info_get", NULL, NULL); + RNA_def_property_enum_funcs(prop, "rna_Mesh_normals_domain_get", NULL, NULL); prop = RNA_def_property(srna, "vertex_normals", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "MeshNormalValue"); diff --git a/source/blender/modifiers/intern/MOD_multires.cc b/source/blender/modifiers/intern/MOD_multires.cc index cbc39ac1853..fad8af38b78 100644 --- a/source/blender/modifiers/intern/MOD_multires.cc +++ b/source/blender/modifiers/intern/MOD_multires.cc @@ -216,7 +216,7 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh return result; } const bool use_clnors = mmd->flags & eMultiresModifierFlag_UseCustomNormals && - mesh->normal_domain_all_info() == ATTR_DOMAIN_CORNER; + mesh->normals_domain() == ATTR_DOMAIN_CORNER; /* NOTE: Orco needs final coordinates on CPU side, which are expected to be * accessible via mesh vertices. For this reason we do not evaluate multires to * grids when orco is requested. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 0369da24846..31f8be06fc3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -336,7 +336,7 @@ static void compute_normal_outputs(const Mesh &mesh, const Span looptri_indices, MutableSpan r_normals) { - switch (mesh.normal_domain_all_info()) { + switch (mesh.normals_domain()) { case ATTR_DOMAIN_POINT: { const Span corner_verts = mesh.corner_verts(); const Span looptris = mesh.looptris(); -- 2.30.2 From e05fe7debc2040fa709fdc02e6bf831b9b289a21 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 16:22:23 -0400 Subject: [PATCH 67/85] Fix typo --- source/blender/blenkernel/intern/DerivedMesh.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 52900a79085..20eb1133852 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -466,7 +466,7 @@ static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *me } else { if (sculpt_dyntopo == false) { - /* Eager normal calculation can potentially be faster than deferring the to drawing code. */ + /* Eager normal calculation can potentially be faster than deferring to drawing code. */ if (domain == ATTR_DOMAIN_FACE) { mesh_final->face_normals(); } -- 2.30.2 From 0455e8caa41b86bc2f4f1a5e23bf91ae251f92b6 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 16:53:15 -0400 Subject: [PATCH 68/85] Update MeshLoop.normal description --- source/blender/makesrna/intern/rna_mesh.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/blender/makesrna/intern/rna_mesh.cc b/source/blender/makesrna/intern/rna_mesh.cc index e94df13ceaf..0ba501726fb 100644 --- a/source/blender/makesrna/intern/rna_mesh.cc +++ b/source/blender/makesrna/intern/rna_mesh.cc @@ -2213,11 +2213,10 @@ static void rna_def_mloop(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", nullptr, nullptr); - RNA_def_property_ui_text( - prop, - "Normal", - "Local space unit length split normal vector of this vertex for this face " - "(must be computed beforehand using calc_normals_split or calc_tangents)"); + RNA_def_property_ui_text(prop, + "Normal", + "The normal direction of the face corner, taking into account sharp " + "faces, sharp edges, and custom normal data"); prop = RNA_def_property(srna, "tangent", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_array(prop, 3); -- 2.30.2 From 876ab8734b467c19f955889e9224f9398081ef41 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 17:19:54 -0400 Subject: [PATCH 69/85] Replace manual virtual array implementations with ForDerivedSpan --- .../draw_cache_extract_mesh_render_data.cc | 81 ++++--------------- 1 file changed, 15 insertions(+), 66 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index f2b2afd2456..ae38da083a5 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -16,6 +16,7 @@ #include "BLI_index_mask.hh" #include "BLI_math_matrix.h" #include "BLI_task.hh" +#include "BLI_virtual_array.hh" #include "BKE_attribute.hh" #include "BKE_editmesh.h" @@ -336,69 +337,15 @@ void mesh_render_data_update_looptris(MeshRenderData &mr, } } -namespace blender { +static bool bm_edge_is_sharp(const BMEdge *const &edge) +{ + return BM_elem_flag_test(edge, BM_ELEM_SMOOTH); +} -class VArrayImpl_For_SharpFace : public VArrayImpl { - const BMFace *const *faces_; - - public: - VArrayImpl_For_SharpFace(const Span faces) - : VArrayImpl(faces.size()), faces_(faces.data()) - { - } - bool get(const int64_t index) const final - { - return !BM_elem_flag_test(faces_[index], BM_ELEM_SMOOTH); - } - void materialize(const IndexMask &mask, bool *dst) const override - { - mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); - } - void materialize_to_uninitialized(const IndexMask &mask, bool *dst) const override - { - materialize(mask, dst); - } - void materialize_compressed(const IndexMask &mask, bool *dst) const override - { - mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); - } - void materialize_compressed_to_uninitialized(const IndexMask &mask, bool *dst) const override - { - materialize_compressed(mask, dst); - } -}; - -class VArrayImpl_For_SharpEdge : public VArrayImpl { - const BMEdge *const *edges_; - - public: - VArrayImpl_For_SharpEdge(const Span edges) - : VArrayImpl(edges.size()), edges_(edges.data()) - { - } - bool get(const int64_t index) const final - { - return !BM_elem_flag_test(edges_[index], BM_ELEM_SMOOTH); - } - void materialize(const IndexMask &mask, bool *dst) const override - { - mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); - } - void materialize_to_uninitialized(const IndexMask &mask, bool *dst) const override - { - materialize(mask, dst); - } - void materialize_compressed(const IndexMask &mask, bool *dst) const override - { - mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); }); - } - void materialize_compressed_to_uninitialized(const IndexMask &mask, bool *dst) const override - { - materialize_compressed(mask, dst); - } -}; - -} // namespace blender +static bool bm_face_is_sharp(const BMFace *const &face) +{ + return BM_elem_flag_test(face, BM_ELEM_SMOOTH); +} /** * Returns whether loop normals are required because of mixed sharp and smooth flags. @@ -417,15 +364,17 @@ static bool bm_loop_normals_required(BMesh *bm) } BM_mesh_elem_table_ensure(bm, BM_FACE); - const VArrayImpl_For_SharpFace sharp_faces({bm->ftable, bm->totface}); - const array_utils::BooleanMix face_mix = array_utils::booleans_mix_calc(VArray(&sharp_faces)); + const VArray sharp_faces = VArray::ForDerivedSpan( + Span(bm->ftable, bm->totface)); + const array_utils::BooleanMix face_mix = array_utils::booleans_mix_calc(sharp_faces); if (face_mix == array_utils::BooleanMix::AllTrue) { return false; } BM_mesh_elem_table_ensure(bm, BM_EDGE); - const VArrayImpl_For_SharpEdge sharp_edges({bm->etable, bm->totedge}); - const array_utils::BooleanMix edge_mix = array_utils::booleans_mix_calc(VArray(&sharp_edges)); + const VArray sharp_edges = VArray::ForDerivedSpan( + Span(bm->etable, bm->totedge)); + const array_utils::BooleanMix edge_mix = array_utils::booleans_mix_calc(sharp_edges); if (edge_mix == array_utils::BooleanMix::AllTrue) { return false; } -- 2.30.2 From 4b925788b6ec9d72ffa5e6eeb5a6e58a7ea7643c Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 17:21:33 -0400 Subject: [PATCH 70/85] Use fewer casts --- .../blenkernel/intern/mesh_legacy_convert.cc | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 80724442260..7210f8fd7f4 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2108,18 +2108,24 @@ static bNodeTree *add_auto_smooth_node_tree(Main &bmain) shade_smooth->locy = 40.0f; bNode *store_node = nodeAddNode(nullptr, node_tree, "GeometryNodeStoreNamedAttribute"); - store_node->locx = 40.0f; - store_node->locy = 40.0f; - static_cast(store_node->storage)->data_type = CD_PROP_BOOL; - static_cast(store_node->storage)->domain = ATTR_DOMAIN_EDGE; - bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); - STRNCPY(name->default_value_typed()->value, "sharp_edge"); + { + store_node->locx = 40.0f; + store_node->locy = 40.0f; + auto *storage = static_cast(store_node->storage); + storage->data_type = CD_PROP_BOOL; + storage->domain = ATTR_DOMAIN_EDGE; + bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); + STRNCPY(name->default_value_typed()->value, "sharp_edge"); + } bNode *greater_node = nodeAddNode(nullptr, node_tree, "FunctionNodeCompare"); - greater_node->locx = -160.0f; - greater_node->locy = -100.0f; - static_cast(greater_node->storage)->operation = NODE_COMPARE_GREATER_THAN; - static_cast(greater_node->storage)->data_type = SOCK_FLOAT; + { + greater_node->locx = -160.0f; + greater_node->locy = -100.0f; + auto *storage = static_cast(store_node->storage); + storage->operation = NODE_COMPARE_GREATER_THAN; + storage->data_type = SOCK_FLOAT; + } bNode *edge_angle_node = nodeAddNode(nullptr, node_tree, "GeometryNodeInputMeshEdgeAngle"); edge_angle_node->locx = -380.0f; -- 2.30.2 From a879546ec3f54cc9acb71396fabcf47e2a3cc452 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 5 Sep 2023 20:44:48 -0400 Subject: [PATCH 71/85] Fix copy and paste mistake in last change to casting --- source/blender/blenkernel/intern/mesh_legacy_convert.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 7210f8fd7f4..e3331136a12 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2122,7 +2122,7 @@ static bNodeTree *add_auto_smooth_node_tree(Main &bmain) { greater_node->locx = -160.0f; greater_node->locy = -100.0f; - auto *storage = static_cast(store_node->storage); + auto *storage = static_cast(greater_node->storage); storage->operation = NODE_COMPARE_GREATER_THAN; storage->data_type = SOCK_FLOAT; } -- 2.30.2 From bbac27d2bb332f6fd48e595ebe1f68d4080bf6df Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 6 Sep 2023 07:47:15 -0400 Subject: [PATCH 72/85] Fix missing sharp is inverse of smooth --- .../draw/intern/draw_cache_extract_mesh_render_data.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index ae38da083a5..8106b3a4b0d 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -339,12 +339,12 @@ void mesh_render_data_update_looptris(MeshRenderData &mr, static bool bm_edge_is_sharp(const BMEdge *const &edge) { - return BM_elem_flag_test(edge, BM_ELEM_SMOOTH); + return !BM_elem_flag_test(edge, BM_ELEM_SMOOTH); } static bool bm_face_is_sharp(const BMFace *const &face) { - return BM_elem_flag_test(face, BM_ELEM_SMOOTH); + return !BM_elem_flag_test(face, BM_ELEM_SMOOTH); } /** -- 2.30.2 From 91c5baadc58ccacb22f163d45f3ea3487eb94388 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 6 Sep 2023 12:18:23 -0400 Subject: [PATCH 73/85] Update versioning to use new nodes --- .../blender/blenkernel/BKE_blender_version.h | 2 +- .../blenkernel/intern/mesh_legacy_convert.cc | 163 ++++++++++-------- .../blenloader/intern/versioning_common.cc | 2 +- 3 files changed, 96 insertions(+), 71 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 0bc34afb0b5..443e44b4128 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 23 +#define BLENDER_FILE_SUBVERSION 24 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index e3331136a12..da2ba9c9e9a 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2087,86 +2087,111 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh) static bNodeTree *add_auto_smooth_node_tree(Main &bmain) { - bNodeTree *node_tree = ntreeAddTree(&bmain, DATA_("Auto Smooth"), "GeometryNodeTree"); + bNodeTree *group = ntreeAddTree(&bmain, DATA_("Auto Smooth"), "GeometryNodeTree"); - node_tree->tree_interface.add_socket(DATA_("Geometry"), - "", - "NodeSocketGeometry", - NODE_INTERFACE_SOCKET_INPUT | NODE_INTERFACE_SOCKET_OUTPUT, - nullptr); - node_tree->tree_interface.add_socket( + group->tree_interface.add_socket(DATA_("Geometry"), + "", + "NodeSocketGeometry", + NODE_INTERFACE_SOCKET_INPUT | NODE_INTERFACE_SOCKET_OUTPUT, + nullptr); + group->tree_interface.add_socket( DATA_("Angle"), "", "NodeSocketFloatAngle", NODE_INTERFACE_SOCKET_INPUT, nullptr); - bNode *group_input = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_INPUT); - group_input->locx = -380.0f; - bNode *group_output = nodeAddStaticNode(nullptr, node_tree, NODE_GROUP_OUTPUT); - group_output->locx = 260.0f; - group_output->flag |= NODE_DO_OUTPUT; - - bNode *shade_smooth = nodeAddNode(nullptr, node_tree, "GeometryNodeSetShadeSmooth"); - shade_smooth->locx = -160.0f; - shade_smooth->locy = 40.0f; - - bNode *store_node = nodeAddNode(nullptr, node_tree, "GeometryNodeStoreNamedAttribute"); - { - store_node->locx = 40.0f; - store_node->locy = 40.0f; - auto *storage = static_cast(store_node->storage); - storage->data_type = CD_PROP_BOOL; - storage->domain = ATTR_DOMAIN_EDGE; - bNodeSocket *name = nodeFindSocket(store_node, SOCK_IN, DATA_("Name")); - STRNCPY(name->default_value_typed()->value, "sharp_edge"); + bNode *group_output = nodeAddNode(nullptr, group, "NodeGroupOutput"); + group_output->locx = 480.0f; + group_output->locy = -100.0f; + bNode *group_input_angle = nodeAddNode(nullptr, group, "NodeGroupInput"); + group_input_angle->locx = -420.0f; + group_input_angle->locy = -300.0f; + LISTBASE_FOREACH (bNodeSocket *, socket, &group_input_angle->outputs) { + if (!STREQ(socket->identifier, "Socket_1")) { + socket->flag |= SOCK_HIDDEN; + } } - - bNode *greater_node = nodeAddNode(nullptr, node_tree, "FunctionNodeCompare"); - { - greater_node->locx = -160.0f; - greater_node->locy = -100.0f; - auto *storage = static_cast(greater_node->storage); - storage->operation = NODE_COMPARE_GREATER_THAN; - storage->data_type = SOCK_FLOAT; + bNode *group_input_mesh = nodeAddNode(nullptr, group, "NodeGroupInput"); + group_input_mesh->locx = -60.0f; + group_input_mesh->locy = -100.0f; + LISTBASE_FOREACH (bNodeSocket *, socket, &group_input_mesh->outputs) { + if (!STREQ(socket->identifier, "Socket_0")) { + socket->flag |= SOCK_HIDDEN; + } } + bNode *shade_smooth_edge = nodeAddNode(nullptr, group, "GeometryNodeSetShadeSmooth"); + shade_smooth_edge->locx = 120.0f; + shade_smooth_edge->locy = -100.0f; + bNode *shade_smooth_face = nodeAddNode(nullptr, group, "GeometryNodeSetShadeSmooth"); + shade_smooth_face->locx = 300.0f; + shade_smooth_face->locy = -100.0f; + bNode *edge_angle = nodeAddNode(nullptr, group, "GeometryNodeInputMeshEdgeAngle"); + edge_angle->locx = -420.0f; + edge_angle->locy = -220.0f; + bNode *edge_smooth = nodeAddNode(nullptr, group, "GeometryNodeInputEdgeSmooth"); + edge_smooth->locx = -60.0f; + edge_smooth->locy = -160.0f; + bNode *face_smooth = nodeAddNode(nullptr, group, "GeometryNodeInputShadeSmooth"); + face_smooth->locx = -240.0f; + face_smooth->locy = -340.0f; + bNode *boolean_and = nodeAddNode(nullptr, group, "FunctionNodeBooleanMath"); + boolean_and->custom1 = NODE_BOOLEAN_MATH_AND; + boolean_and->locx = -60.0f; + boolean_and->locy = -220.0f; + bNode *less_than_or_equal = nodeAddNode(nullptr, group, "FunctionNodeCompare"); + static_cast(less_than_or_equal->storage)->operation = + NODE_COMPARE_LESS_EQUAL; + less_than_or_equal->locx = -240.0f; + less_than_or_equal->locy = -180.0f; - bNode *edge_angle_node = nodeAddNode(nullptr, node_tree, "GeometryNodeInputMeshEdgeAngle"); - edge_angle_node->locx = -380.0f; - edge_angle_node->locy = -180.0f; - - nodeAddLink(node_tree, - group_input, - static_cast(group_input->outputs.first), - shade_smooth, - nodeFindSocket(shade_smooth, SOCK_IN, "Geometry")); - nodeAddLink(node_tree, - shade_smooth, - nodeFindSocket(shade_smooth, SOCK_OUT, "Geometry"), - store_node, - nodeFindSocket(store_node, SOCK_IN, "Geometry")); - nodeAddLink(node_tree, - edge_angle_node, - nodeFindSocket(edge_angle_node, SOCK_OUT, "Unsigned Angle"), - greater_node, - nodeFindSocket(greater_node, SOCK_IN, "A")); - nodeAddLink(node_tree, - group_input, - static_cast(BLI_findlink(&group_input->outputs, 1)), - greater_node, - nodeFindSocket(greater_node, SOCK_IN, "B")); - nodeAddLink(node_tree, - greater_node, - nodeFindSocket(greater_node, SOCK_OUT, "Result"), - store_node, - nodeFindSocket(store_node, SOCK_IN, "Value_Bool")); - nodeAddLink(node_tree, - store_node, - nodeFindSocket(store_node, SOCK_OUT, "Geometry"), + nodeAddLink(group, + edge_angle, + nodeFindSocket(edge_angle, SOCK_OUT, "Unsigned Angle"), + less_than_or_equal, + nodeFindSocket(less_than_or_equal, SOCK_IN, "A")); + nodeAddLink(group, + shade_smooth_face, + nodeFindSocket(shade_smooth_face, SOCK_OUT, "Geometry"), group_output, - static_cast(group_output->inputs.first)); + nodeFindSocket(group_output, SOCK_IN, "Socket_0")); + nodeAddLink(group, + group_input_angle, + nodeFindSocket(group_input_angle, SOCK_OUT, "Socket_1"), + less_than_or_equal, + nodeFindSocket(less_than_or_equal, SOCK_IN, "B")); + nodeAddLink(group, + less_than_or_equal, + nodeFindSocket(less_than_or_equal, SOCK_OUT, "Result"), + boolean_and, + nodeFindSocket(boolean_and, SOCK_IN, "Boolean")); + nodeAddLink(group, + face_smooth, + nodeFindSocket(face_smooth, SOCK_OUT, "Smooth"), + boolean_and, + nodeFindSocket(boolean_and, SOCK_IN, "Boolean_001")); + nodeAddLink(group, + group_input_mesh, + nodeFindSocket(group_input_mesh, SOCK_OUT, "Socket_0"), + shade_smooth_edge, + nodeFindSocket(shade_smooth_edge, SOCK_IN, "Geometry")); + nodeAddLink(group, + edge_smooth, + nodeFindSocket(edge_smooth, SOCK_OUT, "Smooth"), + shade_smooth_edge, + nodeFindSocket(shade_smooth_edge, SOCK_IN, "Selection")); + nodeAddLink(group, + shade_smooth_edge, + nodeFindSocket(shade_smooth_edge, SOCK_OUT, "Geometry"), + shade_smooth_face, + nodeFindSocket(shade_smooth_face, SOCK_IN, "Geometry")); + nodeAddLink(group, + boolean_and, + nodeFindSocket(boolean_and, SOCK_OUT, "Boolean"), + shade_smooth_edge, + nodeFindSocket(shade_smooth_edge, SOCK_IN, "Shade Smooth")); - LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { + LISTBASE_FOREACH (bNode *, node, &group->nodes) { nodeSetSelected(node, false); } - return node_tree; + return group; } void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index 03b791f112e..ee537cdc529 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -528,7 +528,7 @@ void do_versions_after_setup(Main *new_bmain, BlendFileReadReport *reports) BKE_lib_override_library_main_hierarchy_root_ensure(new_bmain); } - if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 22)) { + if (!blendfile_or_libraries_versions_atleast(new_bmain, 400, 24)) { BKE_main_mesh_legacy_convert_auto_smooth(*new_bmain); } } -- 2.30.2 From 4d027a7554633942d7bfa3b906adfad83e52bcd8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 6 Sep 2023 12:24:56 -0400 Subject: [PATCH 74/85] Fix missing attribute domains for set shade smooth nodes --- source/blender/blenkernel/intern/mesh_legacy_convert.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index da2ba9c9e9a..d17ab0a4dfd 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2117,9 +2117,11 @@ static bNodeTree *add_auto_smooth_node_tree(Main &bmain) } } bNode *shade_smooth_edge = nodeAddNode(nullptr, group, "GeometryNodeSetShadeSmooth"); + shade_smooth_edge->custom1 = ATTR_DOMAIN_EDGE; shade_smooth_edge->locx = 120.0f; shade_smooth_edge->locy = -100.0f; bNode *shade_smooth_face = nodeAddNode(nullptr, group, "GeometryNodeSetShadeSmooth"); + shade_smooth_face->custom1 = ATTR_DOMAIN_FACE; shade_smooth_face->locx = 300.0f; shade_smooth_face->locy = -100.0f; bNode *edge_angle = nodeAddNode(nullptr, group, "GeometryNodeInputMeshEdgeAngle"); -- 2.30.2 From 2faacfa6dd6027af2e1ba1255aa9acd0be7de4d7 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 11 Sep 2023 14:08:20 -0400 Subject: [PATCH 75/85] Make cache dirty tagging more solid --- source/blender/blenkernel/BKE_mesh.h | 3 +++ .../blenkernel/intern/geometry_component_mesh.cc | 8 ++++---- source/blender/blenkernel/intern/mesh_runtime.cc | 5 +++++ source/blender/makesrna/intern/rna_mesh.cc | 10 ++++++++-- source/blender/makesrna/intern/rna_mesh_api.cc | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index d454f01d8d9..fff7db050cd 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -76,6 +76,9 @@ void BKE_mesh_tag_topology_changed(struct Mesh *mesh); */ void BKE_mesh_tag_edges_split(struct Mesh *mesh); +/** Call when changing "sharp_face" or "sharp_edge" data. */ +void BKE_mesh_tag_sharpness_changed(struct Mesh *mesh); + /** * Call when face vertex order has changed but positions and faces haven't changed */ diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 036f01184f6..7e09db5994d 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -858,10 +858,10 @@ static void tag_component_positions_changed(void *owner) } } -static void tag_component_corner_normals_dirty(void *owner) +static void tag_component_sharpness_changed(void *owner) { if (Mesh *mesh = static_cast(owner)) { - mesh->runtime->corner_normals_cache.tag_dirty(); + BKE_mesh_tag_sharpness_changed(mesh); } } @@ -1187,7 +1187,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() BuiltinAttributeProvider::Creatable, BuiltinAttributeProvider::Deletable, face_access, - tag_component_corner_normals_dirty); + tag_component_sharpness_changed); static BuiltinCustomDataLayerProvider sharp_edge("sharp_edge", ATTR_DOMAIN_EDGE, @@ -1196,7 +1196,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() BuiltinAttributeProvider::Creatable, BuiltinAttributeProvider::Deletable, edge_access, - tag_component_corner_normals_dirty); + tag_component_sharpness_changed); static VertexGroupsAttributeProvider vertex_groups; static CustomDataAttributeProvider corner_custom_data(ATTR_DOMAIN_CORNER, corner_access); diff --git a/source/blender/blenkernel/intern/mesh_runtime.cc b/source/blender/blenkernel/intern/mesh_runtime.cc index 004cc826e61..d93336fca62 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.cc +++ b/source/blender/blenkernel/intern/mesh_runtime.cc @@ -355,6 +355,11 @@ void BKE_mesh_tag_edges_split(Mesh *mesh) } } +void BKE_mesh_tag_sharpness_changed(Mesh *mesh) +{ + mesh->runtime->corner_normals_cache.tag_dirty(); +} + void BKE_mesh_tag_face_winding_changed(Mesh *mesh) { mesh->runtime->vert_normals_cache.tag_dirty(); diff --git a/source/blender/makesrna/intern/rna_mesh.cc b/source/blender/makesrna/intern/rna_mesh.cc index 6bea5ac8250..b9142dce30a 100644 --- a/source/blender/makesrna/intern/rna_mesh.cc +++ b/source/blender/makesrna/intern/rna_mesh.cc @@ -582,7 +582,10 @@ static void rna_MeshPolygon_use_smooth_set(PointerRNA *ptr, bool value) &mesh->face_data, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->faces_num, "sharp_face")); } const int index = rna_MeshPolygon_index_get(ptr); - sharp_faces[index] = !value; + if (value != sharp_faces[index]) { + sharp_faces[index] = value; + BKE_mesh_tag_sharpness_changed(mesh); + } } static bool rna_MeshPolygon_select_get(PointerRNA *ptr) @@ -1368,7 +1371,10 @@ static void rna_MeshEdge_use_edge_sharp_set(PointerRNA *ptr, bool value) &mesh->edge_data, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totedge, "sharp_edge")); } const int index = rna_MeshEdge_index_get(ptr); - sharp_edge[index] = value; + if (value != sharp_edge[index]) { + sharp_edge[index] = value; + BKE_mesh_tag_sharpness_changed(mesh); + } } static bool rna_MeshEdge_use_seam_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_mesh_api.cc b/source/blender/makesrna/intern/rna_mesh_api.cc index 3b09ae269d2..58391697f93 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.cc +++ b/source/blender/makesrna/intern/rna_mesh_api.cc @@ -178,6 +178,7 @@ static void rna_Mesh_update(Mesh *mesh, mesh->runtime->vert_normals_cache.tag_dirty(); mesh->runtime->face_normals_cache.tag_dirty(); + mesh->runtime->corner_normals_cache.tag_dirty(); DEG_id_tag_update(&mesh->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh); -- 2.30.2 From 5e759bf241b5eb5022a28e7da2854614a05b8950 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 28 Sep 2023 17:32:30 -0400 Subject: [PATCH 76/85] Cleanup: Remove redundant check --- source/blender/blenkernel/intern/mesh_normals.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 422ae59949f..35940e65f55 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -828,7 +828,7 @@ static void mesh_edges_sharp_tag(const OffsetIndices faces, /* We want to avoid tagging edges as sharp when it is already defined as such by * other causes than angle threshold. */ - if (!r_sharp_edges.is_empty() && is_angle_sharp) { + if (is_angle_sharp) { r_sharp_edges[edge_i] = true; } } -- 2.30.2 From ee05da84413f5443e16890f6542709b1b3ff7ed0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 29 Sep 2023 09:44:45 -0400 Subject: [PATCH 77/85] Fix Cycles mesh extraction --- intern/cycles/blender/mesh.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index f6f48109dac..5eb8cb8c52e 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -818,7 +818,7 @@ static void create_mesh(Scene *scene, const blender::bke::AttributeAccessor b_attributes = b_mesh.attributes(); int numfaces = (!subdivision) ? b_mesh.looptris().size() : faces.size(); - bool use_loop_normals = b_mesh.normals_domain() == ATTR_DOMAIN_CORNER && + bool use_loop_normals = b_mesh.normals_domain() == blender::bke::MeshNormalDomain::Corner && (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK); /* If no faces, create empty mesh. */ @@ -832,9 +832,7 @@ static void create_mesh(Scene *scene, ATTR_DOMAIN_FACE); blender::Span corner_normals; if (use_loop_normals) { - corner_normals = { - static_cast(CustomData_get_layer(&b_mesh.loop_data, CD_NORMAL)), - corner_verts.size()}; + corner_normals = b_mesh.corner_normals(); } int numngons = 0; -- 2.30.2 From 6770c55a508741c55687c3c5a30f05a6fcdf7bcf Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 29 Sep 2023 09:44:56 -0400 Subject: [PATCH 78/85] Fix redundant normal layer removal --- source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 7111b493ba4..7fabb684bdd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -146,7 +146,6 @@ static void expand_mesh(Mesh &mesh, mesh.face_offset_indices[mesh.faces_num] = mesh.totloop + loop_expand; } if (loop_expand != 0) { - CustomData_free_layers(&mesh.loop_data, CD_NORMAL, mesh.totloop); CustomData_free_layers(&mesh.loop_data, CD_MDISPS, mesh.totloop); CustomData_free_layers(&mesh.loop_data, CD_TANGENT, mesh.totloop); CustomData_free_layers(&mesh.loop_data, CD_PAINT_MASK, mesh.totloop); -- 2.30.2 From 9560c55236ca8984afbeee53b01f6e17be9089d1 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 29 Sep 2023 09:45:14 -0400 Subject: [PATCH 79/85] Use a proper descriptive enum type --- source/blender/blenkernel/BKE_mesh_types.hh | 25 +++++++++ .../blender/blenkernel/intern/DerivedMesh.cc | 11 ++-- .../blender/blenkernel/intern/mesh_normals.cc | 51 +++++++++---------- .../blender/blenkernel/intern/shrinkwrap.cc | 2 +- .../blenkernel/intern/subdiv_modifier.cc | 2 +- .../draw_cache_extract_mesh_render_data.cc | 5 +- .../intern/draw_cache_impl_subdivision.cc | 3 +- .../blender/editors/object/object_bake_api.cc | 2 +- .../io/alembic/exporter/abc_writer_mesh.cc | 8 ++- .../blender/io/collada/GeometryExporter.cpp | 2 +- source/blender/io/usd/hydra/mesh.cc | 2 +- .../blender/io/usd/intern/usd_writer_mesh.cc | 8 ++- .../wavefront_obj/exporter/obj_export_mesh.cc | 2 +- source/blender/makesdna/DNA_mesh_types.h | 5 +- source/blender/makesrna/intern/rna_mesh.cc | 14 +++-- .../blender/modifiers/intern/MOD_multires.cc | 2 +- .../node_geo_distribute_points_on_faces.cc | 8 ++- 17 files changed, 91 insertions(+), 61 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_types.hh b/source/blender/blenkernel/BKE_mesh_types.hh index 3396c22aa8c..d5799b96c9d 100644 --- a/source/blender/blenkernel/BKE_mesh_types.hh +++ b/source/blender/blenkernel/BKE_mesh_types.hh @@ -43,6 +43,31 @@ enum eMeshWrapperType { namespace blender::bke { +/** + * The complexity requirement of attribute domains needed to process normals. + * See #Mesh::normals_domain(). + */ +enum class MeshNormalDomain : int8_t { + /** + * The mesh is completely smooth shaded; either all faces or edges are sharp. + * Only #Mesh::face_normals() is necessary. This case is generally the best + * for performance, since no mixing is necessary and multithreading is simple. + */ + Face, + /** + * The mesh is completely smooth shaded; there are no sharp face or edges. Only + * #Mesh::vert_normals() is necessary. Calculating face normals is still necessary though, + * since they have to be mixed to become vertex normals. + */ + Point, + /** + * The mesh has mixed smooth and sharp shading. In order to split the normals on each side of + * sharp edges, they need to be processed per-face-corner. Normals can be retrieved with + * #Mesh::corner_normals(). + */ + Corner, +}; + /** * Cache of a mesh's loose edges, accessed with #Mesh::loose_edges(). * */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index c7320ce996b..4c2120f9148 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -449,15 +449,16 @@ static void add_orco_mesh( static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *mesh_final) { - const eAttrDomain domain = eAttrDomain(mesh_final->normals_domain()); + using namespace blender::bke; + const MeshNormalDomain domain = mesh_final->normals_domain(); /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; if (subsurf_runtime_data) { - subsurf_runtime_data->calc_loop_normals = domain == ATTR_DOMAIN_CORNER; + subsurf_runtime_data->calc_loop_normals = domain == MeshNormalDomain::Corner; } - if (domain == ATTR_DOMAIN_CORNER) { + if (domain == MeshNormalDomain::Corner) { /* Compute loop normals (NOTE: will compute face and vert normals as well, if needed!). In case * of deferred CPU subdivision, this will be computed when the wrapper is generated. */ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { @@ -467,10 +468,10 @@ static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *me else { if (sculpt_dyntopo == false) { /* Eager normal calculation can potentially be faster than deferring to drawing code. */ - if (domain == ATTR_DOMAIN_FACE) { + if (domain == MeshNormalDomain::Face) { mesh_final->face_normals(); } - else if (domain == ATTR_DOMAIN_POINT) { + else if (domain == MeshNormalDomain::Point) { mesh_final->vert_normals(); } } diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 35940e65f55..cdbe325c9b7 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -299,16 +299,16 @@ static void normals_calc_faces_and_verts(const Span positions, /** \name Mesh Normal Calculation * \{ */ -int Mesh::normals_domain() const +blender::bke::MeshNormalDomain Mesh::normals_domain() const { using namespace blender; using namespace blender::bke; if (this->faces_num == 0) { - return ATTR_DOMAIN_POINT; + return MeshNormalDomain::Point; } if (CustomData_has_layer(&this->loop_data, CD_CUSTOMLOOPNORMAL)) { - return ATTR_DOMAIN_CORNER; + return MeshNormalDomain::Corner; } const AttributeAccessor attributes = this->attributes(); @@ -317,22 +317,22 @@ int Mesh::normals_domain() const const array_utils::BooleanMix face_mix = array_utils::booleans_mix_calc(sharp_faces); if (face_mix == array_utils::BooleanMix::AllTrue) { - return ATTR_DOMAIN_FACE; + return MeshNormalDomain::Face; } const VArray sharp_edges = *attributes.lookup_or_default( "sharp_edge", ATTR_DOMAIN_EDGE, false); const array_utils::BooleanMix edge_mix = array_utils::booleans_mix_calc(sharp_edges); if (edge_mix == array_utils::BooleanMix::AllTrue) { - return ATTR_DOMAIN_FACE; + return MeshNormalDomain::Face; } if (edge_mix == array_utils::BooleanMix::AllFalse && face_mix == array_utils::BooleanMix::AllFalse) { - return ATTR_DOMAIN_POINT; + return MeshNormalDomain::Point; } - return ATTR_DOMAIN_CORNER; + return MeshNormalDomain::Corner; } blender::Span Mesh::vert_normals() const @@ -387,15 +387,16 @@ blender::Span Mesh::face_normals() const blender::Span Mesh::corner_normals() const { using namespace blender; + using namespace blender::bke; this->runtime->corner_normals_cache.ensure([&](Vector &r_data) { + r_data.reinitialize(this->totloop); const OffsetIndices faces = this->faces(); - r_data.reinitialize(faces.total_size()); switch (this->normals_domain()) { - case ATTR_DOMAIN_POINT: { + case MeshNormalDomain::Point: { array_utils::gather(this->vert_normals(), this->corner_verts(), r_data.as_mutable_span()); break; } - case ATTR_DOMAIN_FACE: { + case MeshNormalDomain::Face: { const Span face_normals = this->face_normals(); threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { @@ -404,30 +405,28 @@ blender::Span Mesh::corner_normals() const }); break; } - case ATTR_DOMAIN_CORNER: { + case MeshNormalDomain::Corner: { const bool *sharp_edges = static_cast( CustomData_get_layer_named(&this->edge_data, CD_PROP_BOOL, "sharp_edge")); const bool *sharp_faces = static_cast( CustomData_get_layer_named(&this->face_data, CD_PROP_BOOL, "sharp_face")); const short2 *custom_normals = static_cast( CustomData_get_layer(&this->loop_data, CD_CUSTOMLOOPNORMAL)); - bke::mesh::normals_calc_loop(this->vert_positions(), - this->edges(), - this->faces(), - this->corner_verts(), - this->corner_edges(), - this->corner_to_face_map(), - this->vert_normals(), - this->face_normals(), - sharp_edges, - sharp_faces, - custom_normals, - nullptr, - r_data); + mesh::normals_calc_loop(this->vert_positions(), + this->edges(), + this->faces(), + this->corner_verts(), + this->corner_edges(), + this->corner_to_face_map(), + this->vert_normals(), + this->face_normals(), + sharp_edges, + sharp_faces, + custom_normals, + nullptr, + r_data); break; } - default: - BLI_assert_unreachable(); } }); return this->runtime->corner_normals_cache.data(); diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index 9555eca1bf4..42f429cb26c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -142,7 +142,7 @@ bool BKE_shrinkwrap_init_tree( if (force_normals || BKE_shrinkwrap_needs_normals(shrinkType, shrinkMode)) { data->face_normals = reinterpret_cast(mesh->face_normals().data()); - if (mesh->normals_domain() == ATTR_DOMAIN_CORNER) { + if (mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner) { data->clnors = reinterpret_cast(mesh->corner_normals().data()); } } diff --git a/source/blender/blenkernel/intern/subdiv_modifier.cc b/source/blender/blenkernel/intern/subdiv_modifier.cc index 10f85aa5640..b1c61e80486 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.cc +++ b/source/blender/blenkernel/intern/subdiv_modifier.cc @@ -87,7 +87,7 @@ static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene, bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh) { return smd->flags & eSubsurfModifierFlag_UseCustomNormals && - mesh->normals_domain() == ATTR_DOMAIN_CORNER; + mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner; } static bool is_subdivision_evaluation_possible_on_gpu() diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index f09515a9f2b..c3b5ee31834 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -413,8 +413,9 @@ void mesh_render_data_update_normals(MeshRenderData &mr, const eMRDataType data_ if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) { mr.face_normals = mr.me->face_normals(); } - if (((data_flag & MR_DATA_LOOP_NOR) && - ELEM(mr.me->normals_domain(), ATTR_DOMAIN_CORNER, ATTR_DOMAIN_FACE)) || + if (((data_flag & MR_DATA_LOOP_NOR) && ELEM(mr.me->normals_domain(), + blender::bke::MeshNormalDomain::Corner, + blender::bke::MeshNormalDomain::Face)) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { mr.loop_normals = mr.me->corner_normals(); diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index bcdad60b13a..efce2f33fd8 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -2152,7 +2152,8 @@ static bool draw_subdiv_create_requested_buffers(Object *ob, runtime_data->stats_totloop = draw_cache.num_subdiv_loops; draw_cache.use_custom_loop_normals = (runtime_data->use_loop_normals) && - mesh_eval->normals_domain() == ATTR_DOMAIN_CORNER; + mesh_eval->normals_domain() == + blender::bke::MeshNormalDomain::Corner; if (DRW_ibo_requested(mbc.buff.ibo.tris)) { draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache.mat_len); diff --git a/source/blender/editors/object/object_bake_api.cc b/source/blender/editors/object/object_bake_api.cc index 45adddce9c8..ea4020d0711 100644 --- a/source/blender/editors/object/object_bake_api.cc +++ b/source/blender/editors/object/object_bake_api.cc @@ -712,7 +712,7 @@ static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, { Mesh *me = BKE_mesh_new_from_object(depsgraph, object, false, preserve_origindex); - if (me->normals_domain() == ATTR_DOMAIN_CORNER) { + if (me->normals_domain() == blender::bke::MeshNormalDomain::Corner) { ED_mesh_split_faces(me); } diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 0dadf9d9b23..d82e2ed9252 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -526,12 +526,12 @@ static void get_loop_normals(const Mesh *mesh, std::vector &normals) normals.clear(); switch (mesh->normals_domain()) { - case ATTR_DOMAIN_POINT: { + case blender::bke::MeshNormalDomain::Point: { /* If all faces are smooth shaded, and there are no custom normals, we don't need to * export normals at all. This is also done by other software, see #71246. */ break; } - case ATTR_DOMAIN_FACE: { + case blender::bke::MeshNormalDomain::Face: { normals.resize(mesh->totloop); MutableSpan dst_normals(reinterpret_cast(normals.data()), normals.size()); @@ -546,7 +546,7 @@ static void get_loop_normals(const Mesh *mesh, std::vector &normals) }); break; } - case ATTR_DOMAIN_CORNER: { + case blender::bke::MeshNormalDomain::Corner: { normals.resize(mesh->totloop); MutableSpan dst_normals(reinterpret_cast(normals.data()), normals.size()); @@ -563,8 +563,6 @@ static void get_loop_normals(const Mesh *mesh, std::vector &normals) }); break; } - default: - BLI_assert_unreachable(); } } diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index 69995be9b73..1b85a0f8c5c 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -626,7 +626,7 @@ void GeometryExporter::create_normals(std::vector &normals, "sharp_face", ATTR_DOMAIN_FACE, false); blender::Span corner_normals; - if (me->normals_domain() == ATTR_DOMAIN_CORNER) { + if (me->normals_domain() == blender::bke::MeshNormalDomain::Corner) { corner_normals = me->corner_normals(); } diff --git a/source/blender/io/usd/hydra/mesh.cc b/source/blender/io/usd/hydra/mesh.cc index 33ba9ea7a8b..7dac3b15bc9 100644 --- a/source/blender/io/usd/hydra/mesh.cc +++ b/source/blender/io/usd/hydra/mesh.cc @@ -233,7 +233,7 @@ void MeshData::write_submeshes(const Mesh *mesh) const Span looptris = mesh->looptris(); Span corner_normals; - if (mesh->normals_domain() == ATTR_DOMAIN_CORNER) { + if (mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner) { corner_normals = mesh->corner_normals(); } diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 85fc81fa791..5672e108416 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -653,11 +653,11 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ MutableSpan dst_normals(reinterpret_cast(loop_normals.data()), loop_normals.size()); switch (mesh->normals_domain()) { - case ATTR_DOMAIN_POINT: { + case bke::MeshNormalDomain::Point: { array_utils::gather(mesh->vert_normals(), mesh->corner_verts(), dst_normals); break; } - case ATTR_DOMAIN_FACE: { + case bke::MeshNormalDomain::Face: { const OffsetIndices faces = mesh->faces(); const Span face_normals = mesh->face_normals(); for (const int i : faces.index_range()) { @@ -665,12 +665,10 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ } break; } - case ATTR_DOMAIN_CORNER: { + case bke::MeshNormalDomain::Corner: { array_utils::copy(mesh->corner_normals(), dst_normals); break; } - default: - BLI_assert_unreachable(); } pxr::UsdAttribute attr_normals = usd_mesh.CreateNormalsAttr(pxr::VtValue(), true); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 7743e012509..2b296af92a7 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -368,7 +368,7 @@ void OBJMesh::store_normal_coords_and_indices() loop_to_normal_index_.fill(-1); Span corner_normals; - if (export_mesh_->normals_domain() == ATTR_DOMAIN_CORNER) { + if (export_mesh_->normals_domain() == blender::bke::MeshNormalDomain::Corner) { corner_normals = export_mesh_->corner_normals(); } diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index dcf4a1ccb58..6d08fafcf44 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -32,6 +32,7 @@ class AttributeAccessor; class MutableAttributeAccessor; struct LooseVertCache; struct LooseEdgeCache; +enum class MeshNormalDomain : int8_t; } // namespace bke } // namespace blender using MeshRuntimeHandle = blender::bke::MeshRuntime; @@ -366,7 +367,7 @@ typedef struct Mesh { * face corner normals, since there is a 2-4x performance cost increase for each more complex * domain. */ - int normals_domain() const; + blender::bke::MeshNormalDomain normals_domain() const; /** * Normal direction of polygons, defined by positions and the winding direction of face corners. */ @@ -438,7 +439,7 @@ enum { ME_FLAG_DEPRECATED_2 = 1 << 2, /* deprecated */ ME_FLAG_UNUSED_3 = 1 << 3, /* cleared */ ME_FLAG_UNUSED_4 = 1 << 4, /* cleared */ - ME_AUTOSMOOTH_LEGACY = 1 << 5, /* deprecated */ + ME_AUTOSMOOTH_LEGACY = 1 << 5, /* deprecated */ ME_FLAG_UNUSED_6 = 1 << 6, /* cleared */ ME_FLAG_UNUSED_7 = 1 << 7, /* cleared */ ME_REMESH_REPROJECT_VERTEX_COLORS = 1 << 8, diff --git a/source/blender/makesrna/intern/rna_mesh.cc b/source/blender/makesrna/intern/rna_mesh.cc index c6958003c35..18a2abbe690 100644 --- a/source/blender/makesrna/intern/rna_mesh.cc +++ b/source/blender/makesrna/intern/rna_mesh.cc @@ -23,6 +23,7 @@ #include "BKE_attribute.h" #include "BKE_editmesh.h" +#include "BKE_mesh_types.hh" #include "RNA_access.hh" #include "RNA_define.hh" @@ -1619,7 +1620,7 @@ int rna_Mesh_loops_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr) static int rna_Mesh_normals_domain_get(PointerRNA *ptr) { - return rna_mesh(ptr)->normals_domain(); + return int(rna_mesh(ptr)->normals_domain()); } static void rna_Mesh_vertex_normals_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) @@ -2999,11 +3000,18 @@ static void rna_def_mesh(BlenderRNA *brna) rna_def_normal_layer_value(brna); + static const EnumPropertyItem normal_domain_items[] = { + {int(blender::bke::MeshNormalDomain::Point), "POINT", 0, "Point", ""}, + {int(blender::bke::MeshNormalDomain::Face), "FACE", 0, "Face", ""}, + {int(blender::bke::MeshNormalDomain::Corner), "CORNER", 0, "Corner", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + prop = RNA_def_property(srna, "normals_domain", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_attribute_domain_only_mesh_no_edge_items); + RNA_def_property_enum_items(prop, normal_domain_items); RNA_def_property_ui_text( prop, - "Normal Domain All Info", + "Normal Domain", "The attribute domain that gives enough information to represent the mesh's normals"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_funcs(prop, "rna_Mesh_normals_domain_get", NULL, NULL); diff --git a/source/blender/modifiers/intern/MOD_multires.cc b/source/blender/modifiers/intern/MOD_multires.cc index 17eebfba216..1280c34abfc 100644 --- a/source/blender/modifiers/intern/MOD_multires.cc +++ b/source/blender/modifiers/intern/MOD_multires.cc @@ -216,7 +216,7 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh return result; } const bool use_clnors = mmd->flags & eMultiresModifierFlag_UseCustomNormals && - mesh->normals_domain() == ATTR_DOMAIN_CORNER; + mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner; /* NOTE: Orco needs final coordinates on CPU side, which are expected to be * accessible via mesh vertices. For this reason we do not evaluate multires to * grids when orco is requested. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 31f8be06fc3..3d5fd4b940c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -337,7 +337,7 @@ static void compute_normal_outputs(const Mesh &mesh, MutableSpan r_normals) { switch (mesh.normals_domain()) { - case ATTR_DOMAIN_POINT: { + case bke::MeshNormalDomain::Point: { const Span corner_verts = mesh.corner_verts(); const Span looptris = mesh.looptris(); const Span vert_normals = mesh.vert_normals(); @@ -347,7 +347,7 @@ static void compute_normal_outputs(const Mesh &mesh, }); break; } - case ATTR_DOMAIN_FACE: { + case bke::MeshNormalDomain::Face: { const Span looptri_faces = mesh.looptri_faces(); VArray face_normals = VArray::ForSpan(mesh.face_normals()); threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) { @@ -356,7 +356,7 @@ static void compute_normal_outputs(const Mesh &mesh, }); break; } - case ATTR_DOMAIN_CORNER: { + case bke::MeshNormalDomain::Corner: { const Span looptris = mesh.looptris(); const Span corner_normals = mesh.corner_normals(); threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) { @@ -365,8 +365,6 @@ static void compute_normal_outputs(const Mesh &mesh, }); break; } - default: - BLI_assert_unreachable(); } } -- 2.30.2 From 7dadb241f39fc1a2b7df2f6588f7aa7beacef6da Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 29 Sep 2023 14:05:59 -0400 Subject: [PATCH 80/85] Remove unhelpful and slow eager normal calculation Calculating normals early (especially corner normals) turns out to be slower here, and prevents optimizations like the renderer only requesting the normals it needs, or only requesting normals based on some scene simplify option that doesn't affect object evaluation. It adds significant complexity too.`calc_loop_normals` was also set but not used. --- .../blender/blenkernel/BKE_subdiv_modifier.hh | 1 - .../blender/blenkernel/intern/DerivedMesh.cc | 34 ------------------- .../blender/modifiers/intern/MOD_subsurf.cc | 1 - 3 files changed, 36 deletions(-) diff --git a/source/blender/blenkernel/BKE_subdiv_modifier.hh b/source/blender/blenkernel/BKE_subdiv_modifier.hh index a6416be3f4e..e6a269be308 100644 --- a/source/blender/blenkernel/BKE_subdiv_modifier.hh +++ b/source/blender/blenkernel/BKE_subdiv_modifier.hh @@ -45,7 +45,6 @@ struct SubsurfRuntimeData { bool has_gpu_subdiv; int resolution; bool use_optimal_display; - bool calc_loop_normals; bool use_loop_normals; /* Cached from the draw code for stats display. */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 4c2120f9148..85f5e89181d 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -447,37 +447,6 @@ static void add_orco_mesh( } } -static void mesh_calc_modifier_final_normals(const bool sculpt_dyntopo, Mesh *mesh_final) -{ - using namespace blender::bke; - const MeshNormalDomain domain = mesh_final->normals_domain(); - - /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ - SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data; - if (subsurf_runtime_data) { - subsurf_runtime_data->calc_loop_normals = domain == MeshNormalDomain::Corner; - } - - if (domain == MeshNormalDomain::Corner) { - /* Compute loop normals (NOTE: will compute face and vert normals as well, if needed!). In case - * of deferred CPU subdivision, this will be computed when the wrapper is generated. */ - if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { - mesh_final->corner_normals(); - } - } - else { - if (sculpt_dyntopo == false) { - /* Eager normal calculation can potentially be faster than deferring to drawing code. */ - if (domain == MeshNormalDomain::Face) { - mesh_final->face_normals(); - } - else if (domain == MeshNormalDomain::Point) { - mesh_final->vert_normals(); - } - } - } -} - /* Does final touches to the final evaluated mesh, making sure it is perfectly usable. * * This is needed because certain information is not passed along intermediate meshes allocated @@ -987,7 +956,6 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph, /* Compute normals. */ if (is_own_mesh) { - mesh_calc_modifier_final_normals(sculpt_dyntopo, mesh_final); mesh_calc_finalize(mesh_input, mesh_final); } else { @@ -999,7 +967,6 @@ static void mesh_calc_modifiers(Depsgraph *depsgraph, * Isolate since computing normals is multithreaded and we are holding a lock. */ blender::threading::isolate_task([&] { mesh_final = BKE_mesh_copy_for_eval(mesh_input); - mesh_calc_modifier_final_normals(sculpt_dyntopo, mesh_final); mesh_calc_finalize(mesh_input, mesh_final); runtime->mesh_eval = mesh_final; }); @@ -1062,7 +1029,6 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final) switch (mesh_final->runtime->wrapper_type) { case ME_WRAPPER_TYPE_SUBD: case ME_WRAPPER_TYPE_MDATA: - mesh_calc_modifier_final_normals(false, mesh_final); break; case ME_WRAPPER_TYPE_BMESH: { BMEditMesh *em = mesh_final->edit_mesh; diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index 96c2f950fce..0e99ea09560 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -205,7 +205,6 @@ static void subdiv_cache_mesh_wrapper_settings(const ModifierEvalContext *ctx, runtime_data->has_gpu_subdiv = true; runtime_data->resolution = mesh_settings.resolution; runtime_data->use_optimal_display = mesh_settings.use_optimal_display; - runtime_data->calc_loop_normals = false; /* Set at the end of modifier stack evaluation. */ runtime_data->use_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals); mesh->runtime->subsurf_runtime_data = runtime_data; -- 2.30.2 From cd968b80de0e4c8172d3175d0191756bf829b60d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Sun, 1 Oct 2023 16:31:26 -0400 Subject: [PATCH 81/85] Fixes --- source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc | 5 ++++- source/blender/io/wavefront_obj/tests/obj_importer_tests.cc | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 2b296af92a7..e87c7483162 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -368,7 +368,10 @@ void OBJMesh::store_normal_coords_and_indices() loop_to_normal_index_.fill(-1); Span corner_normals; - if (export_mesh_->normals_domain() == blender::bke::MeshNormalDomain::Corner) { + if (ELEM(export_mesh_->normals_domain(), + bke::MeshNormalDomain::Point, + bke::MeshNormalDomain::Corner)) + { corner_normals = export_mesh_->corner_normals(); } diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index 0090906f212..8a13e30f289 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -137,7 +137,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest { const Span positions = mesh->vert_positions(); EXPECT_V3_NEAR(positions.first(), exp.vert_first, 0.0001f); EXPECT_V3_NEAR(positions.last(), exp.vert_last, 0.0001f); - const float3 *lnors = &mesh->corner_normals().first(); + const float3 *lnors = mesh->corner_normals().data(); float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0); EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f); const float2 *mloopuv = static_cast( -- 2.30.2 From 78a34dffddc365a7f966303418684c0aaf83e566 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 19 Oct 2023 00:20:11 +0200 Subject: [PATCH 82/85] Fix subversion --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_common.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 8c75a57ff66..eabb647dfd6 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 1 +#define BLENDER_FILE_SUBVERSION 2 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index 286c94b386b..d68be18250e 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -528,7 +528,7 @@ void do_versions_after_setup(Main *new_bmain, BlendFileReadReport *reports) BKE_lib_override_library_main_hierarchy_root_ensure(new_bmain); } - if (!blendfile_or_libraries_versions_atleast(new_bmain, 401, 1)) { + if (!blendfile_or_libraries_versions_atleast(new_bmain, 401, 2)) { BKE_main_mesh_legacy_convert_auto_smooth(*new_bmain); } } -- 2.30.2 From 95d4ba381b4b2c87ab39fc76834477c896b81ad4 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 19 Oct 2023 17:47:22 +0200 Subject: [PATCH 83/85] Fix Cycles "all sharp" case --- intern/cycles/blender/mesh.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index 5eb8cb8c52e..cdfeadb806a 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -816,9 +816,10 @@ static void create_mesh(Scene *scene, const blender::OffsetIndices faces = b_mesh.faces(); const blender::Span corner_verts = b_mesh.corner_verts(); const blender::bke::AttributeAccessor b_attributes = b_mesh.attributes(); + const blender::bke::MeshNormalDomain normals_domain = b_mesh.normals_domain(); int numfaces = (!subdivision) ? b_mesh.looptris().size() : faces.size(); - bool use_loop_normals = b_mesh.normals_domain() == blender::bke::MeshNormalDomain::Corner && + bool use_loop_normals = normals_domain == blender::bke::MeshNormalDomain::Corner && (mesh->get_subdivision_type() != Mesh::SUBDIVISION_CATMULL_CLARK); /* If no faces, create empty mesh. */ @@ -937,7 +938,8 @@ static void create_mesh(Scene *scene, } } else { - std::fill(smooth, smooth + numtris, true); + /* If only face normals are needed, all faces are sharp. */ + std::fill(smooth, smooth + numtris, normals_domain != blender::bke::MeshNormalDomain::Face); } if (use_loop_normals && !corner_normals.is_empty()) { -- 2.30.2 From 22bcc0e96d1d881b873eff88e610459d2936240b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 19 Oct 2023 17:56:37 +0200 Subject: [PATCH 84/85] Fix obj import tests --- source/blender/io/wavefront_obj/tests/obj_importer_tests.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index 4ea8fc5689b..869a23ca3a3 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -137,7 +137,9 @@ class obj_importer_test : public BlendfileLoadingBaseTest { const Span positions = mesh->vert_positions(); EXPECT_V3_NEAR(positions.first(), exp.vert_first, 0.0001f); EXPECT_V3_NEAR(positions.last(), exp.vert_last, 0.0001f); - const float3 *lnors = mesh->corner_normals().data(); + const float3 *lnors = mesh->normals_domain() == bke::MeshNormalDomain::Corner ? + mesh->corner_normals().data() : + nullptr; float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0); EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f); const float2 *mloopuv = static_cast( -- 2.30.2 From bc4dd268c185818465ea68c8b50bb3369146cb0a Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 20 Oct 2023 15:19:17 +0200 Subject: [PATCH 85/85] Attempt to fix windows build error --- source/blender/blenkernel/intern/mesh_normals.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index cdbe325c9b7..640075689f3 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -390,7 +390,7 @@ blender::Span Mesh::corner_normals() const using namespace blender::bke; this->runtime->corner_normals_cache.ensure([&](Vector &r_data) { r_data.reinitialize(this->totloop); - const OffsetIndices faces = this->faces(); + const OffsetIndices faces = this->faces(); switch (this->normals_domain()) { case MeshNormalDomain::Point: { array_utils::gather(this->vert_normals(), this->corner_verts(), r_data.as_mutable_span()); -- 2.30.2