Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJanne Karhu <jhkarh@gmail.com>2010-11-03 00:16:41 +0300
committerJanne Karhu <jhkarh@gmail.com>2010-11-03 00:16:41 +0300
commit09435ec149b499fabb112114bcdd24a9b3dc6cda (patch)
tree78ca1268596d49c56479a77de91785cc834ee660 /source
parent130088300bec57aa0f11042bb09e48a67417a514 (diff)
Oops, particle collisions didn't take simulation subframes into account at all.
* This caused nearly all particles to leak through the collision surface if simulation subframes were used and the collision object was moving. * In addition to fixing this I also did some more cleanup of the collision code and refined some of the comments.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_particle.h4
-rw-r--r--source/blender/blenkernel/intern/boids.c12
-rw-r--r--source/blender/blenkernel/intern/particle_system.c50
3 files changed, 40 insertions, 26 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 1416e1280cf..5bcd69865fc 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -171,7 +171,9 @@ typedef struct ParticleCollision
float co1[3], co2[3]; // ray start and end points
float ve1[3], ve2[3]; // particle velocities
float ray_len; // original length of co2-co1, needed for collision time evaluation
- float t; // time of previous collision, needed for substracting face velocity
+ float f; // time factor of previous collision, needed for substracting face velocity
+ float cfra; // start of the timestep (during frame change, since previous integer frame)
+ float dfra; // duration of timestep in frames
} ParticleCollision;
typedef struct ParticleDrawData {
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 5c2c0721972..1bde0639055 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -205,7 +205,9 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
add_v3_v3v3(col.co2, pa->prev_state.co, pa->prev_state.vel);
sub_v3_v3v3(ray_dir, col.co2, col.co1);
mul_v3_fl(ray_dir, acbr->look_ahead);
- col.t = 0.0f;
+ col.f = 0.0f;
+ col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+ col.dfra = bbd->dfra;
hit.index = -1;
hit.dist = col.ray_len = len_v3(ray_dir);
@@ -772,7 +774,9 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
sub_v3_v3v3(col.co2, pa->state.co, zvec);
sub_v3_v3(col.co2, zvec);
sub_v3_v3v3(ray_dir, col.co2, col.co1);
- col.t = 0.0f;
+ col.f = 0.0f;
+ col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+ col.dfra = bbd->dfra;
hit.index = -1;
hit.dist = col.ray_len = len_v3(ray_dir);
@@ -796,7 +800,9 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
sub_v3_v3v3(col.co2, pa->state.co, zvec);
sub_v3_v3(col.co2, zvec);
sub_v3_v3v3(ray_dir, col.co2, col.co1);
- col.t = 0.0f;
+ col.f = 0.0f;
+ col.cfra = fmod(bbd->cfra-bbd->dfra, 1.0f);
+ col.dfra = bbd->dfra;
hit.index = -1;
hit.dist = col.ray_len = len_v3(ray_dir);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index a4c0776f5df..504105d5950 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2777,23 +2777,26 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B
MVert *x = col->md->x;
MVert *v = col->md->current_v;
float vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], t;
+ float x0[3], x1[3], x2[3], x3[3];
+ float *t0=x0, *t1=x1, *t2=x2, *t3=(face->v4 ? x3 : NULL);
- float *t0, *t1, *t2, *t3;
- t0 = x[ face->v1 ].co;
- t1 = x[ face->v2 ].co;
- t2 = x[ face->v3 ].co;
- t3 = face->v4 ? x[ face->v4].co : NULL;
+ /* move collision face to start of timestep */
+ madd_v3_v3v3fl(t0, x[face->v1].co, v[face->v1].co, col->cfra);
+ madd_v3_v3v3fl(t1, x[face->v2].co, v[face->v2].co, col->cfra);
+ madd_v3_v3v3fl(t2, x[face->v3].co, v[face->v3].co, col->cfra);
+ if(t3)
+ madd_v3_v3v3fl(t3, x[face->v4].co, v[face->v4].co, col->cfra);
/* calculate average velocity of face */
- VECCOPY(vel, v[ face->v1 ].co);
- VECADD(vel, vel, v[ face->v2 ].co);
- VECADD(vel, vel, v[ face->v3 ].co);
- mul_v3_fl(vel, 0.33334f);
+ copy_v3_v3(vel, v[ face->v1 ].co);
+ add_v3_v3(vel, v[ face->v2 ].co);
+ add_v3_v3(vel, v[ face->v3 ].co);
+ mul_v3_fl(vel, 0.33334f*col->dfra);
/* substract face velocity, in other words convert to
a coordinate system where only the particle moves */
- VECADDFAC(co1, col->co1, vel, -col->t);
- VECSUB(co2, col->co2, vel);
+ madd_v3_v3v3fl(co1, col->co1, vel, -col->f);
+ sub_v3_v3v3(co2, col->co2, vel);
do
{
@@ -2875,7 +2878,7 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
copy_v3_v3(col.co2, pa->state.co);
copy_v3_v3(col.ve1, pa->prev_state.vel);
copy_v3_v3(col.ve2, pa->state.vel);
- col.t = 0.0f;
+ col.f = 0.0f;
/* override for boids */
if(part->phystype == PART_PHYS_BOIDS) {
@@ -2893,6 +2896,9 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
hit.index = -1;
hit.dist = col.ray_len = len_v3(ray_dir);
+ col.cfra = fmod(cfra-dfra, 1.0f);
+ col.dfra = dfra;
+
/* even if particle is stationary we want to check for moving colliders */
/* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */
if(hit.dist == 0.0f)
@@ -2917,11 +2923,11 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
/* 2. */
if(hit.index>=0) {
PartDeflect *pd = col.hit_ob->pd;
- float co[3]; /* point of collision */
- float x = hit.dist/col.ray_len; /* location of collision between this iteration */
- float df = col.t + x * (1.0f - col.t); /* time of collision between frame change*/
- float dt1 = (df - col.t) * timestep; /* iteration time of collision (in seconds) */
- float dt2 = (1.0f - df) * timestep; /* time left after collision (in seconds) */
+ float co[3]; /* point of collision */
+ float x = hit.dist/col.ray_len; /* location factor of collision between this iteration */
+ float f = col.f + x * (1.0f - col.f); /* time factor of collision between timestep */
+ float dt1 = (f - col.f) * timestep; /* time since previous collision (in seconds) */
+ float dt2 = (1.0f - f) * timestep; /* time left after collision (in seconds) */
int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */
deflections++;
@@ -2935,12 +2941,12 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
/* particle dies in collision */
if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) {
pa->alive = PARS_DYING;
- pa->dietime = pa->state.time + (cfra - pa->state.time) * df;
+ pa->dietime = pa->state.time + (cfra - pa->state.time) * f;
copy_v3_v3(pa->state.co, co);
- interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, df);
- interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, df);
- interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, df);
+ interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f);
+ interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f);
+ interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f);
/* particle is dead so we don't need to calculate further */
return;
@@ -3073,7 +3079,7 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
copy_v3_v3(col.ve1, v0);
copy_v3_v3(col.ve2, pa->state.vel);
- col.t = df;
+ col.f = f;
}
else {
/* final chance to prevent failure, so stick to the surface and hope for the best */