Commit: 0607cd2e15cc54692c7eed01500f6098dbaf1722
Author: Luca Rood
Date:   Sat Mar 4 00:24:35 2017 -0300
Branches: cloth-improvements
https://developer.blender.org/rB0607cd2e15cc54692c7eed01500f6098dbaf1722

Replace plNearestPoints with a deticated solution

Implement a dedicated collision detection function (was previously
relying on Bullet's generic `plNearestPoints`).
This function computes all the collision data to be used for response:
coordinates, distance, direction vector.

This new function has three advantages:

* Remove a dependency from cloth simulation (Bullet).
* Give more pleasing collision results (this function is tailored
specifically for our collision response method).
* Much faster computation (not benchmarked extensively, but observed
overal simulation time was cut roughly in half with "collision-heavy"
simulations).

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

M       source/blender/blenkernel/BKE_collision.h
M       source/blender/blenkernel/intern/collision.c

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

diff --git a/source/blender/blenkernel/BKE_collision.h 
b/source/blender/blenkernel/BKE_collision.h
index 8fedcd4ab0..6a859c0058 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -72,7 +72,7 @@ typedef enum {
 typedef struct CollPair {
        unsigned int face1; // cloth face
        unsigned int face2; // object face
-       double distance; // magnitude of vector
+       float distance;
        float normal[3];
        float vector[3]; // unnormalized collision vector: p2-p1
        float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
diff --git a/source/blender/blenkernel/intern/collision.c 
b/source/blender/blenkernel/intern/collision.c
index 2f3968ec92..64215a2b63 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -49,9 +49,6 @@
 #include "BKE_modifier.h"
 #include "BKE_scene.h"
 
-#ifdef WITH_BULLET
-#include "Bullet-C-Api.h"
-#endif
 #include "BLI_kdopbvh.h"
 #include "BKE_collision.h"
 
@@ -177,6 +174,236 @@ void bvhtree_update_from_mvert(
 Collision modifier code end
 ***********************************/
 
+static void clamp_point_seg(float a[3], float b[3], float p[3])
+{
+       float ap[3], bp[3], ab[3];
+
+       sub_v3_v3v3(ap, p, a);
+       sub_v3_v3v3(bp, p, b);
+       sub_v3_v3v3(ab, b, a);
+
+       if (dot_v3v3(ap, bp) > 0.0f) {
+               if (dot_v3v3(ap, ab) > 0.0f) {
+                       copy_v3_v3(p, b);
+               }
+               else {
+                       copy_v3_v3(p, a);
+               }
+       }
+}
+
+static bool isect_seg_seg(float a1[3], float a2[3], float b1[3], float b2[3], 
float r_a[3], float r_b[3])
+{
+       if (isect_line_line_v3(a1, a2, b1, b2, r_a, r_b)) {
+               clamp_point_seg(a1, a2, r_a);
+               clamp_point_seg(b1, b2, r_b);
+
+               return true;
+       }
+
+       return false;
+}
+
+BLI_INLINE int next_ind(int i)
+{
+       return (++i < 3) ? i : 0;
+}
+
+static float compute_collision_point(float a1[3], float a2[3], float a3[3], 
float b1[3], float b2[3], float b3[3],
+                                     bool culling, bool use_normal, float 
r_a[3], float r_b[3], float r_vec[3])
+{
+       float a[3][3];
+       float b[3][3];
+       float dist;
+       float mindist = FLT_MAX;
+       float tmp_co1[3], tmp_co2[3];
+       float isect_a[3], isect_b[3];
+       int isect_count = 0;
+       float tmp, tmp_vec[3];
+       float normal[3], cent[3];
+       bool backside = false;
+
+       copy_v3_v3(a[0], a1);
+       copy_v3_v3(a[1], a2);
+       copy_v3_v3(a[2], a3);
+
+       copy_v3_v3(b[0], b1);
+       copy_v3_v3(b[1], b2);
+       copy_v3_v3(b[2], b3);
+
+       /* Find intersections */
+       for (int i = 0; i < 3; i++) {
+               if (isect_line_segment_tri_v3(a[i], a[next_ind(i)], b[0], b[1], 
b[2], &tmp, NULL)) {
+                       interp_v3_v3v3(isect_a, a[i], a[next_ind(i)], tmp);
+                       isect_count++;
+               }
+       }
+
+       if (isect_count == 0) {
+               for (int i = 0; i < 3; i++) {
+                       if (isect_line_segment_tri_v3(b[i], b[next_ind(i)], 
a[0], a[1], a[2], &tmp, NULL)) {
+                               isect_count++;
+                       }
+               }
+       }
+       else if (isect_count == 1) {
+               for (int i = 0; i < 3; i++) {
+                       if (isect_line_segment_tri_v3(b[i], b[next_ind(i)], 
a[0], a[1], a[2], &tmp, NULL)) {
+                               interp_v3_v3v3(isect_b, b[i], b[next_ind(i)], 
tmp);
+                               break;
+                       }
+               }
+       }
+
+       /* Determine collision side */
+       if (culling) {
+               normal_tri_v3(normal, b[0], b[1], b[2]);
+               cent_tri_v3(cent, b[0], b[1], b[2]);
+
+               if (isect_count == 2) {
+                       backside = true;
+               }
+               else if (isect_count == 0) {
+                       for (int i = 0; i < 3; i++) {
+                               sub_v3_v3v3(tmp_vec, a[i], cent);
+                               if (dot_v3v3(tmp_vec, normal) < 0.0f) {
+                                       backside = true;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (isect_count == 1) {
+               /* Edge intersection */
+               copy_v3_v3(r_a, isect_a);
+               copy_v3_v3(r_b, isect_b);
+
+               sub_v3_v3v3(r_vec, r_b, r_a);
+
+               return 0.0f;
+       }
+       else if (backside) {
+               float maxdist = 0.0f;
+               bool found = false;
+
+               /* Point projections */
+               for (int i = 0; i < 3; i++) {
+                       if (isect_ray_tri_v3(a[i], normal, b[0], b[1], b[2], 
&tmp, NULL)) {
+                               if (tmp > maxdist) {
+                                       maxdist = tmp;
+                                       copy_v3_v3(r_a, a[i]);
+                                       madd_v3_v3v3fl(r_b, a[i], normal, tmp);
+                                       found = true;
+                               }
+                       }
+               }
+
+               negate_v3(normal);
+
+               for (int i = 0; i < 3; i++) {
+                       if (isect_ray_tri_v3(b[i], normal, a[0], a[1], a[2], 
&tmp, NULL)) {
+                               if (tmp > maxdist) {
+                                       maxdist = tmp;
+                                       madd_v3_v3v3fl(r_a, b[i], normal, tmp);
+                                       copy_v3_v3(r_b, b[i]);
+                                       found = true;
+                               }
+                       }
+               }
+
+               negate_v3(normal);
+
+               /* Edge projections */
+               for (int i = 0; i < 3; i++) {
+                       float dir[3];
+
+                       sub_v3_v3v3(tmp_vec, b[next_ind(i)], b[i]);
+                       cross_v3_v3v3(dir, tmp_vec, normal);
+
+                       for (int j = 0; j < 3; j++) {
+                               if (isect_line_plane_v3(tmp_co1, a[j], 
a[next_ind(j)], b[i], dir) &&
+                                   point_in_slice_seg(tmp_co1, a[j], 
a[next_ind(j)]) &&
+                                   point_in_slice_seg(tmp_co1, b[i], 
b[next_ind(i)]))
+                               {
+                                       closest_to_line_v3(tmp_co2, tmp_co1, 
b[i], b[next_ind(i)]);
+                                       sub_v3_v3v3(tmp_vec, tmp_co1, tmp_co2);
+                                       tmp = len_v3(tmp_vec);
+
+                                       if ((tmp > maxdist) && 
(dot_v3v3(tmp_vec, normal) < 0.0f)) {
+                                               maxdist = tmp;
+                                               copy_v3_v3(r_a, tmp_co1);
+                                               copy_v3_v3(r_b, tmp_co2);
+                                               found = true;
+                                       }
+                               }
+                       }
+               }
+
+               /* If no point is found, will fallback onto regular proximity 
test below */
+               if (found) {
+                       sub_v3_v3v3(r_vec, r_b, r_a);
+
+                       return 0.0f;
+               }
+       }
+
+       /* Closest point */
+       for (int i = 0; i < 3; i++) {
+               closest_on_tri_to_point_v3(tmp_co1, a[i], b[0], b[1], b[2]);
+               tmp = len_squared_v3v3(tmp_co1, a[i]);
+
+               if (tmp < mindist) {
+                       mindist = tmp;
+                       copy_v3_v3(r_a, a[i]);
+                       copy_v3_v3(r_b, tmp_co1);
+               }
+       }
+
+       for (int i = 0; i < 3; i++) {
+               closest_on_tri_to_point_v3(tmp_co1, b[i], a[0], a[1], a[2]);
+               tmp = len_squared_v3v3(tmp_co1, b[i]);
+
+               if (tmp < mindist) {
+                       mindist = tmp;
+                       copy_v3_v3(r_a, tmp_co1);
+                       copy_v3_v3(r_b, b[i]);
+               }
+       }
+
+       /* Closest edge */
+       if (isect_count == 0) {
+               for (int i = 0; i < 3; i++) {
+                       for (int j = 0; j < 3; j++) {
+                               if (isect_seg_seg(a[i], a[next_ind(i)], b[j], 
b[next_ind(j)], tmp_co1, tmp_co2)) {
+                                       tmp = len_squared_v3v3(tmp_co1, 
tmp_co2);
+
+                                       if (tmp < mindist) {
+                                               mindist = tmp;
+                                               copy_v3_v3(r_a, tmp_co1);
+                                               copy_v3_v3(r_b, tmp_co2);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (isect_count == 0) {
+               sub_v3_v3v3(r_vec, r_a, r_b);
+               dist = sqrtf(mindist);
+       }
+       else {
+               sub_v3_v3v3(r_vec, r_b, r_a);
+               dist = 0.0f;
+       }
+
+       if (culling && (dot_v3v3(r_vec, normal) < 0.0f)) {
+               return FLT_MAX;
+       }
+
+       return dist;
+}
+
 static void free_impulse_clusters(ImpulseCluster *clusters)
 {
        while (clusters) {
@@ -396,8 +623,6 @@ static int cloth_collision_response_static 
(ClothModifierData *clmd, CollisionMo
        float v1[3], v2[3], relativeVelocity[3];
        float magrelVel;
        float epsilon2 = BLI_bvhtree_get_epsilon ( collmd->bvhtree );
-       float collider_norm[3];
-       bool backside;
 
        cloth1 = clmd->clothObject;
 
@@ -426,34 +651,6 @@ static int cloth_collision_response_static 
(ClothModifierData *clmd, CollisionMo
                        collmd->current_x[collpair->bp3].co,
                        &u1, &u2, &u3 );
 
-               /* compute collision normal */
-               if (collob->pd->flag & PFIELD_CLOTH_USE_NORMAL) {
-                       normal_tri_v3(collider_norm, 
collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, 
collmd->current_x[collpair->bp3].co);
-                       backside = dot_v3v3(collider_norm, collpair->normal) < 
0.0f;
-
-                       if (!(collob->pd->flag & PFIELD_CLOTH_USE_CULLING) && 
backside) {
-                               negate_v3(collider_norm);
-                               backside = false;
-                       }
-               }
-               else {
-                       copy_v3_v3(collider_norm, collpair->normal);
-
-                       if (collob->pd->flag & PFIELD_CLOTH_USE_CULLING) {
-                               float tmp_norm[3];
-
-                               normal_tri_v3(tmp_norm, 
collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, 
collmd->current_x[collpair->bp3].co);
-                               backside = dot_v3v3(collider_norm, tmp_norm) < 
0.0f;
-
-                               if (backside) {
-                                       negate_v3(collider_norm);
-                               }
-                       }
-                       else {
-                               backside = false;
-                       }
-               }
-
                /* Calculate relative "velocity". */
                collision_interpolateOnTriangle ( v1, 
cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, 
cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
 
@@ -462,7 +659,7 @@ static int cloth_collision_response_static 
(ClothModifierData *clmd, CollisionMo
                sub_v3_v3v3(relativeVelocity, v2, v1);
 
                /* Calculate the normal component of the relative velocity 
(actually only the magnitude - the direction is stored in 'normal'). */
-               magrelVel = dot_v3v3(relativeVelocity, collider_norm);
+               magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
 
                /* printf("magrelVel: %f\n", magrelVel); */
 
@@ -478,7 +675,7 @@ static int cloth_collision_response_static 
(ClothModifierData *clmd, CollisionMo
                        float temp[3], time_multiplier;
 
                        /* calculate tangential velocity */
-                       copy_v3_v3 ( temp, collider_norm );
+                       copy_v3_v3(temp, collpair->normal);
                        mul_v3_fl(temp, magrelVel);
                        sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp);
 
@@ -508,38 +705,14 @@ static int cloth_collision_response_static 
(ClothModifierData *clmd, CollisionMo
                        /* Impulse should be uniform throughout polygon, the 
scaling used above was wrong */
                        impulse =  magrelVel / 1.5f;
 
-                       if (backside) {
-                               float pt_relvel[3];
-                               float pt_magvel;
-
-                               sub_v3_v3v3(pt_relvel, v2, 
cloth1->verts[collpair->ap1].tv);
-                               pt_magvel = dot_v3v3(pt_relvel, collider_norm);
-
-                               VECADDMUL ( i1, collider_norm, pt_magvel * 
0.25f );
-                               cloth1->verts[collpair->ap1].impulse_count++;
-
-                               sub_v3_v3v3(pt_relvel, v2, 
cloth1->verts[collpair->ap2].tv);
-                               pt_magvel = dot_v3v3(pt_relvel, collider_norm);
-
-                               VECADDMUL ( i2, collider_norm, pt_magvel * 
0.25f );
-                               cloth1->verts[collpair->ap2].impulse_count++;
-
-                               sub_v3_v3v3(pt_relvel, v2, 
cloth1->verts[collpair->ap3].tv);
-                               pt_magvel = dot_v3v3(pt_relvel, collider_norm);
-
-                               VECADDMUL ( i3, collider_norm, pt_magvel * 
0.25f );
-                               cloth1->verts[collpair->ap3].impulse_count++;
-                       }
-                       else {
-                               VECADDMUL ( i1, collider_norm, w1 * impulse );
-                               cloth1->verts[collpair->ap1].impulse_count++;
+                       VECADDMUL ( i1, collpair->normal, w1 * impulse );
+                       cloth1->verts[collpair->ap1].impulse_count++;
 
-                               VECADDMUL ( i2, collider_norm, w2 * impulse );
-                               cloth1->verts[collpair->ap2].impulse_count++;
+                       VECADDMUL ( i2, collpair->normal, w2 * impulse );
+                       cloth1->verts[collpair->ap2].impulse_count

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to