[Bf-blender-cvs] [42c974ee021] particle-solver-dev: Fixed "popping" and some tunneling issues with moving colliders
Sebastian Parborg
noreply at git.blender.org
Thu Jun 4 19:15:37 CEST 2020
Commit: 42c974ee02105f9d06c32f2167fc2e65c6e909ad
Author: Sebastian Parborg
Date: Thu Jun 4 19:15:09 2020 +0200
Branches: particle-solver-dev
https://developer.blender.org/rB42c974ee02105f9d06c32f2167fc2e65c6e909ad
Fixed "popping" and some tunneling issues with moving colliders
===================================================================
M source/blender/simulations/bparticles/simulate.cpp
===================================================================
diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp
index a35bbd9c69a..87c1c507d74 100644
--- a/source/blender/simulations/bparticles/simulate.cpp
+++ b/source/blender/simulations/bparticles/simulate.cpp
@@ -66,7 +66,8 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points
std::array<std::pair<float3, float3>, 3> &tri_points,
float radius,
float3 &coll_normal,
- float3 &hit_bary_weights)
+ float3 &hit_bary_weights,
+ float3 &point_on_plane)
{
std::array<float3, 3> cur_tri_points;
float t0, t1, dt_init, d0, d1, dd;
@@ -80,25 +81,48 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points
t1 = dt_init;
d1 = 0.f;
+ /* particle already inside face, so report collision */
+ if (d0 <= COLLISION_ZERO) {
+ p = particle_points.first;
+ // Save barycentric weight for velocity calculation later
+ interp_weights_tri_v3(
+ hit_bary_weights, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2], p);
+
+ normal_from_closest_point_to_tri(
+ coll_normal, p, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
+ // TODO clean up
+ float3 point = p;
+ float3 normal = coll_normal;
+ float3 p2;
+ closest_on_tri_to_point_v3(p2, point, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
+ float new_d = (p2 - point).length();
+ if (new_d < radius + COLLISION_MIN_DISTANCE) {
+ // printf("too close!\n");
+ point_on_plane = p2 + normal * (radius + COLLISION_MIN_DISTANCE);
+ }
+ else {
+ point_on_plane = p;
+ }
+
+ // printf("t = 0, d0 = %f\n", d0);
+
+ // print_v3("p", p);
+ // print_v3("first", particle_points.first);
+ // print_v3("second", particle_points.second);
+ // print_v3("point on plane", point_on_plane);
+
+ return 0.f;
+ }
+
for (int iter = 0; iter < 10; iter++) { //, itersum++) {
+ // printf("\nt1 %f\n", t1);
+
/* get current location */
collision_interpolate_element(tri_points, cur_tri_points, t1);
p = float3::interpolate(particle_points.first, particle_points.second, t1);
d1 = distance_to_tri(p, cur_tri_points, radius);
- /* particle already inside face, so report collision */
- if (iter == 0 && d0 <= COLLISION_ZERO) {
- p = particle_points.first;
- // Save barycentric weight for velocity calculation later
- interp_weights_tri_v3(
- hit_bary_weights, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2], p);
-
- normal_from_closest_point_to_tri(
- coll_normal, p, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
- return 0.f;
- }
-
/* Zero gradient (no movement relative to element). Can't step from
* here. */
if (d1 == d0) {
@@ -117,6 +141,47 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points
}
}
+ if (d1 <= COLLISION_ZERO) {
+ if (t1 >= -COLLISION_ZERO && t1 <= 1.f) {
+ // Save barycentric weight for velocity calculation later
+ interp_weights_tri_v3(
+ hit_bary_weights, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2], p);
+
+ normal_from_closest_point_to_tri(
+ coll_normal, p, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
+
+ // TODO clean up
+ float3 point = p;
+ float3 normal = coll_normal;
+ float3 p2;
+ closest_on_tri_to_point_v3(
+ p2, point, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
+ float new_d = (p2 - point).length();
+ if (new_d < radius + COLLISION_MIN_DISTANCE) {
+ // TODO should probably always do this
+ // printf("too close!\n");
+ point_on_plane = p2 + normal * (radius + COLLISION_MIN_DISTANCE);
+ }
+ else {
+ point_on_plane = p;
+ }
+
+ // printf("old_d %f\n", new_d);
+ // printf("new_d %f\n", (point_on_plane - p2).length());
+ // print_v3("p", p);
+ // print_v3("first", particle_points.first);
+ // print_v3("second", particle_points.second);
+ // print_v3("point on plane", point_on_plane);
+
+ CLAMP(t1, 0.f, 1.f);
+ return t1;
+ }
+ else {
+ return -1.f;
+ }
+ }
+
+ /* Derive next time step */
dd = (t1 - t0) / (d1 - d0);
t0 = t1;
@@ -137,23 +202,6 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points
else if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f)) {
return -1.f;
}
-
- if (d1 <= COLLISION_ZERO) {
- if (t1 >= -COLLISION_ZERO && t1 <= 1.f) {
- // Save barycentric weight for velocity calculation later
- interp_weights_tri_v3(
- hit_bary_weights, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2], p);
-
- normal_from_closest_point_to_tri(
- coll_normal, p, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
-
- CLAMP(t1, 0.f, 1.f);
- return t1;
- }
- else {
- return -1.f;
- }
- }
}
return -1.0;
}
@@ -204,6 +252,17 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist - COLLISION_MIN_DISTANCE);
normal_from_closest_point_to_tri(hit->no, hit->co, v0, v1, v2);
+ // TODO clean up (unify this into a function and using it in the rapson code)
+ float3 point = hit->co;
+ float3 normal = hit->no;
+ float3 p2;
+ closest_on_tri_to_point_v3(p2, point, v0, v1, v2);
+ float new_d = (p2 - point).length();
+ if (new_d < ray->radius + COLLISION_MIN_DISTANCE) {
+ // printf("too close!\n");
+ point = p2 + normal * (ray->radius + COLLISION_MIN_DISTANCE);
+ copy_v3_v3(hit->co, point);
+ }
}
return;
}
@@ -231,9 +290,14 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
tri_points[2].first = new_start_points[2];
}
+ float3 point_on_plane;
+ /* TODO this is to silence gcc "may be use un-intied" warnings. Look into if I missed a case
+ * where this is actually true */
+ zero_v3(point_on_plane);
+
// Check if we get hit by the moving object
float coll_time = collision_newton_rhapson(
- rd->particle_points, tri_points, ray->radius, coll_normal, hit_bary_weights);
+ rd->particle_points, tri_points, ray->radius, coll_normal, hit_bary_weights, point_on_plane);
dist = float3::distance(rd->particle_points.first, rd->particle_points.second) * coll_time;
@@ -252,21 +316,10 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
rd->hit_vel += (tri_points[i].second - tri_points[i].first) * hit_bary_weights[i] /
rd->duration;
}
- // rd->hit_vel = float3(0, 0, 5.0);
-
- // Subract COLLISION_MIN_DISTANCE from the distance to make sure that we do not collide with
- // the exact same point if the particle does not have time to move away from the collision
- // point.
- float pad_dist = COLLISION_MIN_DISTANCE;
- if (dot_v3v3(rd->hit_vel, ray->direction) > 0) {
- // The particle is traveling in the same direction as the collider, add distance instead of
- // subtracting it.
- pad_dist *= -1.0f;
- }
+ // printf("====Best hit so far!\n");
- madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist - pad_dist);
- // zero_v3(hit->co);
+ copy_v3_v3(hit->co, point_on_plane);
copy_v3_v3(hit->no, coll_normal);
}
}
@@ -298,6 +351,10 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
// cloth_bvh_collision
for (uint pindex : IndexRange(amount)) {
+ // if (pindex != 84 /* && pindex != 357 && pindex != 378*/) {
+ // continue;
+ //}
+
float mass = 1.0f;
float duration = remaining_durations[pindex];
bool collided;
@@ -336,7 +393,7 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
hit.index = -1;
hit.dist = max_move;
// TODO the particle radius seems a bit flaky with higher distances?
- float particle_radius = 0.01f;
+ float particle_radius = 0.05f;
float3 start = positions[pindex];
float3 dir = velocities[pindex].normalized();
@@ -377,17 +434,21 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
prev_collider = collmd;
prev_hit_idx = hit.index;
collided = true;
- // TODO need to make sure that we do not try to collide with the same triangle during
- // the next subframe. Only applicable for moving colliders of course...
}
if (collided) {
- positions[pindex] = best_hit.co;
+ // dead_state[pindex] = true;
+ float3 normal = best_hit.no;
+
+ // printf("==== COLLIDED ====\n");
// print_v3("best_hit", best_hit.co);
- //
- // dot normal from vt with hit.co - start to see which way to deflect the particle
- float3 normal = best_hit.no;
+ // print_v3("hit normal", normal);
+ // print_v3("hit velo", best_hit_vel);
+ // print_v3("part velo", velocities[pindex]);
+
+ // TODO now that we calculate the normal in a smooth way, we should not need to have a
+ // "n_v" vector to get a correct normal vector for the bounce.
float3 n_v = float3::project(velocities[pindex], normal);
n_v = n_v.normalized();
@@ -398,7 +459,7 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
float3 hit_normal_velo = float3::project(best_hit_vel, n_v);
float3 local_velo = velocities[pindex] - hit_normal_velo;
- float dampening = 0.1f;
+ float dampening = 0.5f;
// Add the dampening factor
local_velo *= (1.0f - dampening);
@@ -429,9 +490,27 @@ BLI_NOINLINE static
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list