[Bf-blender-cvs] [0607cd2e15] cloth-improvements: Replace plNearestPoints with a deticated solution
Luca Rood
noreply at git.blender.org
Sat Mar 4 06:22:38 CET 2017
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. @@
More information about the Bf-blender-cvs
mailing list