Curves: initial surface collision for curves sculpt mode #104469

Merged
Jacques Lucke merged 29 commits from JacquesLucke/blender:temp-curves-surface-collision into main 2023-02-11 13:46:39 +01:00
1 changed files with 21 additions and 5 deletions
Showing only changes of commit d359dc4648 - Show all commits

View File

@ -62,18 +62,23 @@ void solve_length_and_collision_constraints(const OffsetIndices<int> points_by_c
BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); });
const float radius = 0.001f;
const int max_collisions = 10;
const int max_collisions = 5;
threading::parallel_for(curve_selection.index_range(), 64, [&](const IndexRange range) {
for (const int curve_i : curve_selection.slice(range)) {
const IndexRange points = points_by_curve[curve_i];
/* Sometimes not all collisions can be handled. This happens relatively rarely, but if it
* happens it's better to just not to move the curve instead of going into the surface. */
bool revert_curve = false;
for (const int point_i : points.drop_front(1)) {
const float goal_segment_length_cu = segment_lengths_cu[point_i - 1];
const float3 &prev_pos_cu = positions_cu[point_i - 1];
const float3 &start_pos_cu = start_positions_cu[point_i];
int used_iterations = 0;
for ([[maybe_unused]] const int iteration : IndexRange(max_collisions)) {
used_iterations++;
const float3 &old_pos_cu = positions_cu[point_i];
if (start_pos_cu == old_pos_cu) {
/* The point did not move, done. */
@ -93,18 +98,22 @@ void solve_length_and_collision_constraints(const OffsetIndices<int> points_by_c
BLI_bvhtree_ray_cast(surface_bvh.tree,
start_pos_su,
ray_direction_su,
0.0f,
radius,
&hit,
surface_bvh.raycast_callback,
&surface_bvh);
if (hit.index == -1) {
break;
}
/* The point was moved through a surface. Now put it back on the correct side of the
* surface and slide it on the surface to keep the length the same. */
const float3 hit_pos_su = hit.co;
const float3 hit_normal_su = hit.no;
if (math::dot(hit_normal_su, ray_direction_su) > 0.0f) {
/* Moving from the inside to the outside is ok. */
break;
}
/* The point was moved through a surface. Now put it back on the correct side of the
* surface and slide it on the surface to keep the length the same. */
const float3 hit_pos_cu = transforms.surface_to_curves * hit_pos_su;
const float3 hit_normal_cu = math::normalize(transforms.surface_to_curves_normal *
@ -131,6 +140,13 @@ void solve_length_and_collision_constraints(const OffsetIndices<int> points_by_c
slide_direction_length_cu;
positions_cu[point_i] = plane_pos_cu + normalized_slide_direction_cu * slide_distance_cu;
}
if (used_iterations == max_collisions) {
JacquesLucke marked this conversation as resolved
Review

theory -> theorem?

`theory` -> `theorem`?
revert_curve = true;
break;
}
}
if (revert_curve) {
positions_cu.slice(points).copy_from(start_positions_cu.slice(points));
}
}
});