diff options
author | Sebastian Parborg <darkdefende@gmail.com> | 2020-04-01 18:49:32 +0300 |
---|---|---|
committer | Sebastian Parborg <darkdefende@gmail.com> | 2020-04-01 18:49:32 +0300 |
commit | 81d5a62f73181f23dece617bbd67ef7029518a80 (patch) | |
tree | 01c0ec6084a1468141a61e424f495741c0658919 | |
parent | c089d7b4d1faf5e6c8f6c3956bfac344fecad314 (diff) |
Fixed radius collision calculation and fixed the collision detection logic
-rw-r--r-- | source/blender/simulations/bparticles/simulate.cpp | 144 |
1 files changed, 65 insertions, 79 deletions
diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp index 27203afb873..af0129206fc 100644 --- a/source/blender/simulations/bparticles/simulate.cpp +++ b/source/blender/simulations/bparticles/simulate.cpp @@ -18,26 +18,6 @@ using BLI::Vector; using BLI::VectorAdaptor; using FN::CPPType; -static bool point_inside_tri(const float mat[3][3], - const float point[3], - std::array<float3, 3> &cur_tri_points) -{ - float mat_coords[3][2]; - float mat_new_pos[2]; - mul_v2_m3v3(mat_new_pos, mat, point); - - for (int i = 0; i < 3; i++) { - mul_v2_m3v3(mat_coords[i], mat, cur_tri_points[i]); - } - - return isect_point_tri_v2(mat_new_pos, mat_coords[0], mat_coords[1], mat_coords[2]); -} - -/* -axis_dominant_v3_to_m3(mat, new_norm); - -*/ - /************************************************ * Collisions (taken from the old particle_system.c) * @@ -110,7 +90,7 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points //} /* particle already inside face, so report collision */ - if (iter == 0 && d0 < 0.f && d0 > -radius) { + if (iter == 0 && (abs(d0) - radius) <= COLLISION_ZERO) { p = particle_points.first; // pce->inside = 1; return 0.f; @@ -155,14 +135,13 @@ static float collision_newton_rhapson(std::pair<float3, float3> &particle_points return -1.f; } - if (d1 <= COLLISION_ZERO && d1 >= -COLLISION_ZERO) { + if ((abs(d1) - radius) <= COLLISION_ZERO) { if (t1 >= -COLLISION_ZERO && t1 <= 1.f) { - /* Do we actually lie inside the triangle? */ - float mat[3][3]; - axis_dominant_v3_to_m3(mat, coll_normal); - if (point_inside_tri(mat, p, cur_tri_points)) { - // if (isect_point_tri_prism_v3(p, cur_tri_points[0], cur_tri_points[1], - // cur_tri_points[2])) { // This is a bit slower than point_inside_tri + /* Do we actually hit the triangle or did we only hit the math plane? */ + float3 closest_point; + closest_on_tri_to_point_v3( + closest_point, p, cur_tri_points[0], cur_tri_points[1], cur_tri_points[2]); + if (float3::distance(closest_point, p) - radius <= COLLISION_ZERO) { CLAMP(t1, 0.f, 1.f); return t1; } @@ -206,6 +185,8 @@ BLI_NOINLINE static void raycast_callback(void *userdata, if (collmd->is_static) { if (ray->radius == 0.0f) { + // TODO particles probably need to always have somekind or radius, so this can probably be + // removed after testing is done. dist = bvhtree_ray_tri_intersection(ray, hit->dist, v0, v1, v2); } else { @@ -215,7 +196,7 @@ BLI_NOINLINE static void raycast_callback(void *userdata, if (dist >= 0.0f && dist < hit->dist) { hit->index = index; hit->dist = dist; - madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist); + madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist - ray->radius); normal_tri_v3(hit->no, v0, v1, v2); } @@ -263,7 +244,7 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat ParticleSystemInfo &system_info, MutableArrayRef<float> remaining_durations, float UNUSED(end_time), - Vector<ColliderCache *> &colliders) + ArrayRef<ColliderCache *> colliders) { uint amount = attributes.size(); BLI_assert(amount == remaining_durations.size()); @@ -285,7 +266,8 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat for (uint pindex : IndexRange(amount)) { float mass = 1.0f; float duration = remaining_durations[pindex]; - bool collided = false; + bool collided; + int coll_num = 0; // Update the velocities here so that the potential distance traveled is correct in the // collision check. @@ -293,59 +275,63 @@ BLI_NOINLINE static void simulate_particle_chunk(SimulationState &UNUSED(simulat // Check if any 'collobjs' collide with the particles here if (colliders.size() != 0) { - // TODO Move this to be upper most loop - for (auto col : colliders) { - CollisionModifierData *collmd = col->collmd; - - if (!collmd->bvhtree) { - continue; - } + do { + collided = false; + BVHTreeRayHit best_hit; + float max_move = (duration * velocities[pindex]).length(); + best_hit.dist = FLT_MAX; + for (ColliderCache *col : colliders) { + CollisionModifierData *collmd = col->collmd; - const int raycast_flag = BVH_RAYCAST_DEFAULT; + if (!collmd->bvhtree) { + continue; + } - float max_move = (duration * velocities[pindex]).length(); + const int raycast_flag = BVH_RAYCAST_DEFAULT; + + BVHTreeRayHit hit; + hit.index = -1; + hit.dist = max_move; + float particle_radius = 0.001f; + float3 start = positions[pindex]; + float3 dir = velocities[pindex].normalized(); + + RayCastData rd; + + rd.collmd = collmd; + rd.particle_points.first = start; + rd.particle_points.second = start + duration * velocities[pindex]; + + BLI_bvhtree_ray_cast_ex(collmd->bvhtree, + start, + dir, + particle_radius, + &hit, + raycast_callback, + &rd, + raycast_flag); + + if (hit.index == -1 || best_hit.dist < hit.dist) { + // We didn't hit anything + continue; + } - BVHTreeRayHit hit; - hit.index = -1; - hit.dist = max_move; - float particle_radius = 0.0f; - float3 start = positions[pindex]; - float3 dir = velocities[pindex].normalized(); - - RayCastData rd; - - rd.collmd = collmd; - rd.particle_points.first = start; - rd.particle_points.second = start + duration * velocities[pindex]; - - BLI_bvhtree_ray_cast_ex(collmd->bvhtree, - start, - dir, - particle_radius, - &hit, - raycast_callback, - &rd, - raycast_flag); - - if (hit.index == -1) { - // We didn't hit anything - continue; + best_hit = hit; + collided = true; } - // TODO move particle to collision point and do additional collision check in the new - // direction. - // update final position of particle - positions[pindex] = hit.co; - // - // dot normal from vt with hit.co - start to see which way to deflect the particle - velocities[pindex] *= -1; - positions[pindex] += duration * (1.0f - hit.dist / max_move) * velocities[pindex]; - collided = true; - break; - } - } - if (!collided) { - positions[pindex] += duration * velocities[pindex]; + if (collided) { + // XXX TODO we need to notify the moving colliders somehow that the new pos is not at t=0 + positions[pindex] = best_hit.co; + // + // dot normal from vt with hit.co - start to see which way to deflect the particle + velocities[pindex] *= -0.5f; + // Calculate the remaining duration + duration -= duration * (1.0f - best_hit.dist / max_move); + coll_num++; + } + } while (collided && coll_num < 10); } + positions[pindex] += duration * velocities[pindex]; } } // namespace BParticles |