[Bf-blender-cvs] [382b15d4459] particle-solver-dev: Make colliders be able to push particles even if dampeing is 1

Sebastian Parborg noreply at git.blender.org
Wed Jun 10 03:40:46 CEST 2020


Commit: 382b15d4459110ec41afa75638d3254940ab9365
Author: Sebastian Parborg
Date:   Wed Jun 10 03:40:12 2020 +0200
Branches: particle-solver-dev
https://developer.blender.org/rB382b15d4459110ec41afa75638d3254940ab9365

Make colliders be able to push particles even if dampeing is 1

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

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

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

diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp
index 87c1c507d74..af5a93917b8 100644
--- a/source/blender/simulations/bparticles/simulate.cpp
+++ b/source/blender/simulations/bparticles/simulate.cpp
@@ -324,6 +324,38 @@ BLI_NOINLINE static void raycast_callback(void *userdata,
   }
 }
 
+static float3 min_add(float3 a, float3 b)
+{
+  // TODO come up with a better function name...
+  if (is_zero_v3(a)) {
+    return b;
+  }
+
+  if (is_zero_v3(b)) {
+    return a;
+  }
+
+  if (dot_v3v3(a, b) < 0.0f) {
+    a -= float3::project(a, b);
+    b -= float3::project(b, a);
+  }
+  float3 proj = float3::project(a, b);
+
+  if (proj.length() > b.length()) {
+    // Make sure we use the longest one as basis.
+    float3 temp = a;
+    a = b;
+    b = temp;
+    proj = float3::project(a, b);
+  }
+
+  // print_v3("proj", proj);
+
+  b += a - proj;
+
+  return b;
+}
+
 BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulation_state),
                                                  ParticleAllocator &UNUSED(particle_allocator),
                                                  MutableAttributesRef attributes,
@@ -360,6 +392,8 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
     bool collided;
     int coll_num = 0;
 
+    float3 constraint_velo = float3(0.0f);
+
     // Update the velocities here so that the potential distance traveled is correct in the
     // collision check.
     velocities[pindex] += duration * forces[pindex] * mass;
@@ -375,7 +409,20 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
       do {
         BVHTreeRayHit best_hit;
         float3 best_hit_vel;
-        float max_move = (duration * velocities[pindex]).length();
+        float max_move;
+
+        float3 dir;
+
+        if (is_zero_v3(velocities[pindex])) {
+          // If velocity is zero, then no collisions will be detected with moving colliders. Make
+          // sure that we have a forced check by setting the dir to something that is not zero.
+          dir = float3(0, 0, 1.0f);
+          max_move = COLLISION_MIN_DISTANCE;
+        }
+        else {
+          dir = velocities[pindex].normalized();
+          max_move = (duration * velocities[pindex]).length();
+        }
 
         best_hit.dist = FLT_MAX;
         collided = false;
@@ -392,11 +439,11 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
           BVHTreeRayHit hit;
           hit.index = -1;
           hit.dist = max_move;
+
           // TODO the particle radius seems a bit flaky with higher distances?
           float particle_radius = 0.05f;
 
           float3 start = positions[pindex];
-          float3 dir = velocities[pindex].normalized();
 
           RayCastData rd;
 
@@ -437,6 +484,7 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
         }
         if (collided) {
           // dead_state[pindex] = true;
+          float dampening = 1.0f;
 
           float3 normal = best_hit.no;
 
@@ -447,48 +495,54 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
           // 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();
+          if (dot_v3v3(best_hit_vel, normal) > 0.0f) {
+            // The collider is moving towards the particle, we need to make sure that the particle
+            // has enough velocity to not tunnel through.
+
+            constraint_velo = min_add(constraint_velo, best_hit_vel);
+          }
+
+          // Modify constraint_velo so if it is along the collider normal if it is moving into
+          // the collision plane.
+          if (dot_v3v3(constraint_velo, normal) < 0.0f) {
+            constraint_velo -= float3::project(constraint_velo, normal);
+          }
 
           // Local velocity on the particle with the collider as reference point.
           // Note that we only take into account the velocity of the collider in the normal
           // direction as the other velocity will be negated again when moving back to the
           // global reference frame.
-          float3 hit_normal_velo = float3::project(best_hit_vel, n_v);
-          float3 local_velo = velocities[pindex] - hit_normal_velo;
+          float3 hit_normal_velo = float3::project(best_hit_vel, normal);
+
+          // --- old
+          // float3 local_velo = velocities[pindex] - hit_normal_velo;
 
-          float dampening = 0.5f;
           // 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");
-            local_velo -= (1.0 + normal_dot) * hit_normal_velo;
-          }
+          // local_velo *= (1.0f - dampening);
 
