diff options
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 32 |
2 files changed, 23 insertions, 16 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 37831728e6f..b3e3968ca9b 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 8e3e2f5d6d0..0728fef2a32 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; |