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); }); }