-          normal_dot = dot_v3v3(local_velo, n_v);
+          // float normal_dot = dot_v3v3(normal, local_velo);
 
-          // if (normal_dot > 0.0f) {
-          //  normal_dot *= -1.0f;
-          //}
-          // if (normal_dot < 0.0f) {
-          // The particle was moving into the collission plane
-          float3 deflect_vel = local_velo - 2.0f * normal_dot * n_v;
+          // float3 deflect_vel = local_velo - 2.0f * normal_dot * normal;
+
+          //--- old end
+
+          float3 part_velo_normal = float3::project(velocities[pindex], normal);
+          float3 part_velo_tangent = velocities[pindex] - part_velo_normal;
+
+          part_velo_normal += hit_normal_velo;
+
+          float3 deflect_vel = part_velo_tangent - part_velo_normal;
+          deflect_vel *= (1.0f - dampening);
 
           // print_v3("normal", normal);
           // printf("normal dir %f\n", normal_dot);
           // print_v3("n_v", n_v);
           // print_v3("vel hit", best_hit_vel);
+          // print_v3("hit_normal_velo", hit_normal_velo);
           // print_v3("vel_pre", velocities[pindex]);
+          // print_v3("vel_local", local_velo);
           // print_v3("deflect_vel", deflect_vel);
+          // print_v3("const vel", constraint_velo);
 
           if (dot_v3v3(deflect_vel, normal) < 0) {
             // TODO this is needed when a particle collides two times on an edge or vert...
@@ -496,6 +550,7 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
             // This is bascially a safety check to see that we are actually moving away from the
             // collider and not further into it.
             deflect_vel *= -1.0f;
+            // printf("invert\n");
           }
 
           float3 temp;
@@ -507,6 +562,20 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
             printf("pindex: %d\n\n\n\n", pindex);
           }
 
+          if (!is_zero_v3(constraint_velo)) {
+            if (coll_num == 9) {
+              // If we are at the last collision check, just try to go into the constraint velocity
+              // direction and hope for the best.
+              deflect_vel = constraint_velo;
+            }
+            else if (float3::project(deflect_vel, constraint_velo).length() <
+                     constraint_velo.length()) {
+              // printf("gapp\n");
+              // print_v3("def old vel", deflect_vel);
+              deflect_vel = min_add(deflect_vel, constraint_velo);
+              // print_v3("const def new vel", deflect_vel);
+            }
+          }
           // float temp = (1.0f + dot_v3v3(deflect_vel, best_hit_vel)) / 2.0f;
           // TODO if particle is moving away from the plane, it assumes the velocity of the
           // collider
@@ -528,12 +597,18 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat
           //  // Do not apply forces if it would make the particle tunnel through colliders
           // velocities[pindex] = force_after_hit;
           //}
+
+          // printf("pindex: %d collnum: %d\n\n", pindex, coll_num);
           coll_num++;
         }
       } while (collided && coll_num < 10);
     }
     float3 move_vec = duration * velocities[pindex];
     positions[pindex] += move_vec;
+    // print_v3("final_velo", velocities[pindex]);
+    // printf("dur: %f\n", duration);
+    // print_v3("move_vec", move_vec);
+    // print_v3("final_pos", positions[pindex]);
   }
 }



More information about the Bf-blender-cvs mailing list