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.
This commit is contained in:
2010-09-16 20:00:30 +00:00
parent b19521f2b2
commit 43d2d0c6ea

View File

@@ -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;
}