Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mesh_sample.cc
| Show All 15 Lines | |||||
| template<typename T> | template<typename T> | ||||
| BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh, | BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh, | ||||
| const Span<int> looptri_indices, | const Span<int> looptri_indices, | ||||
| const Span<float3> bary_coords, | const Span<float3> bary_coords, | ||||
| const VArray<T> &src, | const VArray<T> &src, | ||||
| const IndexMask mask, | const IndexMask mask, | ||||
| const MutableSpan<T> dst) | const MutableSpan<T> dst) | ||||
| { | { | ||||
| const Span<MLoop> loops = mesh.loops(); | const Span<int> corner_verts = mesh.corner_verts(); | ||||
| const Span<MLoopTri> looptris = mesh.looptris(); | const Span<MLoopTri> looptris = mesh.looptris(); | ||||
| for (const int i : mask) { | for (const int i : mask) { | ||||
| const int looptri_index = looptri_indices[i]; | const int looptri_index = looptri_indices[i]; | ||||
| const MLoopTri &looptri = looptris[looptri_index]; | const MLoopTri &looptri = looptris[looptri_index]; | ||||
| const float3 &bary_coord = bary_coords[i]; | const float3 &bary_coord = bary_coords[i]; | ||||
| const int v0_index = loops[looptri.tri[0]].v; | const int v0_index = corner_verts[looptri.tri[0]]; | ||||
| const int v1_index = loops[looptri.tri[1]].v; | const int v1_index = corner_verts[looptri.tri[1]]; | ||||
| const int v2_index = loops[looptri.tri[2]].v; | const int v2_index = corner_verts[looptri.tri[2]]; | ||||
| const T v0 = src[v0_index]; | const T v0 = src[v0_index]; | ||||
| const T v1 = src[v1_index]; | const T v1 = src[v1_index]; | ||||
| const T v2 = src[v2_index]; | const T v2 = src[v2_index]; | ||||
| const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); | const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); | ||||
| dst[i] = interpolated_value; | dst[i] = interpolated_value; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| if (!bary_coords_.is_empty()) { | if (!bary_coords_.is_empty()) { | ||||
| BLI_assert(bary_coords_.size() >= mask_.min_array_size()); | BLI_assert(bary_coords_.size() >= mask_.min_array_size()); | ||||
| return bary_coords_; | return bary_coords_; | ||||
| } | } | ||||
| bary_coords_.reinitialize(mask_.min_array_size()); | bary_coords_.reinitialize(mask_.min_array_size()); | ||||
| const Span<float3> positions = mesh_->vert_positions(); | const Span<float3> positions = mesh_->vert_positions(); | ||||
| const Span<MLoop> loops = mesh_->loops(); | const Span<int> corner_verts = mesh_->corner_verts(); | ||||
| const Span<MLoopTri> looptris = mesh_->looptris(); | const Span<MLoopTri> looptris = mesh_->looptris(); | ||||
| for (const int i : mask_) { | for (const int i : mask_) { | ||||
| const int looptri_index = looptri_indices_[i]; | const int looptri_index = looptri_indices_[i]; | ||||
| const MLoopTri &looptri = looptris[looptri_index]; | const MLoopTri &looptri = looptris[looptri_index]; | ||||
| const int v0_index = loops[looptri.tri[0]].v; | |||||
| const int v1_index = loops[looptri.tri[1]].v; | |||||
| const int v2_index = loops[looptri.tri[2]].v; | |||||
| interp_weights_tri_v3(bary_coords_[i], | interp_weights_tri_v3(bary_coords_[i], | ||||
| positions[v0_index], | positions[corner_verts[looptri.tri[0]]], | ||||
| positions[v1_index], | positions[corner_verts[looptri.tri[1]]], | ||||
| positions[v2_index], | positions[corner_verts[looptri.tri[2]]], | ||||
| positions_[i]); | positions_[i]); | ||||
| } | } | ||||
| return bary_coords_; | return bary_coords_; | ||||
| } | } | ||||
| Span<float3> MeshAttributeInterpolator::ensure_nearest_weights() | Span<float3> MeshAttributeInterpolator::ensure_nearest_weights() | ||||
| { | { | ||||
| if (!nearest_weights_.is_empty()) { | if (!nearest_weights_.is_empty()) { | ||||
| BLI_assert(nearest_weights_.size() >= mask_.min_array_size()); | BLI_assert(nearest_weights_.size() >= mask_.min_array_size()); | ||||
| return nearest_weights_; | return nearest_weights_; | ||||
| } | } | ||||
| nearest_weights_.reinitialize(mask_.min_array_size()); | nearest_weights_.reinitialize(mask_.min_array_size()); | ||||
| const Span<float3> positions = mesh_->vert_positions(); | const Span<float3> positions = mesh_->vert_positions(); | ||||
| const Span<MLoop> loops = mesh_->loops(); | const Span<int> corner_verts = mesh_->corner_verts(); | ||||
| const Span<MLoopTri> looptris = mesh_->looptris(); | const Span<MLoopTri> looptris = mesh_->looptris(); | ||||
| for (const int i : mask_) { | for (const int i : mask_) { | ||||
| const int looptri_index = looptri_indices_[i]; | const int looptri_index = looptri_indices_[i]; | ||||
| const MLoopTri &looptri = looptris[looptri_index]; | const MLoopTri &looptri = looptris[looptri_index]; | ||||
| const int v0_index = loops[looptri.tri[0]].v; | const float d0 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[0]]]); | ||||
| const int v1_index = loops[looptri.tri[1]].v; | const float d1 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[1]]]); | ||||
| const int v2_index = loops[looptri.tri[2]].v; | const float d2 = len_squared_v3v3(positions_[i], positions[corner_verts[looptri.tri[2]]]); | ||||
| const float d0 = len_squared_v3v3(positions_[i], positions[v0_index]); | |||||
| const float d1 = len_squared_v3v3(positions_[i], positions[v1_index]); | |||||
| const float d2 = len_squared_v3v3(positions_[i], positions[v2_index]); | |||||
| nearest_weights_[i] = MIN3_PAIR(d0, d1, d2, float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1)); | nearest_weights_[i] = MIN3_PAIR(d0, d1, d2, float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1)); | ||||
| } | } | ||||
| return nearest_weights_; | return nearest_weights_; | ||||
| } | } | ||||
| void MeshAttributeInterpolator::sample_data(const GVArray &src, | void MeshAttributeInterpolator::sample_data(const GVArray &src, | ||||
| const eAttrDomain domain, | const eAttrDomain domain, | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | int sample_surface_points_spherical(RandomNumberGenerator &rng, | ||||
| const float3 &sample_pos, | const float3 &sample_pos, | ||||
| const float sample_radius, | const float sample_radius, | ||||
| const float approximate_density, | const float approximate_density, | ||||
| Vector<float3> &r_bary_coords, | Vector<float3> &r_bary_coords, | ||||
| Vector<int> &r_looptri_indices, | Vector<int> &r_looptri_indices, | ||||
| Vector<float3> &r_positions) | Vector<float3> &r_positions) | ||||
| { | { | ||||
| const Span<float3> positions = mesh.vert_positions(); | const Span<float3> positions = mesh.vert_positions(); | ||||
| const Span<MLoop> loops = mesh.loops(); | const Span<int> corner_verts = mesh.corner_verts(); | ||||
| const Span<MLoopTri> looptris = mesh.looptris(); | const Span<MLoopTri> looptris = mesh.looptris(); | ||||
| const float sample_radius_sq = pow2f(sample_radius); | const float sample_radius_sq = pow2f(sample_radius); | ||||
| const float sample_plane_area = M_PI * sample_radius_sq; | const float sample_plane_area = M_PI * sample_radius_sq; | ||||
| /* Used for switching between two triangle sampling strategies. */ | /* Used for switching between two triangle sampling strategies. */ | ||||
| const float area_threshold = sample_plane_area; | const float area_threshold = sample_plane_area; | ||||
| const int old_num = r_bary_coords.size(); | const int old_num = r_bary_coords.size(); | ||||
| for (const int looptri_index : looptri_indices_to_sample) { | for (const int looptri_index : looptri_indices_to_sample) { | ||||
| const MLoopTri &looptri = looptris[looptri_index]; | const MLoopTri &looptri = looptris[looptri_index]; | ||||
| const float3 &v0 = positions[loops[looptri.tri[0]].v]; | const float3 &v0 = positions[corner_verts[looptri.tri[0]]]; | ||||
| const float3 &v1 = positions[loops[looptri.tri[1]].v]; | const float3 &v1 = positions[corner_verts[looptri.tri[1]]]; | ||||
| const float3 &v2 = positions[loops[looptri.tri[2]].v]; | const float3 &v2 = positions[corner_verts[looptri.tri[2]]]; | ||||
| const float looptri_area = area_tri_v3(v0, v1, v2); | const float looptri_area = area_tri_v3(v0, v1, v2); | ||||
| if (looptri_area < area_threshold) { | if (looptri_area < area_threshold) { | ||||
| /* The triangle is small compared to the sample radius. Sample by generating random | /* The triangle is small compared to the sample radius. Sample by generating random | ||||
| * barycentric coordinates. */ | * barycentric coordinates. */ | ||||
| const int amount = rng.round_probabilistic(approximate_density * looptri_area); | const int amount = rng.round_probabilistic(approximate_density * looptri_area); | ||||
| for ([[maybe_unused]] const int i : IndexRange(amount)) { | for ([[maybe_unused]] const int i : IndexRange(amount)) { | ||||
| ▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | int sample_surface_points_projected( | ||||
| const bool front_face_only, | const bool front_face_only, | ||||
| const int tries_num, | const int tries_num, | ||||
| const int max_points, | const int max_points, | ||||
| Vector<float3> &r_bary_coords, | Vector<float3> &r_bary_coords, | ||||
| Vector<int> &r_looptri_indices, | Vector<int> &r_looptri_indices, | ||||
| Vector<float3> &r_positions) | Vector<float3> &r_positions) | ||||
| { | { | ||||
| const Span<float3> positions = mesh.vert_positions(); | const Span<float3> positions = mesh.vert_positions(); | ||||
| const Span<MLoop> loops = mesh.loops(); | const Span<int> corner_verts = mesh.corner_verts(); | ||||
| const Span<MLoopTri> looptris = mesh.looptris(); | const Span<MLoopTri> looptris = mesh.looptris(); | ||||
| int point_count = 0; | int point_count = 0; | ||||
| for ([[maybe_unused]] const int _ : IndexRange(tries_num)) { | for ([[maybe_unused]] const int _ : IndexRange(tries_num)) { | ||||
| if (point_count == max_points) { | if (point_count == max_points) { | ||||
| break; | break; | ||||
| } | } | ||||
| Show All 25 Lines | if (front_face_only) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| } | } | ||||
| const int looptri_index = ray_hit.index; | const int looptri_index = ray_hit.index; | ||||
| const float3 pos = ray_hit.co; | const float3 pos = ray_hit.co; | ||||
| const float3 bary_coords = compute_bary_coord_in_triangle( | const float3 bary_coords = compute_bary_coord_in_triangle( | ||||
| positions, loops, looptris[looptri_index], pos); | positions, corner_verts, looptris[looptri_index], pos); | ||||
| r_positions.append(pos); | r_positions.append(pos); | ||||
| r_bary_coords.append(bary_coords); | r_bary_coords.append(bary_coords); | ||||
| r_looptri_indices.append(looptri_index); | r_looptri_indices.append(looptri_index); | ||||
| point_count++; | point_count++; | ||||
| } | } | ||||
| return point_count; | return point_count; | ||||
| } | } | ||||
| float3 compute_bary_coord_in_triangle(const Span<float3> vert_positions, | float3 compute_bary_coord_in_triangle(const Span<float3> vert_positions, | ||||
| const Span<MLoop> loops, | const Span<int> corner_verts, | ||||
| const MLoopTri &looptri, | const MLoopTri &looptri, | ||||
| const float3 &position) | const float3 &position) | ||||
| { | { | ||||
| const float3 &v0 = vert_positions[loops[looptri.tri[0]].v]; | const float3 &v0 = vert_positions[corner_verts[looptri.tri[0]]]; | ||||
| const float3 &v1 = vert_positions[loops[looptri.tri[1]].v]; | const float3 &v1 = vert_positions[corner_verts[looptri.tri[1]]]; | ||||
| const float3 &v2 = vert_positions[loops[looptri.tri[2]].v]; | const float3 &v2 = vert_positions[corner_verts[looptri.tri[2]]]; | ||||
| float3 bary_coords; | float3 bary_coords; | ||||
| interp_weights_tri_v3(bary_coords, v0, v1, v2, position); | interp_weights_tri_v3(bary_coords, v0, v1, v2, position); | ||||
| return bary_coords; | return bary_coords; | ||||
| } | } | ||||
| } // namespace blender::bke::mesh_surface_sample | } // namespace blender::bke::mesh_surface_sample | ||||