Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/boids.c
| Show First 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | static bool rule_avoid_collision(BoidRule *rule, | ||||
| BoidParticle *bpa = pa->boid; | BoidParticle *bpa = pa->boid; | ||||
| ColliderCache *coll; | ColliderCache *coll; | ||||
| float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; | float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; | ||||
| float co1[3], vel1[3], co2[3], vel2[3]; | float co1[3], vel1[3], co2[3], vel2[3]; | ||||
| float len, t, inp, t_min = 2.0f; | float len, t, inp, t_min = 2.0f; | ||||
| int n, neighbors = 0, nearest = 0; | int n, neighbors = 0, nearest = 0; | ||||
| bool ret = 0; | bool ret = 0; | ||||
| // check deflector objects first | /* Check deflector objects first. */ | ||||
| if (acbr->options & BRULE_ACOLL_WITH_DEFLECTORS && bbd->sim->colliders) { | if (acbr->options & BRULE_ACOLL_WITH_DEFLECTORS && bbd->sim->colliders) { | ||||
| ParticleCollision col; | ParticleCollision col; | ||||
| BVHTreeRayHit hit; | BVHTreeRayHit hit; | ||||
| float radius = val->personal_space * pa->size, ray_dir[3]; | float radius = val->personal_space * pa->size, ray_dir[3]; | ||||
| memset(&col, 0, sizeof(ParticleCollision)); | memset(&col, 0, sizeof(ParticleCollision)); | ||||
| copy_v3_v3(col.co1, pa->prev_state.co); | copy_v3_v3(col.co1, pa->prev_state.co); | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | if (hit.index >= 0) { | ||||
| bbd->wanted_speed = sqrtf(t) * len_v3(pa->prev_state.vel); | bbd->wanted_speed = sqrtf(t) * len_v3(pa->prev_state.vel); | ||||
| bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed); | bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed); | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| // check boids in own system | /* Check boids in own system. */ | ||||
| if (acbr->options & BRULE_ACOLL_WITH_BOIDS) { | if (acbr->options & BRULE_ACOLL_WITH_BOIDS) { | ||||
| neighbors = BLI_kdtree_3d_range_search_with_len_squared_cb(bbd->sim->psys->tree, | neighbors = BLI_kdtree_3d_range_search_with_len_squared_cb(bbd->sim->psys->tree, | ||||
| pa->prev_state.co, | pa->prev_state.co, | ||||
| &ptn, | &ptn, | ||||
| acbr->look_ahead * | acbr->look_ahead * | ||||
| len_v3(pa->prev_state.vel), | len_v3(pa->prev_state.vel), | ||||
| len_squared_v3v3_with_normal_bias, | len_squared_v3v3_with_normal_bias, | ||||
| pa->prev_state.ave); | pa->prev_state.ave); | ||||
| ▲ Show 20 Lines • Show All 513 Lines • ▼ Show 20 Lines | static boid_rule_cb boid_rules[] = { | ||||
| rule_goal_avoid, | rule_goal_avoid, | ||||
| rule_goal_avoid, | rule_goal_avoid, | ||||
| rule_avoid_collision, | rule_avoid_collision, | ||||
| rule_separate, | rule_separate, | ||||
| rule_flock, | rule_flock, | ||||
| rule_follow_leader, | rule_follow_leader, | ||||
| rule_average_speed, | rule_average_speed, | ||||
| rule_fight, | rule_fight, | ||||
| // rule_help, | #if 0 | ||||
| // rule_protect, | rule_help, | ||||
| // rule_hide, | rule_protect, | ||||
| // rule_follow_path, | rule_hide, | ||||
| // rule_follow_wall, | rule_follow_path, | ||||
| rule_follow_wall, | |||||
| #endif | |||||
| }; | }; | ||||
| static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *pa) | static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *pa) | ||||
| { | { | ||||
| BoidParticle *bpa = pa->boid; | BoidParticle *bpa = pa->boid; | ||||
| if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { | if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { | ||||
| val->max_speed = boids->land_max_speed * bpa->data.health / boids->health; | val->max_speed = boids->land_max_speed * bpa->data.health / boids->health; | ||||
| ▲ Show 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | static BoidState *get_boid_state(BoidSettings *boids, ParticleData *pa) | ||||
| /* for some reason particle isn't at a valid state */ | /* for some reason particle isn't at a valid state */ | ||||
| state = boids->states.first; | state = boids->states.first; | ||||
| if (state) { | if (state) { | ||||
| bpa->data.state_id = state->id; | bpa->data.state_id = state->id; | ||||
| } | } | ||||
| return state; | return state; | ||||
| } | } | ||||
| // static int boid_condition_is_true(BoidCondition *cond) | |||||
| //{ | #if 0 /* TODO */ | ||||
| // /* TODO */ | static int boid_condition_is_true(BoidCondition *cond) | ||||
| // return 0; | { | ||||
| //} | return 0; | ||||
| } | |||||
| #endif | |||||
| /* determines the velocity the boid wants to have */ | /* determines the velocity the boid wants to have */ | ||||
| void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) | void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) | ||||
| { | { | ||||
| BoidRule *rule; | BoidRule *rule; | ||||
| BoidSettings *boids = bbd->part->boids; | BoidSettings *boids = bbd->part->boids; | ||||
| BoidValues val; | BoidValues val; | ||||
| BoidState *state = get_boid_state(boids, pa); | BoidState *state = get_boid_state(boids, pa); | ||||
| BoidParticle *bpa = pa->boid; | BoidParticle *bpa = pa->boid; | ||||
| ParticleSystem *psys = bbd->sim->psys; | ParticleSystem *psys = bbd->sim->psys; | ||||
| int rand; | int rand; | ||||
| // BoidCondition *cond; | |||||
| if (bpa->data.health <= 0.0f) { | if (bpa->data.health <= 0.0f) { | ||||
| pa->alive = PARS_DYING; | pa->alive = PARS_DYING; | ||||
| pa->dietime = bbd->cfra; | pa->dietime = bbd->cfra; | ||||
| return; | return; | ||||
| } | } | ||||
| // planned for near future | /* Planned for near future. */ | ||||
| // cond = state->conditions.first; | #if 0 | ||||
| // for (; cond; cond=cond->next) { | BoidCondition *cond = state->conditions.first; | ||||
| // if (boid_condition_is_true(cond)) { | for (; cond; cond = cond->next) { | ||||
| // pa->boid->state_id = cond->state_id; | if (boid_condition_is_true(cond)) { | ||||
| // state = get_boid_state(boids, pa); | pa->boid->state_id = cond->state_id; | ||||
| // break; /* only first true condition is used */ | state = get_boid_state(boids, pa); | ||||
| // } | break; /* only first true condition is used */ | ||||
| //} | } | ||||
| } | |||||
| #endif | |||||
| zero_v3(bbd->wanted_co); | zero_v3(bbd->wanted_co); | ||||
| bbd->wanted_speed = 0.0f; | bbd->wanted_speed = 0.0f; | ||||
| /* create random seed for every particle & frame */ | /* create random seed for every particle & frame */ | ||||
| rand = (int)(psys_frand(psys, psys->seed + p) * 1000); | rand = (int)(psys_frand(psys, psys->seed + p) * 1000); | ||||
| rand = (int)(psys_frand(psys, (int)bbd->cfra + rand) * 1000); | rand = (int)(psys_frand(psys, (int)bbd->cfra + rand) * 1000); | ||||
| ▲ Show 20 Lines • Show All 389 Lines • ▼ Show 20 Lines | case eBoidMode_Falling: { | ||||
| } | } | ||||
| else { | else { | ||||
| bpa->data.mode = eBoidMode_InAir; | bpa->data.mode = eBoidMode_InAir; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case eBoidMode_Climbing: { | case eBoidMode_Climbing: { | ||||
| boid_climb(boids, pa, ground_co, ground_nor); | boid_climb(boids, pa, ground_co, ground_nor); | ||||
| // float nor[3]; | #if 0 | ||||
| // copy_v3_v3(nor, ground_nor); | float nor[3]; | ||||
| copy_v3_v3(nor, ground_nor); | |||||
| /* Gather apparent gravity to r_ve. */ | |||||
| madd_v3_v3fl(pa->r_ve, ground_nor, -1.0); | |||||
| normalize_v3(pa->r_ve); | |||||
| /* Raise boid it's size from surface. */ | |||||
| mul_v3_fl(nor, pa->size * boids->height); | |||||
| add_v3_v3v3(pa->state.co, ground_co, nor); | |||||
| ///* gather apparent gravity to r_ve */ | /* Remove normal component from velocity. */ | ||||
| // madd_v3_v3fl(pa->r_ve, ground_nor, -1.0); | project_v3_v3v3(v, pa->state.vel, ground_nor); | ||||
| // normalize_v3(pa->r_ve); | sub_v3_v3v3(pa->state.vel, pa->state.vel, v); | ||||
| #endif | |||||
| ///* raise boid it's size from surface */ | |||||
| // mul_v3_fl(nor, pa->size * boids->height); | |||||
| // add_v3_v3v3(pa->state.co, ground_co, nor); | |||||
| ///* remove normal component from velocity */ | |||||
| // project_v3_v3v3(v, pa->state.vel, ground_nor); | |||||
| // sub_v3_v3v3(pa->state.vel, pa->state.vel, v); | |||||
| break; | break; | ||||
| } | } | ||||
| case eBoidMode_OnLand: { | case eBoidMode_OnLand: { | ||||
| /* stick boid on goal when close enough */ | /* stick boid on goal when close enough */ | ||||
| if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= | if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= | ||||
| pa->size * boids->height) { | pa->size * boids->height) { | ||||
| bpa->data.mode = eBoidMode_Climbing; | bpa->data.mode = eBoidMode_Climbing; | ||||
| bpa->ground = bbd->goal_ob; | bpa->ground = bbd->goal_ob; | ||||
| ▲ Show 20 Lines • Show All 219 Lines • Show Last 20 Lines | |||||