[Bf-blender-cvs] [277b1d7] master: Fix T26658: particles stopped or bounced by 100% permeability colliders.

Alexander Gavrilov noreply at git.blender.org
Sat Aug 6 09:36:10 CEST 2016


Commit: 277b1d76ff73c3dfb2150ec06af622962c300618
Author: Alexander Gavrilov
Date:   Fri Jul 22 18:55:37 2016 +0300
Branches: master
https://developer.blender.org/rB277b1d76ff73c3dfb2150ec06af622962c300618

Fix T26658: particles stopped or bounced by 100% permeability colliders.

There were two issues here. One is that the fix done originally for this
bug only checks for colliding with the same face as the single preceeding
hit. If the particle hits an edge or vertex of the collider, it in fact
hits two or more faces, so the loop ends up cycling between first two
of them and reaches the max collision limit.

The fix is to disable the collider for the sim step once a permeability
roll succeeds, by adding it to a skip list. Skipping just one face causes
some particles to bounce at odd angles in case of partial permeability.

The second problem was that the collider bounced back a small percentage
of particles, and the cause seemed to be that the code was set to flip
the velocity if the particle was just past the collider but still within
collision distance. Inverting both values causes a half permeable collider
to stop particles, so it seems that this if branch shouldn't bounce at all.

Test file: {F327322}

Reviewers: lukastoenne, brecht

Reviewed By: brecht

Subscribers: brecht, #physics

Maniphest Tasks: T26658

Differential Revision: https://developer.blender.org/D2120

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

M	source/blender/blenkernel/BKE_particle.h
M	source/blender/blenkernel/intern/particle_system.c

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

diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 3783172..b3e3968 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -63,6 +63,8 @@ struct BVHTreeRay;
 struct BVHTreeRayHit; 
 struct EdgeHash;
 
+#define PARTICLE_COLLISION_MAX_COLLISIONS 10
+
 #define PARTICLE_P              ParticleData * pa; int p
 #define LOOP_PARTICLES  for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++)
 #define LOOP_EXISTING_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) if (!(pa->flag & PARS_UNEXIST))
@@ -205,8 +207,7 @@ typedef struct ParticleCollisionElement {
 typedef struct ParticleCollision {
 	struct Object *current;
 	struct Object *hit;
-	struct Object *prev;
-	struct Object *skip;
+	struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS+1];
 	struct Object *emitter;
 
 	struct CollisionModifierData *md; // collision modifier for current object;
@@ -218,7 +219,7 @@ typedef struct ParticleCollision {
 
 	float original_ray_length; //original length of co2-co1, needed for collision time evaluation
 
-	int prev_index;
+	int skip_count;
 
 	ParticleCollisionElement pce;
 
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 8e3e2f5..0728fef 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2183,7 +2183,6 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
  *     http://en.wikipedia.org/wiki/Newton's_method
  *
  ************************************************/
-#define COLLISION_MAX_COLLISIONS	10
 #define COLLISION_MIN_RADIUS 0.001f
 #define COLLISION_MIN_DISTANCE 0.0001f
 #define COLLISION_ZERO 0.00001f
@@ -2570,10 +2569,6 @@ void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay
 	pce.inside = 0;
 	pce.index = index;
 
-	/* don't collide with same face again */
-	if (col->hit == col->current && col->pce.index == index && col->pce.tot == 3)
-		return;
-
 	collision = collision_sphere_to_tri(col, ray->radius, &pce, &t);
 	if (col->pce.inside == 0) {
 		collision += collision_sphere_to_edges(col, ray->radius, &pce, &t);
@@ -2609,8 +2604,17 @@ static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRay
 		hit->dist = col->original_ray_length = 0.000001f;
 
 	for (coll = colliders->first; coll; coll=coll->next) {
-		/* for boids: don't check with current ground object */
-		if (coll->ob == col->skip)
+		/* for boids: don't check with current ground object; also skip if permeated */
+		bool skip = false;
+
+		for (int i = 0; i < col->skip_count; i++) {
+			if (coll->ob == col->skip[i]) {
+				skip = true;
+				break;
+			}
+		}
+
+		if (skip)
 			continue;
 
 		/* particles should not collide with emitter at birth */
@@ -2746,7 +2750,7 @@ static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeR
 		if (through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot)))
 			mul_v3_v3fl(v0_nor, pce->nor, vc_dot);
 		else if (v0_dot > 0.f)
-			mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? -1.0f : 1.0f) * v0_dot);
+			mul_v3_v3fl(v0_nor, pce->nor, vc_dot + v0_dot);
 		else
 			mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot);
 
@@ -2801,8 +2805,10 @@ static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeR
 		col->f = f;
 	}
 
-	col->prev = col->hit;
-	col->prev_index = hit->index;
+	/* if permeability random roll succeeded, disable collider for this sim step */
+	if (through) {
+		col->skip[col->skip_count++] = col->hit;
+	}
 
 	return 1;
 }
@@ -2863,16 +2869,16 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa
 	if (part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) {
 		col.boid = 1;
 		col.boid_z = pa->state.co[2];
-		col.skip = pa->boid->ground;
+		col.skip[col.skip_count++] = pa->boid->ground;
 	}
 
 	/* 10 iterations to catch multiple collisions */
-	while (collision_count < COLLISION_MAX_COLLISIONS) {
+	while (collision_count < PARTICLE_COLLISION_MAX_COLLISIONS) {
 		if (collision_detect(pa, &col, &hit, sim->colliders)) {
 			
 			collision_count++;
 
-			if (collision_count == COLLISION_MAX_COLLISIONS)
+			if (collision_count == PARTICLE_COLLISION_MAX_COLLISIONS)
 				collision_fail(pa, &col);
 			else if (collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0)
 				return;




More information about the Bf-blender-cvs mailing list