diff options
author | Janne Karhu <jhkarh@gmail.com> | 2010-01-23 18:45:01 +0300 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2010-01-23 18:45:01 +0300 |
commit | 9feadd443a69484ec5b56af566d28758cc7ae119 (patch) | |
tree | 97355147e633ad439fb6d56f66b88413bc81dc1c /source | |
parent | 1bb6ba0605d56f5fcb3a190a350659dd2e4ae600 (diff) |
Small fixes for particles.
* Particle collision with size was broken since raytrace optimizations by jaguarandi, now the collision code falls back to old slower method when the collision ray has a radius.
* Single goal/avoid object now works for boids.
* Some tiny improvements on collision avoidance for boids.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/boids.c | 32 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/effect.c | 8 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_kdopbvh.c | 3 |
3 files changed, 32 insertions, 11 deletions
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 838e595d83f..777c653beca 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -77,6 +77,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, EffectedPoint epoint; ListBase *effectors = bbd->sim->psys->effectors; EffectorCache *cur, *eff = NULL; + EffectorCache temp_eff; EffectorData efd, cur_efd; float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0); float priority = 0.0f, len = 0.0f; @@ -91,7 +92,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) { if(gabr->ob == eob) { - /* TODO: objects without any effector and effectors with multiple points */ + /* TODO: effectors with multiple points */ if(get_effector_data(cur, &efd, &epoint, 0)) { if(cur->pd && cur->pd->forcefield == PFIELD_BOID) priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights); @@ -105,7 +106,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, } else if(rule->type == eBoidRuleType_Goal && eob == bpa->ground) ; /* skip current object */ - else if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(eff, &efd, &epoint, 0)) { + else if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(cur, &cur_efd, &epoint, 0)) { float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights); if(temp == 0.0f) @@ -125,11 +126,21 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, } } + /* if the object doesn't have effector data we have to fake it */ + if(eff == NULL && gabr->ob) { + memset(&temp_eff, 0, sizeof(EffectorCache)); + temp_eff.ob = gabr->ob; + temp_eff.scene = bbd->sim->scene; + eff = &temp_eff; + get_effector_data(eff, &efd, &epoint, 0); + priority = 1.0f; + } + /* then use that effector */ if(priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */ Object *eob = eff->ob; - PartDeflect *pd = eob->pd; - float surface = pd->shape == PFIELD_SHAPE_SURFACE ? 1.0f : 0.0f; + PartDeflect *pd = eff->pd; + float surface = (pd && pd->shape == PFIELD_SHAPE_SURFACE) ? 1.0f : 0.0f; if(gabr->options & BRULE_GOAL_AVOID_PREDICT) { /* estimate future location of target */ @@ -219,10 +230,19 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * } /* then avoid that object */ if(hit.index>=0) { - /* TODO: not totally happy with this part */ t = hit.dist/col.ray_len; - VECCOPY(bbd->wanted_co, col.nor); + /* avoid head-on collision */ + if(dot_v3v3(col.nor, pa->prev_state.ave) < -0.99) { + /* don't know why, but uneven range [0.0,1.0] */ + /* works much better than even [-1.0,1.0] */ + bbd->wanted_co[0] = BLI_frand(); + bbd->wanted_co[1] = BLI_frand(); + bbd->wanted_co[2] = BLI_frand(); + } + else { + VECCOPY(bbd->wanted_co, col.nor); + } mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index b261d3365af..f4fea899005 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -593,7 +593,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin float cfra = eff->scene->r.cfra; int ret = 0; - if(eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) { + if(eff->pd && eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) { /* closest point in the object surface is an effector */ float vec[3]; @@ -606,7 +606,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin efd->size = 0.0f; } - else if(eff->pd->shape==PFIELD_SHAPE_POINTS) { + else if(eff->pd && eff->pd->shape==PFIELD_SHAPE_POINTS) { if(eff->ob->derivedFinal) { DerivedMesh *dm = eff->ob->derivedFinal; @@ -667,7 +667,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin normalize_v3(efd->nor); /* for vortex the shape chooses between old / new force */ - if(eff->pd->shape == PFIELD_SHAPE_PLANE) { + if(eff->pd && eff->pd->shape == PFIELD_SHAPE_PLANE) { /* efd->loc is closes point on effector xy-plane */ float temp[3]; sub_v3_v3v3(temp, point->loc, ob->obmat[3]); @@ -698,7 +698,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin efd->distance = len_v3(efd->vec_to_point); /* rest length for harmonic effector, will have to see later if this could be extended to other effectors */ - if(eff->pd->forcefield == PFIELD_HARMONIC && eff->pd->f_size) + if(eff->pd && eff->pd->forcefield == PFIELD_HARMONIC && eff->pd->f_size) mul_v3_fl(efd->vec_to_point, (efd->distance-eff->pd->f_size)/efd->distance); if(eff->flag & PE_USE_NORMAL_DATA) { diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index eebff8dfaef..a91c24471bb 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1502,7 +1502,8 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) //ray-bv is really fast.. and simple tests revealed its worth to test it //before calling the ray-primitive functions - float dist = fast_ray_nearest_hit(data, node); + /* XXX: temporary solution for particles untill fast_ray_nearest_hit supports ray.radius */ + float dist = (data->ray.radius > 0.0f) ? ray_nearest_hit(data, node->bv) : fast_ray_nearest_hit(data, node); if(dist >= data->hit.dist) return; if(node->totnode == 0) |