From bec033e057836755a9dcb0100367262e5ad1f6b6 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 28 Apr 2023 14:44:08 -0400 Subject: [PATCH] Cleanup: Simplify and deduplicate mesh sampling code It arguably reads easier if simple operations like reading from indices of an array don't each get their own line. Also the same corner attribute sampling was repeated in a few places. And add a new function to sample normals from the corner domain, and use lower level arguments to the lower level functions (i.e. not just a mesh pointer, but the necessary data arrays). --- source/blender/blenkernel/BKE_mesh_sample.hh | 25 ++++- .../blender/blenkernel/intern/mesh_sample.cc | 104 ++++++++---------- .../editors/curves/intern/curves_ops.cc | 19 +--- .../geometry/intern/add_curves_on_mesh.cc | 2 +- .../node_geo_distribute_points_on_faces.cc | 44 +++----- 5 files changed, 90 insertions(+), 104 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh index 3f181d0ae28..d5fb841545b 100644 --- a/source/blender/blenkernel/BKE_mesh_sample.hh +++ b/source/blender/blenkernel/BKE_mesh_sample.hh @@ -23,21 +23,29 @@ class RandomNumberGenerator; namespace blender::bke::mesh_surface_sample { -void sample_point_attribute(const Mesh &mesh, +void sample_point_attribute(Span corner_verts, + Span looptris, Span looptri_indices, Span bary_coords, const GVArray &src, IndexMask mask, GMutableSpan dst); -void sample_corner_attribute(const Mesh &mesh, +void sample_corner_attribute(Span looptris, Span looptri_indices, Span bary_coords, const GVArray &src, IndexMask mask, GMutableSpan dst); -void sample_face_attribute(const Mesh &mesh, +void sample_corner_normals(Span looptris, + Span looptri_indices, + Span bary_coords, + Span src, + IndexMask mask, + MutableSpan dst); + +void sample_face_attribute(Span looptris, Span looptri_indices, const GVArray &src, IndexMask mask, @@ -143,4 +151,15 @@ inline T sample_corner_attrribute_with_bary_coords(const float3 &bary_weights, corner_attribute[looptri.tri[2]]); } +template +inline T sample_corner_attrribute_with_bary_coords(const float3 &bary_weights, + const MLoopTri &looptri, + const VArray &corner_attribute) +{ + return attribute_math::mix3(bary_weights, + corner_attribute[looptri.tri[0]], + corner_attribute[looptri.tri[1]], + corner_attribute[looptri.tri[2]]); +} + } // namespace blender::bke::mesh_surface_sample diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 4c7474e244c..f843263e739 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -10,111 +10,103 @@ #include "DNA_meshdata_types.h" #include "BLI_rand.hh" +#include "BLI_task.hh" namespace blender::bke::mesh_surface_sample { 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, const IndexMask mask, const MutableSpan dst) { - const Span corner_verts = mesh.corner_verts(); - const Span looptris = mesh.looptris(); - for (const int i : mask) { - const int looptri_index = looptri_indices[i]; - const MLoopTri &looptri = looptris[looptri_index]; - 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; + const MLoopTri &tri = looptris[looptri_indices[i]]; + 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]]]); } } -void sample_point_attribute(const Mesh &mesh, +void sample_point_attribute(const Span corner_verts, + const Span looptris, const Span looptri_indices, const Span bary_coords, const GVArray &src, const IndexMask mask, const GMutableSpan dst) { - BLI_assert(src.size() == mesh.totvert); BLI_assert(src.type() == dst.type()); 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(corner_verts, + 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 float3 &bary_coord = bary_coords[i]; - - 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; + const MLoopTri &tri = looptris[looptri_indices[i]]; + dst[i] = sample_corner_attrribute_with_bary_coords(bary_coords[i], tri, src); } } -void sample_corner_attribute(const Mesh &mesh, +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 MLoopTri &tri = looptris[looptri_indices[i]]; + const float3 value = sample_corner_attrribute_with_bary_coords(bary_coords[i], tri, src); + dst[i] = math::normalize(value); + } +} + +void sample_corner_attribute(const Span looptris, const Span looptri_indices, const Span bary_coords, const GVArray &src, const IndexMask mask, const GMutableSpan dst) { - BLI_assert(src.size() == mesh.totloop); BLI_assert(src.type() == dst.type()); const CPPType &type = src.type(); 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()); + 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]; @@ -123,19 +115,18 @@ void sample_face_attribute(const Mesh &mesh, } } -void sample_face_attribute(const Mesh &mesh, +void sample_face_attribute(const Span looptris, const Span looptri_indices, const GVArray &src, const IndexMask mask, const GMutableSpan dst) { - BLI_assert(src.size() == mesh.totpoly); BLI_assert(src.type() == dst.type()); 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(looptris, looptri_indices, src.typed(), mask, dst.typed()); }); } @@ -161,14 +152,8 @@ Span MeshAttributeInterpolator::ensure_barycentric_coords() const Span looptris = mesh_->looptris(); for (const int i : mask_) { - const int looptri_index = looptri_indices_[i]; - const MLoopTri &looptri = looptris[looptri_index]; - - interp_weights_tri_v3(bary_coords_[i], - positions[corner_verts[looptri.tri[0]]], - positions[corner_verts[looptri.tri[1]]], - positions[corner_verts[looptri.tri[2]]], - positions_[i]); + const MLoopTri &tri = looptris[looptri_indices_[i]]; + bary_coords_[i] = compute_bary_coord_in_triangle(positions, corner_verts, tri, positions_[i]); } return bary_coords_; } @@ -223,13 +208,14 @@ void MeshAttributeInterpolator::sample_data(const GVArray &src, /* Interpolate the source attributes on the surface. */ switch (domain) { case ATTR_DOMAIN_POINT: - sample_point_attribute(*mesh_, looptri_indices_, weights, src, mask_, dst); + sample_point_attribute( + mesh_->corner_verts(), mesh_->looptris(), looptri_indices_, weights, src, mask_, dst); break; case ATTR_DOMAIN_FACE: - sample_face_attribute(*mesh_, looptri_indices_, src, mask_, dst); + sample_face_attribute(mesh_->looptris(), looptri_indices_, src, mask_, dst); break; case ATTR_DOMAIN_CORNER: - sample_corner_attribute(*mesh_, looptri_indices_, weights, src, mask_, dst); + sample_corner_attribute(mesh_->looptris(), looptri_indices_, weights, src, mask_, dst); break; case ATTR_DOMAIN_EDGE: /* Not yet supported. */ diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index c0aeb92e473..75be2a931c3 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -33,6 +33,7 @@ #include "BKE_mesh.hh" #include "BKE_mesh_legacy_convert.h" #include "BKE_mesh_runtime.h" +#include "BKE_mesh_sample.hh" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_particle.h" @@ -632,19 +633,11 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, } if (!surface_uv_map.is_empty()) { - const MLoopTri &looptri = surface_looptris[looptri_index]; - const int corner0 = looptri.tri[0]; - const int corner1 = looptri.tri[1]; - const int corner2 = looptri.tri[2]; - const float2 &uv0 = surface_uv_map[corner0]; - const float2 &uv1 = surface_uv_map[corner1]; - const float2 &uv2 = surface_uv_map[corner2]; - const float3 &p0_su = surface_positions[corner_verts[corner0]]; - const float3 &p1_su = surface_positions[corner_verts[corner1]]; - const float3 &p2_su = surface_positions[corner_verts[corner2]]; - float3 bary_coords; - interp_weights_tri_v3(bary_coords, p0_su, p1_su, p2_su, new_first_point_pos_su); - const float2 uv = attribute_math::mix3(bary_coords, uv0, uv1, uv2); + const MLoopTri &tri = surface_looptris[looptri_index]; + const float3 bary_coords = bke::mesh_surface_sample::compute_bary_coord_in_triangle( + surface_positions, corner_verts, tri, new_first_point_pos_su); + const float2 uv = bke::mesh_surface_sample::sample_corner_attrribute_with_bary_coords( + bary_coords, tri, surface_uv_map); surface_uv_coords[curve_i] = uv; } } diff --git a/source/blender/geometry/intern/add_curves_on_mesh.cc b/source/blender/geometry/intern/add_curves_on_mesh.cc index 1ba107be59a..55ba55577b8 100644 --- a/source/blender/geometry/intern/add_curves_on_mesh.cc +++ b/source/blender/geometry/intern/add_curves_on_mesh.cc @@ -340,7 +340,7 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves, /* Find surface normal at root points. */ Array new_normals_su(added_curves_num); bke::mesh_surface_sample::sample_corner_attribute( - *inputs.surface, + inputs.surface_looptris, looptri_indices, bary_coords, VArray::ForSpan(inputs.corner_normals_su), 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 07c77dd215f..46adc21bfeb 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 @@ -255,7 +255,8 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, { switch (source_domain) { case ATTR_DOMAIN_POINT: { - bke::mesh_surface_sample::sample_point_attribute(mesh, + bke::mesh_surface_sample::sample_point_attribute(mesh.corner_verts(), + mesh.looptris(), looptri_indices, bary_coords, source_data, @@ -264,7 +265,7 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, break; } case ATTR_DOMAIN_CORNER: { - bke::mesh_surface_sample::sample_corner_attribute(mesh, + bke::mesh_surface_sample::sample_corner_attribute(mesh.looptris(), looptri_indices, bary_coords, source_data, @@ -273,8 +274,11 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, break; } case ATTR_DOMAIN_FACE: { - bke::mesh_surface_sample::sample_face_attribute( - mesh, looptri_indices, source_data, IndexMask(output_data.size()), output_data); + bke::mesh_surface_sample::sample_face_attribute(mesh.looptris(), + looptri_indices, + source_data, + IndexMask(output_data.size()), + output_data); break; } default: { @@ -298,25 +302,19 @@ BLI_NOINLINE static void propagate_existing_attributes( const AttributeIDRef attribute_id = entry.key; const eCustomDataType output_data_type = entry.value.data_type; - GAttributeReader source_attribute = mesh_attributes.lookup(attribute_id); - if (!source_attribute) { + GAttributeReader src = mesh_attributes.lookup(attribute_id); + if (!src) { continue; } - /* The output domain is always #ATTR_DOMAIN_POINT, since we are creating a point cloud. */ - GSpanAttributeWriter attribute_out = point_attributes.lookup_or_add_for_write_only_span( + GSpanAttributeWriter dst = point_attributes.lookup_or_add_for_write_only_span( attribute_id, ATTR_DOMAIN_POINT, output_data_type); - if (!attribute_out) { + if (!dst) { continue; } - interpolate_attribute(mesh, - bary_coords, - looptri_indices, - source_attribute.domain, - source_attribute.varray, - attribute_out.span); - attribute_out.finish(); + interpolate_attribute(mesh, bary_coords, looptri_indices, src.domain, src.varray, dst.span); + dst.finish(); } } @@ -337,19 +335,9 @@ static void compute_normal_outputs(const Mesh &mesh, const_cast(&mesh), nullptr, reinterpret_cast(corner_normals.data())); 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; - } + bke::mesh_surface_sample::sample_corner_normals( + looptris, looptri_indices, bary_coords, corner_normals, range, r_normals); }); }