diff options
author | Janne Karhu <jhkarh@gmail.com> | 2010-09-17 00:00:30 +0400 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2010-09-17 00:00:30 +0400 |
commit | 43d2d0c6ea6c74319de455f7ef81b42c597d1e5c (patch) | |
tree | c455bdda17f0729fa0e667bc745aa264d67ba4cf /source/blender/blenkernel/intern/boids.c | |
parent | b19521f2b21266ca4e1c22774c5b9528bc2624d0 (diff) |
Bug fix: Boids that could only fly didn't take the ground object into account leading to problems when flying near the ground.
Reported by Mike Pan and Dalai Felinto by mail.
Diffstat (limited to 'source/blender/blenkernel/intern/boids.c')
-rw-r--r-- | source/blender/blenkernel/intern/boids.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 54ffda6c0a9..5bf228b2392 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -240,6 +240,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size); bbd->wanted_speed = sqrt(t) * len_v3(pa->prev_state.vel); + bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed); return 1; } @@ -736,6 +737,7 @@ static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData * val->jump_speed = 0.0f; /* no jumping in air */ } } + static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *ground_co, float *ground_nor) { BoidParticle *bpa = pa->boid; @@ -765,16 +767,15 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro if(!bbd->sim->colliders) return NULL; + /* first try to find below boid */ copy_v3_v3(col.co1, pa->state.co); - copy_v3_v3(col.co2, pa->state.co); - add_v3_v3(col.co1, zvec); + 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; hit.index = -1; hit.dist = col.ray_len = len_v3(ray_dir); - /* find out upmost deflector object */ for(coll = bbd->sim->colliders->first; coll; coll = coll->next){ col.ob = coll->ob; col.md = coll->collmd; @@ -789,14 +790,37 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro normalize_v3_v3(ground_nor, col.nor); return col.hit_ob; } - else { - /* default to z=0 */ - VECCOPY(ground_co, pa->state.co); - ground_co[2] = 0; - ground_nor[0] = ground_nor[1] = 0.0f; - ground_nor[2] = 1.0f; - return NULL; + + /* couldn't find below, so find upmost deflector object */ + add_v3_v3(col.co1, pa->state.co, zvec); + 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; + hit.index = -1; + hit.dist = col.ray_len = len_v3(ray_dir); + + for(coll = bbd->sim->colliders->first; coll; coll = coll->next){ + col.ob = coll->ob; + col.md = coll->collmd; + + if(col.md && col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); + } + /* then use that object */ + if(hit.index>=0) { + t = hit.dist/col.ray_len; + interp_v3_v3v3(ground_co, col.co1, col.co2, t); + normalize_v3_v3(ground_nor, col.nor); + return col.hit_ob; } + + /* default to z=0 */ + VECCOPY(ground_co, pa->state.co); + ground_co[2] = 0; + ground_nor[0] = ground_nor[1] = 0.0f; + ground_nor[2] = 1.0f; + return NULL; } } static int boid_rule_applies(ParticleData *pa, BoidSettings *boids, BoidRule *rule) @@ -1226,8 +1250,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) VECADDFAC(pa->state.vel, pa->state.vel, acc, dtime); - if(bpa->data.mode != eBoidMode_InAir) - bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); + //if(bpa->data.mode != eBoidMode_InAir) + bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor); /* change modes, constrain movement & keep track of down vector */ switch(bpa->data.mode) { @@ -1255,11 +1279,18 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) boid_find_ground(bbd, pa, ground_co, ground_nor); boid_climb(boids, pa, ground_co, ground_nor); } - /* land boid when belowg ground */ - else if(boids->options & BOID_ALLOW_LAND && pa->state.co[2] <= ground_co[2] + pa->size * boids->height) { - pa->state.co[2] = ground_co[2] + pa->size * boids->height; - pa->state.vel[2] = 0.0f; - bpa->data.mode = eBoidMode_OnLand; + else if(pa->state.co[2] <= ground_co[2] + pa->size * boids->height) { + /* land boid when below ground */ + if(boids->options & BOID_ALLOW_LAND) { + pa->state.co[2] = ground_co[2] + pa->size * boids->height; + pa->state.vel[2] = 0.0f; + bpa->data.mode = eBoidMode_OnLand; + } + /* fly above ground */ + else { + pa->state.co[2] = ground_co[2] + pa->size * boids->height; + pa->state.vel[2] = 0.0f; + } } break; } |