[Bf-blender-cvs] [fb919408848] particle-solver-dev: Calculate normals from collision triangles using the closest point

Sebastian Parborg noreply at git.blender.org
Tue Jun 2 16:42:36 CEST 2020


Commit: fb919408848c35df4bbb2cd2eae5ae0ab013c21f
Author: Sebastian Parborg
Date:   Tue Jun 2 16:42:08 2020 +0200
Branches: particle-solver-dev
https://developer.blender.org/rBfb919408848c35df4bbb2cd2eae5ae0ab013c21f

Calculate normals from collision triangles using the closest point

===================================================================

M	source/blender/simulations/bparticles/simulate.cpp

===================================================================

diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp
index a99a5c347a1..a35bbd9c69a 100644
--- a/source/blender/simulations/bparticles/simulate.cpp
+++ b/source/blender/simulations/bparticles/simulate.cpp
@@ -30,6 +30,19 @@ using FN::CPPType;
 #define COLLISION_MIN_RADIUS 0.001f     // TODO check if this is needed
 #define COLLISION_MIN_DISTANCE 0.0001f  // TODO check if this is needed
 #define COLLISION_ZERO 0.00001f
+
+static void normal_from_closest_point_to_tri(
+    float no[3], const float p[3], const float v0[3], const float v1[3], const float v2[3])
+{
+  // Calculate the normal using the closest point on the triangle. This makes sure that
+  // particles can collide and be deflected in the correct direction when colliding with verts
+  // or edges of the triangle.
+  float point_on_tri[3];
+  closest_on_tri_to_point_v3(point_on_tri, p, v0, v1, v2);
+  sub_v3_v3v3(no, p, point_on_tri);
+  normalize_v3(no);
+}
+
 static float distance_to_tri(float3 &p, std::array<float3, 3> &cur_tri_points, float radius)
 {
   float3 closest_point;
@@ -81,7 +94,8 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points
       interp_weights_tri_v3(
           hit_bary_weights, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2], p);
 
-      normal_tri_v3(coll_normal, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
+      normal_from_closest_point_to_tri(
+          coll_normal, p, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
       return 0.f;
     }
 
@@ -130,7 +144,8 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points
         interp_weights_tri_v3(
             hit_bary_weights, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2], p);
 
-        normal_tri_v3(coll_normal, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]);
+        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;
@@ -188,7 +203,7 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
       // point.
       madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist - COLLISION_MIN_DISTANCE);
 
-      normal_tri_v3(hit->no, v0, v1, v2);
+      normal_from_closest_point_to_tri(hit->no, hit->co, v0, v1, v2);
     }
     return;
   }
@@ -230,12 +245,6 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
     // We have a collision!
     hit->index = index;
     hit->dist = dist;
-    // 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.
-    madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist - COLLISION_MIN_DISTANCE);
-    // zero_v3(hit->co);
-    copy_v3_v3(hit->no, coll_normal);
 
     // Calculate the velocity of the point we hit
     zero_v3(rd->hit_vel);
@@ -244,6 +253,21 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
                      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;
+    }
+
+    madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist - pad_dist);
+    // zero_v3(hit->co);
+    copy_v3_v3(hit->no, coll_normal);
   }
 }
 
@@ -282,7 +306,9 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
     // Update the velocities here so that the potential distance traveled is correct in the
     // collision check.
     velocities[pindex] += duration * forces[pindex] * mass;
-    // TODO check if there is issues with moving colliders and particles with 0 velocity
+    // TODO check if there is issues with moving colliders and particles with 0 velocity.
+    // (There is issues with particles with zero velocity as they will not collide with anything if
+    // the ray lenght is 0.
 
     // Check if any 'collobjs' collide with the particles here
     if (colliders.size() != 0) {
@@ -325,7 +351,7 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
           rd.start_time = 1.0 - duration / remaining_durations[pindex];
 
           // TODO perhaps have two callbacks and check for static colider here instead?
-          // So, if statis use callback A otherwise B
+          // So, if static use callback A otherwise B
           BLI_bvhtree_ray_cast_ex(collmd->bvhtree,
                                   start,
                                   dir,
@@ -372,15 +398,18 @@ 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.5f;
+          float dampening = 0.1f;
           // Add the dampening factor
           local_velo *= (1.0f - dampening);
 
           float normal_dot = dot_v3v3(n_v, local_velo) / hit_normal_velo.length();
           // printf("normal dot %f\n", normal_dot);
           if (normal_dot < 1.0f) {
+            // We are not moving fast enough away from the collider. Make sure that we have at
+            // least the same speed as it to avoid tunneling.
             // TODO Dampening messes this calulcation up as we assume that local_velo is just:
-            // "velocities[pindex] - hit_normal_velo" printf("trigger\n");
+            // "velocities[pindex] - hit_normal_velo"
+            // printf("trigger\n");
             local_velo -= (1.0 + normal_dot) * hit_normal_velo;
           }
 
@@ -407,6 +436,9 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
           // print_v3("vel_post", velocities[pindex]);
           //}
 
+          // TODO add a check here to see if we are inside the collider (current pos on the normal
+          // is less than radius)
+
           // Calculate the remaining duration
           // printf("old dur: %f\n", duration);
           duration -= duration * (best_hit.dist / max_move);



More information about the Bf-blender-cvs mailing list