[Bf-blender-cvs] [de0983f3c47] particle-solver-dev: Use the triangle normal if the hit point lies inside the triangle

Sebastian Parborg noreply at git.blender.org
Thu Jun 25 13:25:30 CEST 2020


Commit: de0983f3c4780c2f1f48a7aa4b62622bec6d3952
Author: Sebastian Parborg
Date:   Thu Jun 25 13:24:53 2020 +0200
Branches: particle-solver-dev
https://developer.blender.org/rBde0983f3c4780c2f1f48a7aa4b62622bec6d3952

Use the triangle normal if the hit point lies inside the triangle

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

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

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

diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp
index e28891c89b1..bbf7e41cd4a 100644
--- a/source/blender/simulations/bparticles/simulate.cpp
+++ b/source/blender/simulations/bparticles/simulate.cpp
@@ -64,13 +64,37 @@ static void collision_interpolate_element(std::array<std::pair<float3, float3>,
 
 static void calc_hit_point_data_tri(float co[3],
                                     float no[3],
+                                    float w[3],
                                     const float v0[3],
                                     const float v1[3],
                                     const float v2[3],
                                     float offset)
 {
+  bool inside = true;
+
+  interp_weights_tri_v3(w, v0, v1, v2, co);
+
+  for (int i = 0; i < 3; i++) {
+    if (w[i] < 0.0f || w[i] > 1.0f) {
+      inside = false;
+      break;
+    }
+  }
   // Calculate normal of the point we hit.
-  normal_from_closest_point_to_tri(no, co, v0, v1, v2);
+  if (inside) {
+    // We are inside the triangle, use the triangle normal as this is more accurate than the
+    // calulated one below.
+    normal_tri_v3(no, v0, v1, v2);
+    // Make sure the normal is pointing in the right direction
+    float3 point_vec;
+    sub_v3_v3v3(point_vec, co, v0);
+    if (dot_v3v3(no, point_vec) < 0.0f) {
+      mul_v3_fl(no, -1.0f);
+    }
+  }
+  else {
+    normal_from_closest_point_to_tri(no, co, v0, v1, v2);
+  }
 
   // Calcualte a point that is not directly in contact with the current triangle. This is so we do
   // not stick to the surface as it will collide with the same triangle immediately next time we
@@ -109,12 +133,10 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points
   /* 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);
 
     calc_hit_point_data_tri(p,
                             coll_normal,
+                            hit_bary_weights,
                             cur_tri_points[0],
                             cur_tri_points[1],
                             cur_tri_points[2],
@@ -151,12 +173,10 @@ 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);
 
         calc_hit_point_data_tri(p,
                                 coll_normal,
+                                hit_bary_weights,
                                 cur_tri_points[0],
                                 cur_tri_points[1],
                                 cur_tri_points[2],
@@ -244,7 +264,9 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
       hit->dist = dist;
       madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
 
-      calc_hit_point_data_tri(hit->co, hit->no, v0, v1, v2, ray->radius + rd->radius_epsilon);
+      float3 w;
+
+      calc_hit_point_data_tri(hit->co, hit->no, w, v0, v1, v2, ray->radius + rd->radius_epsilon);
       // No dt info available for static collisions, will manually calculate this later.
       rd->rel_dt = 0.0f;
     }
@@ -465,7 +487,7 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
             // We didn't hit anything
             continue;
           }
-          if (!collmd->is_static && prev_collider == collmd && prev_hit_idx == hit.index) {
+          if (collmd->is_static && prev_collider == collmd && prev_hit_idx == hit.index) {
             // We collided with the same face twice in a row.
             // Skip collision handling here as the set velocity from the previous collision
             // handling should keep the particle from tunneling through the face.



More information about the Bf-blender-cvs mailing list