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).
This commit is contained in:
@@ -23,21 +23,29 @@ class RandomNumberGenerator;
|
||||
|
||||
namespace blender::bke::mesh_surface_sample {
|
||||
|
||||
void sample_point_attribute(const Mesh &mesh,
|
||||
void sample_point_attribute(Span<int> corner_verts,
|
||||
Span<MLoopTri> looptris,
|
||||
Span<int> looptri_indices,
|
||||
Span<float3> bary_coords,
|
||||
const GVArray &src,
|
||||
IndexMask mask,
|
||||
GMutableSpan dst);
|
||||
|
||||
void sample_corner_attribute(const Mesh &mesh,
|
||||
void sample_corner_attribute(Span<MLoopTri> looptris,
|
||||
Span<int> looptri_indices,
|
||||
Span<float3> bary_coords,
|
||||
const GVArray &src,
|
||||
IndexMask mask,
|
||||
GMutableSpan dst);
|
||||
|
||||
void sample_face_attribute(const Mesh &mesh,
|
||||
void sample_corner_normals(Span<MLoopTri> looptris,
|
||||
Span<int> looptri_indices,
|
||||
Span<float3> bary_coords,
|
||||
Span<float3> src,
|
||||
IndexMask mask,
|
||||
MutableSpan<float3> dst);
|
||||
|
||||
void sample_face_attribute(Span<MLoopTri> looptris,
|
||||
Span<int> 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<typename T>
|
||||
inline T sample_corner_attrribute_with_bary_coords(const float3 &bary_weights,
|
||||
const MLoopTri &looptri,
|
||||
const VArray<T> &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
|
||||
|
||||
@@ -10,111 +10,103 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
namespace blender::bke::mesh_surface_sample {
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh,
|
||||
BLI_NOINLINE static void sample_point_attribute(const Span<int> corner_verts,
|
||||
const Span<MLoopTri> looptris,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> bary_coords,
|
||||
const VArray<T> &src,
|
||||
const IndexMask mask,
|
||||
const MutableSpan<T> dst)
|
||||
{
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
const Span<MLoopTri> 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<int> corner_verts,
|
||||
const Span<MLoopTri> looptris,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> 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<T>(
|
||||
mesh, looptri_indices, bary_coords, src.typed<T>(), mask, dst.typed<T>());
|
||||
sample_point_attribute<T>(corner_verts,
|
||||
looptris,
|
||||
looptri_indices,
|
||||
bary_coords,
|
||||
src.typed<T>(),
|
||||
mask,
|
||||
dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void sample_corner_attribute(const Mesh &mesh,
|
||||
BLI_NOINLINE static void sample_corner_attribute(const Span<MLoopTri> looptris,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> bary_coords,
|
||||
const VArray<T> &src,
|
||||
const IndexMask mask,
|
||||
const MutableSpan<T> dst)
|
||||
{
|
||||
const Span<MLoopTri> 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<MLoopTri> looptris,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> bary_coords,
|
||||
const Span<float3> src,
|
||||
const IndexMask mask,
|
||||
const MutableSpan<float3> 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<MLoopTri> looptris,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> 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<T>(
|
||||
mesh, looptri_indices, bary_coords, src.typed<T>(), mask, dst.typed<T>());
|
||||
looptris, looptri_indices, bary_coords, src.typed<T>(), mask, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void sample_face_attribute(const Mesh &mesh,
|
||||
void sample_face_attribute(const Span<MLoopTri> looptris,
|
||||
const Span<int> looptri_indices,
|
||||
const VArray<T> &src,
|
||||
const IndexMask mask,
|
||||
const MutableSpan<T> dst)
|
||||
{
|
||||
const Span<MLoopTri> 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<MLoopTri> looptris,
|
||||
const Span<int> 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<T>(mesh, looptri_indices, src.typed<T>(), mask, dst.typed<T>());
|
||||
sample_face_attribute<T>(looptris, looptri_indices, src.typed<T>(), mask, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -161,14 +152,8 @@ Span<float3> MeshAttributeInterpolator::ensure_barycentric_coords()
|
||||
const Span<MLoopTri> 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. */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves,
|
||||
/* Find surface normal at root points. */
|
||||
Array<float3> new_normals_su(added_curves_num);
|
||||
bke::mesh_surface_sample::sample_corner_attribute(
|
||||
*inputs.surface,
|
||||
inputs.surface_looptris,
|
||||
looptri_indices,
|
||||
bary_coords,
|
||||
VArray<float3>::ForSpan(inputs.corner_normals_su),
|
||||
|
||||
@@ -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 *>(&mesh), nullptr, reinterpret_cast<float(*)[3]>(corner_normals.data()));
|
||||
|
||||
const Span<MLoopTri> 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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user