2011-10-10 09:38:02 +00:00
|
|
|
/*
|
2009-07-20 23:52:53 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-07-20 23:52:53 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2009 by Janne Karhu.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:40:57 +00:00
|
|
|
/** \file blender/blenkernel/intern/boids.c
|
|
|
|
* \ingroup bke
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2009-07-20 23:52:53 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_object_force.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
|
|
|
#include "BLI_rand.h"
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2009-07-20 23:52:53 +00:00
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_kdtree.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
#include "BKE_collision.h"
|
2009-07-20 23:52:53 +00:00
|
|
|
#include "BKE_effect.h"
|
|
|
|
#include "BKE_boids.h"
|
|
|
|
#include "BKE_particle.h"
|
2011-01-07 19:18:31 +00:00
|
|
|
|
2009-07-20 23:52:53 +00:00
|
|
|
#include "BKE_modifier.h"
|
|
|
|
|
|
|
|
#include "RNA_enum_types.h"
|
|
|
|
|
|
|
|
typedef struct BoidValues {
|
|
|
|
float max_speed, max_acc;
|
|
|
|
float max_ave, min_speed;
|
|
|
|
float personal_space, jump_speed;
|
|
|
|
} BoidValues;
|
|
|
|
|
|
|
|
static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness);
|
|
|
|
|
2010-10-17 06:38:56 +00:00
|
|
|
static int rule_none(BoidRule *UNUSED(rule), BoidBrainData *UNUSED(data), BoidValues *UNUSED(val), ParticleData *UNUSED(pa))
|
2009-07-20 23:52:53 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
|
|
|
|
{
|
|
|
|
BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule;
|
|
|
|
BoidSettings *boids = bbd->part->boids;
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
EffectedPoint epoint;
|
|
|
|
ListBase *effectors = bbd->sim->psys->effectors;
|
|
|
|
EffectorCache *cur, *eff = NULL;
|
2010-01-23 15:45:01 +00:00
|
|
|
EffectorCache temp_eff;
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
EffectorData efd, cur_efd;
|
2009-07-20 23:52:53 +00:00
|
|
|
float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
|
2009-08-26 00:38:43 +00:00
|
|
|
float priority = 0.0f, len = 0.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
/* first find out goal/predator with highest priority */
|
2012-03-24 07:52:14 +00:00
|
|
|
if (effectors) for (cur = effectors->first; cur; cur=cur->next) {
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
Object *eob = cur->ob;
|
|
|
|
PartDeflect *pd = cur->pd;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) {
|
|
|
|
if (gabr->ob == eob) {
|
2010-01-23 15:45:01 +00:00
|
|
|
/* TODO: effectors with multiple points */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (get_effector_data(cur, &efd, &epoint, 0)) {
|
|
|
|
if (cur->pd && cur->pd->forcefield == PFIELD_BOID)
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights);
|
|
|
|
else
|
|
|
|
priority = 1.0;
|
|
|
|
|
|
|
|
eff = cur;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-10-14 13:08:19 +00:00
|
|
|
else if (rule->type == eBoidRuleType_Goal && eob == bpa->ground) {
|
|
|
|
/* skip current object */
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(cur, &cur_efd, &epoint, 0)) {
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights);
|
|
|
|
|
2012-10-14 13:08:19 +00:00
|
|
|
if (temp == 0.0f) {
|
|
|
|
/* do nothing */
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (temp > priority) {
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
priority = temp;
|
|
|
|
eff = cur;
|
|
|
|
efd = cur_efd;
|
|
|
|
len = efd.distance;
|
|
|
|
}
|
|
|
|
/* choose closest object with same priority */
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (temp == priority && efd.distance < len) {
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
eff = cur;
|
|
|
|
efd = cur_efd;
|
|
|
|
len = efd.distance;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-23 15:45:01 +00:00
|
|
|
/* if the object doesn't have effector data we have to fake it */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (eff == NULL && gabr->ob) {
|
2010-01-23 15:45:01 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-07-20 23:52:53 +00:00
|
|
|
/* then use that effector */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
Object *eob = eff->ob;
|
2010-01-23 15:45:01 +00:00
|
|
|
PartDeflect *pd = eff->pd;
|
|
|
|
float surface = (pd && pd->shape == PFIELD_SHAPE_SURFACE) ? 1.0f : 0.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (gabr->options & BRULE_GOAL_AVOID_PREDICT) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* estimate future location of target */
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
get_effector_data(eff, &efd, &epoint, 1);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(efd.vel, efd.distance / (val->max_speed * bbd->timestep));
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(efd.loc, efd.vel);
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(efd.vec_to_point, pa->prev_state.co, efd.loc);
|
|
|
|
efd.distance = len_v3(efd.vec_to_point);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (rule->type == eBoidRuleType_Goal && boids->options & BOID_ALLOW_CLIMB && surface!=0.0f) {
|
|
|
|
if (!bbd->goal_ob || bbd->goal_priority < priority) {
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->goal_ob = eob;
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(bbd->goal_co, efd.loc);
|
|
|
|
copy_v3_v3(bbd->goal_nor, efd.nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing &&
|
2009-07-20 23:52:53 +00:00
|
|
|
priority > 2.0f * gabr->fear_factor) {
|
|
|
|
/* detach from surface and try to fly away from danger */
|
2010-02-26 09:02:52 +00:00
|
|
|
negate_v3_v3(efd.vec_to_point, bpa->gravity);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, efd.vec_to_point);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(bbd->wanted_co, mul);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
bbd->wanted_speed = val->max_speed * priority;
|
|
|
|
|
|
|
|
/* with goals factor is approach velocity factor */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (rule->type == eBoidRuleType_Goal && boids->landing_smoothness > 0.0f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
float len2 = 2.0f*len_v3(pa->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
surface *= pa->size * boids->height;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len2 > 0.0f && efd.distance - surface < len2) {
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
len2 = (efd.distance - surface)/len2;
|
2011-11-11 12:00:08 +00:00
|
|
|
bbd->wanted_speed *= powf(len2, boids->landing_smoothness);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
|
|
|
|
{
|
|
|
|
BoidRuleAvoidCollision *acbr = (BoidRuleAvoidCollision*) rule;
|
|
|
|
KDTreeNearest *ptn = NULL;
|
|
|
|
ParticleTarget *pt;
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
ColliderCache *coll;
|
2009-07-20 23:52:53 +00:00
|
|
|
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 len, t, inp, t_min = 2.0f;
|
|
|
|
int n, neighbors = 0, nearest = 0;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
//check deflector objects first
|
2012-03-24 06:18:31 +00:00
|
|
|
if (acbr->options & BRULE_ACOLL_WITH_DEFLECTORS && bbd->sim->colliders) {
|
2009-07-20 23:52:53 +00:00
|
|
|
ParticleCollision col;
|
|
|
|
BVHTreeRayHit hit;
|
|
|
|
float radius = val->personal_space * pa->size, ray_dir[3];
|
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(col.co1, pa->prev_state.co);
|
2009-11-10 20:43:45 +00:00
|
|
|
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);
|
2010-11-02 21:16:41 +00:00
|
|
|
col.f = 0.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
hit.index = -1;
|
2011-03-18 15:31:32 +00:00
|
|
|
hit.dist = col.original_ray_length = len_v3(ray_dir);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* find out closest deflector object */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (coll = bbd->sim->colliders->first; coll; coll=coll->next) {
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
/* don't check with current ground object */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (coll->ob == bpa->ground)
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
continue;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-03-18 15:31:32 +00:00
|
|
|
col.current = coll->ob;
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
col.md = coll->collmd;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (col.md && col.md->bvhtree)
|
2011-03-18 15:31:32 +00:00
|
|
|
BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, BKE_psys_collision_neartest_cb, &col);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
/* then avoid that object */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (hit.index>=0) {
|
2011-03-18 15:31:32 +00:00
|
|
|
t = hit.dist/col.original_ray_length;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2010-01-23 15:45:01 +00:00
|
|
|
/* avoid head-on collision */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dot_v3v3(col.pce.nor, pa->prev_state.ave) < -0.99f) {
|
2012-04-29 15:47:02 +00:00
|
|
|
/* don't know why, but uneven range [0.0, 1.0] */
|
|
|
|
/* works much better than even [-1.0, 1.0] */
|
2010-01-23 15:45:01 +00:00
|
|
|
bbd->wanted_co[0] = BLI_frand();
|
|
|
|
bbd->wanted_co[1] = BLI_frand();
|
|
|
|
bbd->wanted_co[2] = BLI_frand();
|
|
|
|
}
|
|
|
|
else {
|
2011-03-18 15:31:32 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, col.pce.nor);
|
2010-01-23 15:45:01 +00:00
|
|
|
}
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-11 12:00:08 +00:00
|
|
|
bbd->wanted_speed = sqrtf(t) * len_v3(pa->prev_state.vel);
|
2010-09-16 20:00:30 +00:00
|
|
|
bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//check boids in own system
|
2012-03-06 18:40:15 +00:00
|
|
|
if (acbr->options & BRULE_ACOLL_WITH_BOIDS) {
|
2009-11-10 20:43:45 +00:00
|
|
|
neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, acbr->look_ahead * len_v3(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn);
|
2012-03-24 07:52:14 +00:00
|
|
|
if (neighbors > 1) for (n=1; n<neighbors; n++) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(co1, pa->prev_state.co);
|
|
|
|
copy_v3_v3(vel1, pa->prev_state.vel);
|
|
|
|
copy_v3_v3(co2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.co);
|
|
|
|
copy_v3_v3(vel2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(loc, co1, co2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, vel1, vel2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
inp = dot_v3v3(vec, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* velocities not parallel */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (inp != 0.0f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
t = -dot_v3v3(loc, vec)/inp;
|
2009-07-20 23:52:53 +00:00
|
|
|
/* cpa is not too far in the future so investigate further */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (t > 0.0f && t < t_min) {
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(co1, vel1, t);
|
|
|
|
madd_v3_v3fl(co2, vel2, t);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, co2, co1);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
len = normalize_v3(vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* distance of cpa is close enough */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len < 2.0f * val->personal_space * pa->size) {
|
2009-07-20 23:52:53 +00:00
|
|
|
t_min = t;
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(vec, len_v3(vel1));
|
|
|
|
mul_v3_fl(vec, (2.0f - t)/2.0f);
|
|
|
|
sub_v3_v3v3(bbd->wanted_co, vel1, vec);
|
|
|
|
bbd->wanted_speed = len_v3(bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ptn) { MEM_freeN(ptn); ptn=NULL; }
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* check boids in other systems */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
|
2009-09-17 22:00:49 +00:00
|
|
|
ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (epsys) {
|
2009-11-10 20:43:45 +00:00
|
|
|
neighbors = BLI_kdtree_range_search(epsys->tree, acbr->look_ahead * len_v3(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn);
|
2012-03-24 07:52:14 +00:00
|
|
|
if (neighbors > 0) for (n=0; n<neighbors; n++) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(co1, pa->prev_state.co);
|
|
|
|
copy_v3_v3(vel1, pa->prev_state.vel);
|
|
|
|
copy_v3_v3(co2, (epsys->particles + ptn[n].index)->prev_state.co);
|
|
|
|
copy_v3_v3(vel2, (epsys->particles + ptn[n].index)->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(loc, co1, co2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, vel1, vel2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
inp = dot_v3v3(vec, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* velocities not parallel */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (inp != 0.0f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
t = -dot_v3v3(loc, vec)/inp;
|
2009-07-20 23:52:53 +00:00
|
|
|
/* cpa is not too far in the future so investigate further */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (t > 0.0f && t < t_min) {
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(co1, vel1, t);
|
|
|
|
madd_v3_v3fl(co2, vel2, t);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, co2, co1);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
len = normalize_v3(vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* distance of cpa is close enough */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len < 2.0f * val->personal_space * pa->size) {
|
2009-07-20 23:52:53 +00:00
|
|
|
t_min = t;
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(vec, len_v3(vel1));
|
|
|
|
mul_v3_fl(vec, (2.0f - t)/2.0f);
|
|
|
|
sub_v3_v3v3(bbd->wanted_co, vel1, vec);
|
|
|
|
bbd->wanted_speed = len_v3(bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ptn) { MEM_freeN(ptn); ptn=NULL; }
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ptn && nearest==0)
|
2009-07-20 23:52:53 +00:00
|
|
|
MEM_freeN(ptn);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2010-10-17 06:38:56 +00:00
|
|
|
static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
|
2009-07-20 23:52:53 +00:00
|
|
|
{
|
|
|
|
KDTreeNearest *ptn = NULL;
|
|
|
|
ParticleTarget *pt;
|
|
|
|
float len = 2.0f * val->personal_space * pa->size + 1.0f;
|
|
|
|
float vec[3] = {0.0f, 0.0f, 0.0f};
|
2009-09-17 22:00:49 +00:00
|
|
|
int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn);
|
2009-07-20 23:52:53 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (neighbors > 1 && ptn[1].dist!=0.0f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, pa->prev_state.co, bbd->sim->psys->particles[ptn[1].index].state.co);
|
|
|
|
mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[1].dist) / ptn[1].dist);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(bbd->wanted_co, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = val->max_speed;
|
|
|
|
len = ptn[1].dist;
|
|
|
|
ret = 1;
|
|
|
|
}
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ptn) { MEM_freeN(ptn); ptn=NULL; }
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* check other boid systems */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
|
2009-09-17 22:00:49 +00:00
|
|
|
ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (epsys) {
|
2009-07-20 23:52:53 +00:00
|
|
|
neighbors = BLI_kdtree_range_search(epsys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (neighbors > 0 && ptn[0].dist < len) {
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, pa->prev_state.co, ptn[0].co);
|
|
|
|
mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[0].dist) / ptn[1].dist);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(bbd->wanted_co, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = val->max_speed;
|
|
|
|
len = ptn[0].dist;
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ptn) { MEM_freeN(ptn); ptn=NULL; }
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2010-10-17 06:38:56 +00:00
|
|
|
static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UNUSED(val), ParticleData *pa)
|
2009-07-20 23:52:53 +00:00
|
|
|
{
|
|
|
|
KDTreeNearest ptn[11];
|
|
|
|
float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
|
2009-09-17 22:00:49 +00:00
|
|
|
int neighbors = BLI_kdtree_find_n_nearest(bbd->sim->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn);
|
2009-07-25 22:20:26 +00:00
|
|
|
int n;
|
2009-07-20 23:52:53 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (neighbors > 1) {
|
|
|
|
for (n=1; n<neighbors; n++) {
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(loc, bbd->sim->psys->particles[ptn[n].index].prev_state.co);
|
|
|
|
add_v3_v3(vec, bbd->sim->psys->particles[ptn[n].index].prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(loc, 1.0f/((float)neighbors - 1.0f));
|
|
|
|
mul_v3_fl(vec, 1.0f/((float)neighbors - 1.0f));
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2010-04-23 23:57:00 +00:00
|
|
|
sub_v3_v3(loc, pa->prev_state.co);
|
|
|
|
sub_v3_v3(vec, pa->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(bbd->wanted_co, vec);
|
|
|
|
add_v3_v3(bbd->wanted_co, loc);
|
2009-11-10 20:43:45 +00:00
|
|
|
bbd->wanted_speed = len_v3(bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
|
|
|
|
{
|
|
|
|
BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule;
|
|
|
|
float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
|
|
|
|
float mul, len;
|
2009-09-17 22:00:49 +00:00
|
|
|
int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size;
|
|
|
|
int i, ret = 0, p = pa - bbd->sim->psys->particles;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (flbr->ob) {
|
2009-07-20 23:52:53 +00:00
|
|
|
float vec2[3], t;
|
|
|
|
|
2012-08-17 14:43:20 +00:00
|
|
|
/* first check we're not blocking the leader */
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, flbr->loc, flbr->oloc);
|
|
|
|
mul_v3_fl(vec, 1.0f/bbd->timestep);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(loc, pa->prev_state.co, flbr->oloc);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul = dot_v3v3(vec, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* leader is not moving */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (mul < 0.01f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
len = len_v3(loc);
|
2009-07-20 23:52:53 +00:00
|
|
|
/* too close to leader */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len < 2.0f * val->personal_space * pa->size) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, loc);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = val->max_speed;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2009-11-10 20:43:45 +00:00
|
|
|
t = dot_v3v3(loc, vec)/mul;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* possible blocking of leader in near future */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (t > 0.0f && t < 3.0f) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(vec2, vec);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(vec2, t);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec2, loc, vec2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
len = len_v3(vec2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len < 2.0f * val->personal_space * pa->size) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, vec2);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = val->max_speed * (3.0f - t)/3.0f;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* not blocking so try to follow leader */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (p && flbr->options & BRULE_LEADER_IN_LINE) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(vec, bbd->sim->psys->particles[p-1].prev_state.vel);
|
|
|
|
copy_v3_v3(loc, bbd->sim->psys->particles[p-1].prev_state.co);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(loc, flbr->oloc);
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, flbr->loc, flbr->oloc);
|
2011-04-02 02:08:33 +00:00
|
|
|
mul_v3_fl(vec, 1.0f/bbd->timestep);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* fac is seconds behind leader */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(loc, vec, -flbr->distance);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(bbd->wanted_co, loc, pa->prev_state.co);
|
|
|
|
bbd->wanted_speed = len_v3(bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (p % n) {
|
2009-07-20 23:52:53 +00:00
|
|
|
float vec2[3], t, t_min = 3.0f;
|
|
|
|
|
|
|
|
/* first check we're not blocking any leaders */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (i = 0; i< bbd->sim->psys->totpart; i+=n) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(vec, bbd->sim->psys->particles[i].prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(loc, pa->prev_state.co, bbd->sim->psys->particles[i].prev_state.co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul = dot_v3v3(vec, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* leader is not moving */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (mul < 0.01f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
len = len_v3(loc);
|
2009-07-20 23:52:53 +00:00
|
|
|
/* too close to leader */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len < 2.0f * val->personal_space * pa->size) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, loc);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = val->max_speed;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2009-11-10 20:43:45 +00:00
|
|
|
t = dot_v3v3(loc, vec)/mul;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* possible blocking of leader in near future */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (t > 0.0f && t < t_min) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(vec2, vec);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(vec2, t);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec2, loc, vec2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
len = len_v3(vec2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len < 2.0f * val->personal_space * pa->size) {
|
2009-07-20 23:52:53 +00:00
|
|
|
t_min = t;
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, loc);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = val->max_speed * (3.0f - t)/3.0f;
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ret) return 1;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* not blocking so try to follow leader */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (flbr->options & BRULE_LEADER_IN_LINE) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(vec, bbd->sim->psys->particles[p-1].prev_state.vel);
|
|
|
|
copy_v3_v3(loc, bbd->sim->psys->particles[p-1].prev_state.co);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(vec, bbd->sim->psys->particles[p - p%n].prev_state.vel);
|
|
|
|
copy_v3_v3(loc, bbd->sim->psys->particles[p - p%n].prev_state.co);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* fac is seconds behind leader */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(loc, vec, -flbr->distance);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(bbd->wanted_co, loc, pa->prev_state.co);
|
|
|
|
bbd->wanted_speed = len_v3(bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
|
|
|
|
{
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
2009-07-20 23:52:53 +00:00
|
|
|
BoidRuleAverageSpeed *asbr = (BoidRuleAverageSpeed*)rule;
|
|
|
|
float vec[3] = {0.0f, 0.0f, 0.0f};
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (asbr->wander > 0.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* abuse pa->r_ave for wandering */
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
|
|
|
|
bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
|
|
|
|
bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(bpa->wander);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(vec, bpa->wander);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_qt_v3(pa->prev_state.rot, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(bbd->wanted_co, 1.1f);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(bbd->wanted_co, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* leveling */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
|
2009-12-30 15:58:59 +00:00
|
|
|
project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(vec, asbr->level);
|
2010-04-23 23:57:00 +00:00
|
|
|
sub_v3_v3(bbd->wanted_co, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* may happen at birth */
|
2012-04-29 15:47:02 +00:00
|
|
|
if (dot_v2v2(bbd->wanted_co, bbd->wanted_co)==0.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_co[0] = 2.0f*(0.5f - BLI_frand());
|
|
|
|
bbd->wanted_co[1] = 2.0f*(0.5f - BLI_frand());
|
|
|
|
bbd->wanted_co[2] = 2.0f*(0.5f - BLI_frand());
|
|
|
|
}
|
|
|
|
|
|
|
|
/* leveling */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
|
2009-12-30 15:58:59 +00:00
|
|
|
project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(vec, asbr->level);
|
2010-04-23 23:57:00 +00:00
|
|
|
sub_v3_v3(bbd->wanted_co, vec);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
bbd->wanted_speed = asbr->speed * val->max_speed;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
|
|
|
|
{
|
|
|
|
BoidRuleFight *fbr = (BoidRuleFight*)rule;
|
|
|
|
KDTreeNearest *ptn = NULL;
|
|
|
|
ParticleTarget *pt;
|
|
|
|
ParticleData *epars;
|
2009-08-26 00:38:43 +00:00
|
|
|
ParticleData *enemy_pa = NULL;
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa;
|
2009-07-20 23:52:53 +00:00
|
|
|
/* friends & enemies */
|
2012-04-29 15:47:02 +00:00
|
|
|
float closest_enemy[3] = {0.0f, 0.0f, 0.0f};
|
2009-07-20 23:52:53 +00:00
|
|
|
float closest_dist = fbr->distance + 1.0f;
|
|
|
|
float f_strength = 0.0f, e_strength = 0.0f;
|
|
|
|
float health = 0.0f;
|
|
|
|
int n, ret = 0;
|
|
|
|
|
|
|
|
/* calculate own group strength */
|
2009-09-17 22:00:49 +00:00
|
|
|
int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn);
|
2012-03-24 06:18:31 +00:00
|
|
|
for (n=0; n<neighbors; n++) {
|
2009-09-17 22:00:49 +00:00
|
|
|
bpa = bbd->sim->psys->particles[ptn[n].index].boid;
|
2009-09-04 23:06:15 +00:00
|
|
|
health += bpa->data.health;
|
|
|
|
}
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
f_strength += bbd->part->boids->strength * health;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ptn) { MEM_freeN(ptn); ptn=NULL; }
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* add other friendlies and calculate enemy strength and find closest enemy */
|
2012-03-24 06:18:31 +00:00
|
|
|
for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
|
2009-09-17 22:00:49 +00:00
|
|
|
ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (epsys) {
|
2009-07-20 23:52:53 +00:00
|
|
|
epars = epsys->particles;
|
|
|
|
|
|
|
|
neighbors = BLI_kdtree_range_search(epsys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn);
|
|
|
|
|
|
|
|
health = 0.0f;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (n=0; n<neighbors; n++) {
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa = epars[ptn[n].index].boid;
|
|
|
|
health += bpa->data.health;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (n==0 && pt->mode==PTARGET_MODE_ENEMY && ptn[n].dist < closest_dist) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(closest_enemy, ptn[n].co);
|
2009-07-20 23:52:53 +00:00
|
|
|
closest_dist = ptn[n].dist;
|
|
|
|
enemy_pa = epars + ptn[n].index;
|
|
|
|
}
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
if (pt->mode==PTARGET_MODE_ENEMY)
|
2009-07-20 23:52:53 +00:00
|
|
|
e_strength += epsys->part->boids->strength * health;
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (pt->mode==PTARGET_MODE_FRIEND)
|
2009-07-20 23:52:53 +00:00
|
|
|
f_strength += epsys->part->boids->strength * health;
|
|
|
|
|
2012-02-23 02:17:50 +00:00
|
|
|
if (ptn) { MEM_freeN(ptn); ptn=NULL; }
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* decide action if enemy presence found */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (e_strength > 0.0f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(bbd->wanted_co, closest_enemy, pa->prev_state.co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* attack if in range */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (closest_dist <= bbd->part->boids->range + pa->size + enemy_pa->size) {
|
2009-07-20 23:52:53 +00:00
|
|
|
float damage = BLI_frand();
|
2010-08-15 15:14:08 +00:00
|
|
|
float enemy_dir[3];
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2010-08-15 15:14:08 +00:00
|
|
|
normalize_v3_v3(enemy_dir, bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* fight mode */
|
|
|
|
bbd->wanted_speed = 0.0f;
|
|
|
|
|
|
|
|
/* must face enemy to fight */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dot_v3v3(pa->prev_state.ave, enemy_dir)>0.5f) {
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa = enemy_pa->boid;
|
|
|
|
bpa->data.health -= bbd->part->boids->strength * bbd->timestep * ((1.0f-bbd->part->boids->accuracy)*damage + bbd->part->boids->accuracy);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* approach mode */
|
|
|
|
bbd->wanted_speed = val->max_speed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if boid doesn't want to fight */
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa = pa->boid;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* decide to flee */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (closest_dist < fbr->flee_distance * fbr->distance) {
|
2010-02-26 09:02:52 +00:00
|
|
|
negate_v3(bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = val->max_speed;
|
|
|
|
}
|
|
|
|
else { /* wait for better odds */
|
|
|
|
bbd->wanted_speed = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef int (*boid_rule_cb)(BoidRule *rule, BoidBrainData *data, BoidValues *val, ParticleData *pa);
|
|
|
|
|
|
|
|
static boid_rule_cb boid_rules[] = {
|
|
|
|
rule_none,
|
|
|
|
rule_goal_avoid,
|
|
|
|
rule_goal_avoid,
|
|
|
|
rule_avoid_collision,
|
|
|
|
rule_separate,
|
|
|
|
rule_flock,
|
|
|
|
rule_follow_leader,
|
|
|
|
rule_average_speed,
|
|
|
|
rule_fight,
|
|
|
|
//rule_help,
|
|
|
|
//rule_protect,
|
|
|
|
//rule_hide,
|
|
|
|
//rule_follow_path,
|
|
|
|
//rule_follow_wall
|
|
|
|
};
|
|
|
|
|
|
|
|
static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *pa)
|
|
|
|
{
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
|
2009-09-04 23:06:15 +00:00
|
|
|
val->max_speed = boids->land_max_speed * bpa->data.health/boids->health;
|
2009-07-20 23:52:53 +00:00
|
|
|
val->max_acc = boids->land_max_acc * val->max_speed;
|
2011-04-02 02:08:33 +00:00
|
|
|
val->max_ave = boids->land_max_ave * (float)M_PI * bpa->data.health/boids->health;
|
2009-07-20 23:52:53 +00:00
|
|
|
val->min_speed = 0.0f; /* no minimum speed on land */
|
|
|
|
val->personal_space = boids->land_personal_space;
|
2009-09-04 23:06:15 +00:00
|
|
|
val->jump_speed = boids->land_jump_speed * bpa->data.health/boids->health;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-09-04 23:06:15 +00:00
|
|
|
val->max_speed = boids->air_max_speed * bpa->data.health/boids->health;
|
2009-07-20 23:52:53 +00:00
|
|
|
val->max_acc = boids->air_max_acc * val->max_speed;
|
2011-04-02 02:08:33 +00:00
|
|
|
val->max_ave = boids->air_max_ave * (float)M_PI * bpa->data.health/boids->health;
|
2009-07-20 23:52:53 +00:00
|
|
|
val->min_speed = boids->air_min_speed * boids->air_max_speed;
|
|
|
|
val->personal_space = boids->air_personal_space;
|
|
|
|
val->jump_speed = 0.0f; /* no jumping in air */
|
|
|
|
}
|
|
|
|
}
|
2010-09-16 20:00:30 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float ground_co[3], float ground_nor[3])
|
2009-07-20 23:52:53 +00:00
|
|
|
{
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.mode == eBoidMode_Climbing) {
|
2009-07-20 23:52:53 +00:00
|
|
|
SurfaceModifierData *surmd = NULL;
|
|
|
|
float x[3], v[3];
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
surmd = (SurfaceModifierData *)modifiers_findByType(bpa->ground, eModifierType_Surface );
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* take surface velocity into account */
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
closest_point_on_surface(surmd, pa->state.co, x, NULL, v);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(x, v);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* get actual position on surface */
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
closest_point_on_surface(surmd, x, ground_co, ground_nor, NULL);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-09-04 23:06:15 +00:00
|
|
|
return bpa->ground;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
float zvec[3] = {0.0f, 0.0f, 2000.0f};
|
|
|
|
ParticleCollision col;
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
ColliderCache *coll;
|
2009-07-20 23:52:53 +00:00
|
|
|
BVHTreeRayHit hit;
|
|
|
|
float radius = 0.0f, t, ray_dir[3];
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!bbd->sim->colliders)
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
return NULL;
|
|
|
|
|
2010-09-16 20:00:30 +00:00
|
|
|
/* first try to find below boid */
|
2010-04-23 23:57:00 +00:00
|
|
|
copy_v3_v3(col.co1, pa->state.co);
|
2010-09-16 20:00:30 +00:00
|
|
|
sub_v3_v3v3(col.co2, pa->state.co, zvec);
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(ray_dir, col.co2, col.co1);
|
2010-11-02 21:16:41 +00:00
|
|
|
col.f = 0.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
hit.index = -1;
|
2011-03-18 15:31:32 +00:00
|
|
|
hit.dist = col.original_ray_length = len_v3(ray_dir);
|
|
|
|
col.pce.inside = 0;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
|
2011-03-18 15:31:32 +00:00
|
|
|
col.current = coll->ob;
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
col.md = coll->collmd;
|
2011-03-18 15:31:32 +00:00
|
|
|
col.fac1 = col.fac2 = 0.f;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (col.md && col.md->bvhtree)
|
2011-03-18 15:31:32 +00:00
|
|
|
BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, BKE_psys_collision_neartest_cb, &col);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
/* then use that object */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (hit.index>=0) {
|
2011-03-18 15:31:32 +00:00
|
|
|
t = hit.dist/col.original_ray_length;
|
2009-11-10 20:43:45 +00:00
|
|
|
interp_v3_v3v3(ground_co, col.co1, col.co2, t);
|
2011-03-18 15:31:32 +00:00
|
|
|
normalize_v3_v3(ground_nor, col.pce.nor);
|
|
|
|
return col.hit;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
2010-09-16 20:00:30 +00:00
|
|
|
|
|
|
|
/* couldn't find below, so find upmost deflector object */
|
2010-09-16 20:33:46 +00:00
|
|
|
add_v3_v3v3(col.co1, pa->state.co, zvec);
|
2010-09-16 20:00:30 +00:00
|
|
|
sub_v3_v3v3(col.co2, pa->state.co, zvec);
|
|
|
|
sub_v3_v3(col.co2, zvec);
|
|
|
|
sub_v3_v3v3(ray_dir, col.co2, col.co1);
|
2010-11-02 21:16:41 +00:00
|
|
|
col.f = 0.0f;
|
2010-09-16 20:00:30 +00:00
|
|
|
hit.index = -1;
|
2011-03-18 15:31:32 +00:00
|
|
|
hit.dist = col.original_ray_length = len_v3(ray_dir);
|
2010-09-16 20:00:30 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
|
2011-03-18 15:31:32 +00:00
|
|
|
col.current = coll->ob;
|
2010-09-16 20:00:30 +00:00
|
|
|
col.md = coll->collmd;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (col.md && col.md->bvhtree)
|
2011-03-18 15:31:32 +00:00
|
|
|
BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, BKE_psys_collision_neartest_cb, &col);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
2010-09-16 20:00:30 +00:00
|
|
|
/* then use that object */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (hit.index>=0) {
|
2011-03-18 15:31:32 +00:00
|
|
|
t = hit.dist/col.original_ray_length;
|
2010-09-16 20:00:30 +00:00
|
|
|
interp_v3_v3v3(ground_co, col.co1, col.co2, t);
|
2011-03-18 15:31:32 +00:00
|
|
|
normalize_v3_v3(ground_nor, col.pce.nor);
|
|
|
|
return col.hit;
|
2010-09-16 20:00:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* default to z=0 */
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(ground_co, pa->state.co);
|
2010-09-16 20:00:30 +00:00
|
|
|
ground_co[2] = 0;
|
|
|
|
ground_nor[0] = ground_nor[1] = 0.0f;
|
|
|
|
ground_nor[2] = 1.0f;
|
|
|
|
return NULL;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-16 14:32:17 +00:00
|
|
|
static int boid_rule_applies(ParticleData *pa, BoidSettings *UNUSED(boids), BoidRule *rule)
|
2009-07-20 23:52:53 +00:00
|
|
|
{
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (rule==NULL)
|
2009-07-20 23:52:53 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing) && rule->flag & BOIDRULE_ON_LAND)
|
2009-07-20 23:52:53 +00:00
|
|
|
return 1;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.mode==eBoidMode_InAir && rule->flag & BOIDRULE_IN_AIR)
|
2009-07-20 23:52:53 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void boids_precalc_rules(ParticleSettings *part, float cfra)
|
|
|
|
{
|
|
|
|
BoidState *state = part->boids->states.first;
|
|
|
|
BoidRule *rule;
|
2012-03-24 06:18:31 +00:00
|
|
|
for (; state; state=state->next) {
|
|
|
|
for (rule = state->rules.first; rule; rule=rule->next) {
|
|
|
|
if (rule->type==eBoidRuleType_FollowLeader) {
|
2009-07-20 23:52:53 +00:00
|
|
|
BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (flbr->ob && flbr->cfra != cfra) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* save object locations for velocity calculations */
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(flbr->oloc, flbr->loc);
|
|
|
|
copy_v3_v3(flbr->loc, flbr->ob->obmat[3]);
|
2009-07-20 23:52:53 +00:00
|
|
|
flbr->cfra = cfra;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void boid_climb(BoidSettings *boids, ParticleData *pa, float *surface_co, float *surface_nor)
|
|
|
|
{
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
2009-07-20 23:52:53 +00:00
|
|
|
float nor[3], vel[3];
|
2011-09-12 04:14:12 +00:00
|
|
|
copy_v3_v3(nor, surface_nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-09-04 23:06:15 +00:00
|
|
|
/* gather apparent gravity */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(bpa->gravity, surface_nor, -1.0f);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(bpa->gravity);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* raise boid it's size from surface */
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(nor, pa->size * boids->height);
|
|
|
|
add_v3_v3v3(pa->state.co, surface_co, nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* remove normal component from velocity */
|
2009-11-10 20:43:45 +00:00
|
|
|
project_v3_v3v3(vel, pa->state.vel, surface_nor);
|
|
|
|
sub_v3_v3v3(pa->state.vel, pa->state.vel, vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
static float boid_goal_signed_dist(float *boid_co, float *goal_co, float *goal_nor)
|
|
|
|
{
|
|
|
|
float vec[3];
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(vec, boid_co, goal_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
return dot_v3v3(vec, goal_nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
/* wanted_co is relative to boid location */
|
|
|
|
static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (rule==NULL)
|
2009-07-20 23:52:53 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boid_rule_applies(pa, bbd->part->boids, rule)==0)
|
2009-07-20 23:52:53 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boid_rules[rule->type](rule, bbd, val, pa)==0)
|
2009-07-20 23:52:53 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (fuzziness < 0.0f || compare_len_v3v3(bbd->wanted_co, pa->prev_state.vel, fuzziness * len_v3(pa->prev_state.vel))==0)
|
2009-07-20 23:52:53 +00:00
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
2011-09-28 05:53:40 +00:00
|
|
|
static BoidState *get_boid_state(BoidSettings *boids, ParticleData *pa)
|
|
|
|
{
|
2009-07-20 23:52:53 +00:00
|
|
|
BoidState *state = boids->states.first;
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (; state; state=state->next) {
|
|
|
|
if (state->id==bpa->data.state_id)
|
2009-07-20 23:52:53 +00:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* for some reason particle isn't at a valid state */
|
|
|
|
state = boids->states.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (state)
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.state_id = state->id;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
2012-06-20 16:43:48 +00:00
|
|
|
//static int boid_condition_is_true(BoidCondition *cond)
|
|
|
|
//{
|
2009-07-20 23:52:53 +00:00
|
|
|
// /* TODO */
|
|
|
|
// return 0;
|
|
|
|
//}
|
|
|
|
|
|
|
|
/* determines the velocity the boid wants to have */
|
|
|
|
void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
|
|
|
|
{
|
|
|
|
BoidRule *rule;
|
|
|
|
BoidSettings *boids = bbd->part->boids;
|
|
|
|
BoidValues val;
|
|
|
|
BoidState *state = get_boid_state(boids, pa);
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
2011-07-10 17:04:56 +00:00
|
|
|
ParticleSystem *psys = bbd->sim->psys;
|
2009-09-04 23:06:15 +00:00
|
|
|
int rand;
|
2009-07-20 23:52:53 +00:00
|
|
|
//BoidCondition *cond;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.health <= 0.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
pa->alive = PARS_DYING;
|
2010-09-03 05:54:09 +00:00
|
|
|
pa->dietime = bbd->cfra;
|
2009-07-20 23:52:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//planned for near future
|
|
|
|
//cond = state->conditions.first;
|
2012-03-24 07:52:14 +00:00
|
|
|
//for (; cond; cond=cond->next) {
|
2012-03-24 06:18:31 +00:00
|
|
|
// if (boid_condition_is_true(cond)) {
|
2009-07-20 23:52:53 +00:00
|
|
|
// pa->boid->state_id = cond->state_id;
|
|
|
|
// state = get_boid_state(boids, pa);
|
|
|
|
// break; /* only first true condition is used */
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
|
2012-10-22 08:15:51 +00:00
|
|
|
zero_v3(bbd->wanted_co);
|
|
|
|
bbd->wanted_speed = 0.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* create random seed for every particle & frame */
|
2011-07-10 17:04:56 +00:00
|
|
|
rand = (int)(PSYS_FRAND(psys->seed + p) * 1000);
|
|
|
|
rand = (int)(PSYS_FRAND((int)bbd->cfra + rand) * 1000);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
set_boid_values(&val, bbd->part->boids, pa);
|
|
|
|
|
|
|
|
/* go through rules */
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (state->ruleset_type) {
|
2009-07-20 23:52:53 +00:00
|
|
|
case eBoidRulesetType_Fuzzy:
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
for (rule = state->rules.first; rule; rule = rule->next) {
|
|
|
|
if (apply_boid_rule(bbd, rule, &val, pa, state->rule_fuzziness))
|
2009-07-20 23:52:53 +00:00
|
|
|
break; /* only first nonzero rule that comes through fuzzy rule is applied */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case eBoidRulesetType_Random:
|
|
|
|
{
|
|
|
|
/* use random rule for each particle (allways same for same particle though) */
|
2009-09-04 23:06:15 +00:00
|
|
|
rule = BLI_findlink(&state->rules, rand % BLI_countlist(&state->rules));
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
apply_boid_rule(bbd, rule, &val, pa, -1.0);
|
|
|
|
}
|
|
|
|
case eBoidRulesetType_Average:
|
|
|
|
{
|
|
|
|
float wanted_co[3] = {0.0f, 0.0f, 0.0f}, wanted_speed = 0.0f;
|
|
|
|
int n = 0;
|
2012-03-24 06:18:31 +00:00
|
|
|
for (rule = state->rules.first; rule; rule=rule->next) {
|
|
|
|
if (apply_boid_rule(bbd, rule, &val, pa, -1.0f)) {
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(wanted_co, bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
wanted_speed += bbd->wanted_speed;
|
|
|
|
n++;
|
2012-10-22 08:15:51 +00:00
|
|
|
zero_v3(bbd->wanted_co);
|
|
|
|
bbd->wanted_speed = 0.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (n > 1) {
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(wanted_co, 1.0f/(float)n);
|
2009-07-20 23:52:53 +00:00
|
|
|
wanted_speed /= (float)n;
|
|
|
|
}
|
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bbd->wanted_co, wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed = wanted_speed;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* decide on jumping & liftoff */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.mode == eBoidMode_OnLand) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* fuzziness makes boids capable of misjudgement */
|
2011-04-02 02:08:33 +00:00
|
|
|
float mul = 1.0f + state->rule_fuzziness;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
float cvel[3], dir[3];
|
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(dir, pa->prev_state.ave);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v2(dir);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(cvel, bbd->wanted_co);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v2(cvel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dot_v2v2(cvel, dir) > 0.95f / mul)
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Liftoff;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (val.jump_speed > 0.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
float jump_v[3];
|
|
|
|
int jump = 0;
|
|
|
|
|
|
|
|
/* jump to get to a location */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bbd->wanted_co[2] > 0.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
float cvel[3], dir[3];
|
|
|
|
float z_v, ground_v, cur_v;
|
|
|
|
float len;
|
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(dir, pa->prev_state.ave);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v2(dir);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(cvel, bbd->wanted_co);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v2(cvel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
len = len_v2(pa->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* first of all, are we going in a suitable direction? */
|
|
|
|
/* or at a suitably slow speed */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dot_v2v2(cvel, dir) > 0.95f / mul || len <= state->rule_fuzziness) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* try to reach goal at highest point of the parabolic path */
|
2009-11-10 20:43:45 +00:00
|
|
|
cur_v = len_v2(pa->prev_state.vel);
|
2009-12-30 15:58:59 +00:00
|
|
|
z_v = sasqrt(-2.0f * bbd->sim->scene->physics_settings.gravity[2] * bbd->wanted_co[2]);
|
|
|
|
ground_v = len_v2(bbd->wanted_co)*sasqrt(-0.5f * bbd->sim->scene->physics_settings.gravity[2] / bbd->wanted_co[2]);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
len = sasqrt((ground_v-cur_v)*(ground_v-cur_v) + z_v*z_v);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (len < val.jump_speed * mul || bbd->part->boids->options & BOID_ALLOW_FLIGHT) {
|
2009-07-20 23:52:53 +00:00
|
|
|
jump = 1;
|
|
|
|
|
|
|
|
len = MIN2(len, val.jump_speed);
|
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(jump_v, dir);
|
2009-07-20 23:52:53 +00:00
|
|
|
jump_v[2] = z_v;
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(jump_v, ground_v);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(jump_v);
|
|
|
|
mul_v3_fl(jump_v, len);
|
|
|
|
add_v2_v2v2(jump_v, jump_v, pa->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* jump to go faster */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (jump == 0 && val.jump_speed > val.max_speed && bbd->wanted_speed > val.max_speed) {
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (jump) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(pa->prev_state.vel, jump_v);
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Falling;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* tries to realize the wanted velocity taking all constraints into account */
|
|
|
|
void boid_body(BoidBrainData *bbd, ParticleData *pa)
|
|
|
|
{
|
|
|
|
BoidSettings *boids = bbd->part->boids;
|
2009-09-04 23:06:15 +00:00
|
|
|
BoidParticle *bpa = pa->boid;
|
2009-07-20 23:52:53 +00:00
|
|
|
BoidValues val;
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
EffectedPoint epoint;
|
2009-07-20 23:52:53 +00:00
|
|
|
float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3];
|
|
|
|
float dvec[3], bvec[3];
|
|
|
|
float new_dir[3], new_speed;
|
|
|
|
float old_dir[3], old_speed;
|
|
|
|
float wanted_dir[3];
|
|
|
|
float q[4], mat[3][3]; /* rotation */
|
|
|
|
float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f};
|
2009-10-05 13:25:56 +00:00
|
|
|
float force[3] = {0.0f, 0.0f, 0.0f};
|
2009-07-20 23:52:53 +00:00
|
|
|
float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep;
|
|
|
|
|
|
|
|
set_boid_values(&val, boids, pa);
|
|
|
|
|
|
|
|
/* make sure there's something in new velocity, location & rotation */
|
2012-04-29 15:47:02 +00:00
|
|
|
copy_particle_key(&pa->state, &pa->prev_state, 0);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bbd->part->flag & PART_SIZEMASS)
|
2009-07-20 23:52:53 +00:00
|
|
|
pa_mass*=pa->size;
|
|
|
|
|
|
|
|
/* if boids can't fly they fall to the ground */
|
2012-03-24 06:18:31 +00:00
|
|
|
if ((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && psys_uses_gravity(bbd->sim))
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Falling;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.mode == eBoidMode_Falling) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* Falling boids are only effected by gravity. */
|
2009-12-30 15:58:59 +00:00
|
|
|
acc[2] = bbd->sim->scene->physics_settings.gravity[2];
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* figure out acceleration */
|
|
|
|
float landing_level = 2.0f;
|
|
|
|
float level = landing_level + 1.0f;
|
|
|
|
float new_vel[3];
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.mode == eBoidMode_Liftoff) {
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_InAir;
|
|
|
|
bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (bpa->data.mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* auto-leveling & landing if close to ground */
|
|
|
|
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* level = how many particle sizes above ground */
|
2011-04-02 02:08:33 +00:00
|
|
|
level = (pa->prev_state.co[2] - ground_co[2])/(2.0f * pa->size) - 0.5f;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
landing_level = - boids->landing_smoothness * pa->prev_state.vel[2] * pa_mass;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (pa->prev_state.vel[2] < 0.0f) {
|
|
|
|
if (level < 1.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_co[0] = bbd->wanted_co[1] = bbd->wanted_co[2] = 0.0f;
|
|
|
|
bbd->wanted_speed = 0.0f;
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Falling;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (level < landing_level) {
|
2009-07-20 23:52:53 +00:00
|
|
|
bbd->wanted_speed *= (level - 1.0f)/landing_level;
|
|
|
|
bbd->wanted_co[2] *= (level - 1.0f)/landing_level;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(old_dir, pa->prev_state.ave);
|
2010-08-15 15:14:08 +00:00
|
|
|
new_speed = normalize_v3_v3(wanted_dir, bbd->wanted_co);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* first check if we have valid direction we want to go towards */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (new_speed == 0.0f) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(new_dir, old_dir);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
float old_dir2[2], wanted_dir2[2], nor[3], angle;
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_v2_v2(old_dir2, old_dir);
|
|
|
|
normalize_v2(old_dir2);
|
|
|
|
copy_v2_v2(wanted_dir2, wanted_dir);
|
|
|
|
normalize_v2(wanted_dir2);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* choose random direction to turn if wanted velocity */
|
|
|
|
/* is directly behind regardless of z-coordinate */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dot_v2v2(old_dir2, wanted_dir2) < -0.99f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
wanted_dir[0] = 2.0f*(0.5f - BLI_frand());
|
|
|
|
wanted_dir[1] = 2.0f*(0.5f - BLI_frand());
|
|
|
|
wanted_dir[2] = 2.0f*(0.5f - BLI_frand());
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(wanted_dir);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* constrain direction with maximum angular velocity */
|
2009-11-10 20:43:45 +00:00
|
|
|
angle = saacos(dot_v3v3(old_dir, wanted_dir));
|
2012-10-23 13:28:22 +00:00
|
|
|
angle = min_ff(angle, val.max_ave);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
cross_v3_v3v3(nor, old_dir, wanted_dir);
|
2012-04-29 15:47:02 +00:00
|
|
|
axis_angle_to_quat(q, nor, angle);
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(new_dir, old_dir);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_qt_v3(q, new_dir);
|
|
|
|
normalize_v3(new_dir);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* save direction in case resulting velocity too small */
|
2012-04-29 15:47:02 +00:00
|
|
|
axis_angle_to_quat(q, nor, angle*dtime);
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(pa->state.ave, old_dir);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_qt_v3(q, pa->state.ave);
|
|
|
|
normalize_v3(pa->state.ave);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* constrain speed with maximum acceleration */
|
2009-11-10 20:43:45 +00:00
|
|
|
old_speed = len_v3(pa->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bbd->wanted_speed < old_speed)
|
2009-07-20 23:52:53 +00:00
|
|
|
new_speed = MAX2(bbd->wanted_speed, old_speed - val.max_acc);
|
|
|
|
else
|
|
|
|
new_speed = MIN2(bbd->wanted_speed, old_speed + val.max_acc);
|
|
|
|
|
|
|
|
/* combine direction and speed */
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(new_vel, new_dir);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(new_vel, new_speed);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* maintain minimum flying velocity if not landing */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (level >= landing_level) {
|
2012-04-29 15:47:02 +00:00
|
|
|
float len2 = dot_v2v2(new_vel, new_vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
float root;
|
|
|
|
|
|
|
|
len2 = MAX2(len2, val.min_speed*val.min_speed);
|
|
|
|
root = sasqrt(new_speed*new_speed - len2);
|
|
|
|
|
|
|
|
new_vel[2] = new_vel[2] < 0.0f ? -root : root;
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v2(new_vel);
|
|
|
|
mul_v2_fl(new_vel, sasqrt(len2));
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* finally constrain speed to max speed */
|
2009-11-10 20:43:45 +00:00
|
|
|
new_speed = normalize_v3(new_vel);
|
|
|
|
mul_v3_fl(new_vel, MIN2(new_speed, val.max_speed));
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* get acceleration from difference of velocities */
|
2009-11-10 20:43:45 +00:00
|
|
|
sub_v3_v3v3(acc, new_vel, pa->prev_state.vel);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* break acceleration to components */
|
2009-11-10 20:43:45 +00:00
|
|
|
project_v3_v3v3(tan_acc, acc, pa->prev_state.ave);
|
|
|
|
sub_v3_v3v3(nor_acc, acc, tan_acc);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* account for effectors */
|
Unified effector functionality for particles, cloth and softbody
* Unified scene wide gravity (currently in scene buttons)
instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
as the effector point.
- "Surface" uses the closest point on an effector object's
surface as the effector point.
- "Every Point" uses every point in a mesh effector object
as an effector point.
- The falloff is calculated from this point, so for example
with "surface" shape and "use only negative z axis" it's
possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
just spherical.
* New effector parameter "flow", which makes the effector act as
surrounding air velocity, so the resulting force is
proportional to the velocity difference of the point and "air
velocity". For example a wind field with flow=1.0 results in
proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
(note. the z-axis is the surface normal in the case of
effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
particles, softbody & cloth, since their final effect depends on many external
factors, like for example the surface area of the effected faces.
Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
DAG_id_flush_update(..).
Known issues
* Curve guides don't yet have all ui buttons in place, but they
should work none the less.
* Hair dynamics don't yet respect force fields.
Other changes
* Particle emission defaults now to frames 1-200 with life of 50
frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
free pidlists after use :).
2009-09-30 22:10:14 +00:00
|
|
|
pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
|
|
|
|
pdDoEffectors(bbd->sim->psys->effectors, bbd->sim->colliders, bbd->part->effector_weights, &epoint, force, NULL);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
|
2009-11-10 20:43:45 +00:00
|
|
|
float length = normalize_v3(force);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
length = MAX2(0.0f, length - boids->land_stick_force);
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(force, length);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(acc, force);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* store smoothed acceleration for nice banking etc. */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(bpa->data.acc, acc, dtime);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(bpa->data.acc, 1.0f / (1.0f + dtime));
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* integrate new location & velocity */
|
|
|
|
|
|
|
|
/* by regarding the acceleration as a force at this stage we*/
|
|
|
|
/* can get better control allthough it's a bit unphysical */
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(acc, 1.0f/pa_mass);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(dvec, acc);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(dvec, dtime*dtime*0.5f);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(bvec, pa->prev_state.vel);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(bvec, dtime);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(dvec, bvec);
|
|
|
|
add_v3_v3(pa->state.co, dvec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(pa->state.vel, acc, dtime);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-04-21 12:51:47 +00:00
|
|
|
//if (bpa->data.mode != eBoidMode_InAir)
|
2010-09-16 20:00:30 +00:00
|
|
|
bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* change modes, constrain movement & keep track of down vector */
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (bpa->data.mode) {
|
2009-07-20 23:52:53 +00:00
|
|
|
case eBoidMode_InAir:
|
|
|
|
{
|
2010-11-02 13:12:30 +00:00
|
|
|
float grav[3];
|
|
|
|
|
2012-10-22 08:15:51 +00:00
|
|
|
grav[0] = 0.0f;
|
|
|
|
grav[1] = 0.0f;
|
|
|
|
grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* don't take forward acceleration into account (better banking) */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) {
|
2009-11-10 20:43:45 +00:00
|
|
|
project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
|
|
|
|
sub_v3_v3v3(dvec, bpa->data.acc, dvec);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(dvec, bpa->data.acc);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 23:06:15 +00:00
|
|
|
/* gather apparent gravity */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(bpa->gravity);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* stick boid on goal when close enough */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Climbing;
|
|
|
|
bpa->ground = bbd->goal_ob;
|
2009-07-20 23:52:53 +00:00
|
|
|
boid_find_ground(bbd, pa, ground_co, ground_nor);
|
|
|
|
boid_climb(boids, pa, ground_co, ground_nor);
|
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
|
2010-09-16 20:00:30 +00:00
|
|
|
/* land boid when below ground */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boids->options & BOID_ALLOW_LAND) {
|
2010-09-16 20:00:30 +00:00
|
|
|
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 */
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (bpa->ground) {
|
2010-09-16 20:00:30 +00:00
|
|
|
pa->state.co[2] = ground_co[2] + pa->size * boids->height;
|
|
|
|
pa->state.vel[2] = 0.0f;
|
|
|
|
}
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case eBoidMode_Falling:
|
|
|
|
{
|
2010-11-02 13:12:30 +00:00
|
|
|
float grav[3];
|
|
|
|
|
2012-10-22 08:15:51 +00:00
|
|
|
grav[0] = 0.0f;
|
|
|
|
grav[1] = 0.0f;
|
|
|
|
grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
|
2010-11-02 13:12:30 +00:00
|
|
|
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-09-04 23:06:15 +00:00
|
|
|
/* gather apparent gravity */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(bpa->gravity, grav, dtime);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(bpa->gravity);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boids->options & BOID_ALLOW_LAND) {
|
2009-07-20 23:52:53 +00:00
|
|
|
/* stick boid on goal when close enough */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Climbing;
|
|
|
|
bpa->ground = bbd->goal_ob;
|
2009-07-20 23:52:53 +00:00
|
|
|
boid_find_ground(bbd, pa, ground_co, ground_nor);
|
|
|
|
boid_climb(boids, pa, ground_co, ground_nor);
|
|
|
|
}
|
|
|
|
/* land boid when really near ground */
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (pa->state.co[2] <= ground_co[2] + 1.01f * pa->size * boids->height) {
|
2009-07-20 23:52:53 +00:00
|
|
|
pa->state.co[2] = ground_co[2] + pa->size * boids->height;
|
|
|
|
pa->state.vel[2] = 0.0f;
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_OnLand;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
/* if we're falling, can fly and want to go upwards lets fly */
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f)
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_InAir;
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_InAir;
|
2009-07-20 23:52:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case eBoidMode_Climbing:
|
|
|
|
{
|
|
|
|
boid_climb(boids, pa, ground_co, ground_nor);
|
|
|
|
//float nor[3];
|
2011-09-12 04:14:12 +00:00
|
|
|
//copy_v3_v3(nor, ground_nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
///* gather apparent gravity to r_ve */
|
2011-11-06 15:39:20 +00:00
|
|
|
//madd_v3_v3fl(pa->r_ve, ground_nor, -1.0);
|
2009-11-10 20:43:45 +00:00
|
|
|
//normalize_v3(pa->r_ve);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
///* raise boid it's size from surface */
|
2009-11-10 20:43:45 +00:00
|
|
|
//mul_v3_fl(nor, pa->size * boids->height);
|
|
|
|
//add_v3_v3v3(pa->state.co, ground_co, nor);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
///* remove normal component from velocity */
|
2009-11-10 20:43:45 +00:00
|
|
|
//project_v3_v3v3(v, pa->state.vel, ground_nor);
|
|
|
|
//sub_v3_v3v3(pa->state.vel, pa->state.vel, v);
|
2009-07-20 23:52:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case eBoidMode_OnLand:
|
|
|
|
{
|
|
|
|
/* stick boid on goal when close enough */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Climbing;
|
|
|
|
bpa->ground = bbd->goal_ob;
|
2009-07-20 23:52:53 +00:00
|
|
|
boid_find_ground(bbd, pa, ground_co, ground_nor);
|
|
|
|
boid_climb(boids, pa, ground_co, ground_nor);
|
|
|
|
}
|
|
|
|
/* ground is too far away so boid falls */
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (pa->state.co[2]-ground_co[2] > 1.1f * pa->size * boids->height)
|
2009-09-04 23:06:15 +00:00
|
|
|
bpa->data.mode = eBoidMode_Falling;
|
2009-07-20 23:52:53 +00:00
|
|
|
else {
|
|
|
|
/* constrain to surface */
|
|
|
|
pa->state.co[2] = ground_co[2] + pa->size * boids->height;
|
|
|
|
pa->state.vel[2] = 0.0f;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boids->banking > 0.0f) {
|
2009-07-20 23:52:53 +00:00
|
|
|
float grav[3];
|
|
|
|
/* Don't take gravity's strength in to account, */
|
|
|
|
/* otherwise amount of banking is hard to control. */
|
2010-02-26 09:02:52 +00:00
|
|
|
negate_v3_v3(grav, ground_nor);
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
|
|
|
|
sub_v3_v3v3(dvec, bpa->data.acc, dvec);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-09-04 23:06:15 +00:00
|
|
|
/* gather apparent gravity */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(bpa->gravity);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-09-04 23:06:15 +00:00
|
|
|
/* gather negative surface normal */
|
2011-11-06 15:39:20 +00:00
|
|
|
madd_v3_v3fl(bpa->gravity, ground_nor, -1.0f);
|
2009-11-10 20:43:45 +00:00
|
|
|
normalize_v3(bpa->gravity);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save direction to state.ave unless the boid is falling */
|
|
|
|
/* (boids can't effect their direction when falling) */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1f*pa->size) {
|
2010-09-16 20:06:10 +00:00
|
|
|
copy_v3_v3(pa->state.ave, pa->state.vel);
|
|
|
|
pa->state.ave[2] *= bbd->part->boids->pitch;
|
|
|
|
normalize_v3(pa->state.ave);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* apply damping */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing))
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_v3_fl(pa->state.vel, 1.0f - 0.2f*bbd->part->dampfac);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* calculate rotation matrix based on forward & down vectors */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bpa->data.mode == eBoidMode_InAir) {
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(mat[0], pa->state.ave);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
project_v3_v3v3(dvec, bpa->gravity, pa->state.ave);
|
|
|
|
sub_v3_v3v3(mat[2], bpa->gravity, dvec);
|
|
|
|
normalize_v3(mat[2]);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-11-10 20:43:45 +00:00
|
|
|
project_v3_v3v3(dvec, pa->state.ave, bpa->gravity);
|
|
|
|
sub_v3_v3v3(mat[0], pa->state.ave, dvec);
|
|
|
|
normalize_v3(mat[0]);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
2011-11-06 15:39:20 +00:00
|
|
|
copy_v3_v3(mat[2], bpa->gravity);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
2010-02-26 09:02:52 +00:00
|
|
|
negate_v3(mat[2]);
|
2009-11-10 20:43:45 +00:00
|
|
|
cross_v3_v3v3(mat[1], mat[2], mat[0]);
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
/* apply rotation */
|
2012-04-29 15:47:02 +00:00
|
|
|
mat3_to_quat_is_ok(q, mat);
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_qt_qt(pa->state.rot, q);
|
2009-07-20 23:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BoidRule *boid_new_rule(int type)
|
|
|
|
{
|
|
|
|
BoidRule *rule = NULL;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (type <= 0)
|
2009-07-20 23:52:53 +00:00
|
|
|
return NULL;
|
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (type) {
|
2009-07-20 23:52:53 +00:00
|
|
|
case eBoidRuleType_Goal:
|
|
|
|
case eBoidRuleType_Avoid:
|
|
|
|
rule = MEM_callocN(sizeof(BoidRuleGoalAvoid), "BoidRuleGoalAvoid");
|
|
|
|
break;
|
|
|
|
case eBoidRuleType_AvoidCollision:
|
|
|
|
rule = MEM_callocN(sizeof(BoidRuleAvoidCollision), "BoidRuleAvoidCollision");
|
|
|
|
((BoidRuleAvoidCollision*)rule)->look_ahead = 2.0f;
|
|
|
|
break;
|
|
|
|
case eBoidRuleType_FollowLeader:
|
|
|
|
rule = MEM_callocN(sizeof(BoidRuleFollowLeader), "BoidRuleFollowLeader");
|
|
|
|
((BoidRuleFollowLeader*)rule)->distance = 1.0f;
|
|
|
|
break;
|
|
|
|
case eBoidRuleType_AverageSpeed:
|
|
|
|
rule = MEM_callocN(sizeof(BoidRuleAverageSpeed), "BoidRuleAverageSpeed");
|
|
|
|
((BoidRuleAverageSpeed*)rule)->speed = 0.5f;
|
|
|
|
break;
|
|
|
|
case eBoidRuleType_Fight:
|
|
|
|
rule = MEM_callocN(sizeof(BoidRuleFight), "BoidRuleFight");
|
|
|
|
((BoidRuleFight*)rule)->distance = 100.0f;
|
|
|
|
((BoidRuleFight*)rule)->flee_distance = 100.0f;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rule = MEM_callocN(sizeof(BoidRule), "BoidRule");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rule->type = type;
|
|
|
|
rule->flag |= BOIDRULE_IN_AIR|BOIDRULE_ON_LAND;
|
2011-02-13 03:21:27 +00:00
|
|
|
BLI_strncpy(rule->name, boidrule_type_items[type-1].name, sizeof(rule->name));
|
2009-07-20 23:52:53 +00:00
|
|
|
|
|
|
|
return rule;
|
|
|
|
}
|
|
|
|
void boid_default_settings(BoidSettings *boids)
|
|
|
|
{
|
|
|
|
boids->air_max_speed = 10.0f;
|
|
|
|
boids->air_max_acc = 0.5f;
|
|
|
|
boids->air_max_ave = 0.5f;
|
|
|
|
boids->air_personal_space = 1.0f;
|
|
|
|
|
|
|
|
boids->land_max_speed = 5.0f;
|
|
|
|
boids->land_max_acc = 0.5f;
|
|
|
|
boids->land_max_ave = 0.5f;
|
|
|
|
boids->land_personal_space = 1.0f;
|
|
|
|
|
|
|
|
boids->options = BOID_ALLOW_FLIGHT;
|
|
|
|
|
|
|
|
boids->landing_smoothness = 3.0f;
|
|
|
|
boids->banking = 1.0f;
|
2010-09-16 20:06:10 +00:00
|
|
|
boids->pitch = 1.0f;
|
2009-07-20 23:52:53 +00:00
|
|
|
boids->height = 1.0f;
|
|
|
|
|
|
|
|
boids->health = 1.0f;
|
|
|
|
boids->accuracy = 1.0f;
|
|
|
|
boids->aggression = 2.0f;
|
|
|
|
boids->range = 1.0f;
|
|
|
|
boids->strength = 0.1f;
|
|
|
|
}
|
|
|
|
|
|
|
|
BoidState *boid_new_state(BoidSettings *boids)
|
|
|
|
{
|
|
|
|
BoidState *state = MEM_callocN(sizeof(BoidState), "BoidState");
|
|
|
|
|
|
|
|
state->id = boids->last_state_id++;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (state->id)
|
2012-01-11 12:33:51 +00:00
|
|
|
BLI_snprintf(state->name, sizeof(state->name), "State %i", state->id);
|
2009-07-20 23:52:53 +00:00
|
|
|
else
|
|
|
|
strcpy(state->name, "State");
|
|
|
|
|
|
|
|
state->rule_fuzziness = 0.5;
|
|
|
|
state->volume = 1.0f;
|
|
|
|
state->channels |= ~0;
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2011-12-17 00:52:36 +00:00
|
|
|
BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state)
|
|
|
|
{
|
2009-07-20 23:52:53 +00:00
|
|
|
BoidState *staten = MEM_dupallocN(state);
|
|
|
|
|
|
|
|
BLI_duplicatelist(&staten->rules, &state->rules);
|
|
|
|
BLI_duplicatelist(&staten->conditions, &state->conditions);
|
|
|
|
BLI_duplicatelist(&staten->actions, &state->actions);
|
|
|
|
|
|
|
|
staten->id = boids->last_state_id++;
|
|
|
|
|
|
|
|
return staten;
|
|
|
|
}
|
|
|
|
void boid_free_settings(BoidSettings *boids)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boids) {
|
2009-07-20 23:52:53 +00:00
|
|
|
BoidState *state = boids->states.first;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (; state; state=state->next) {
|
2009-07-20 23:52:53 +00:00
|
|
|
BLI_freelistN(&state->rules);
|
|
|
|
BLI_freelistN(&state->conditions);
|
|
|
|
BLI_freelistN(&state->actions);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_freelistN(&boids->states);
|
|
|
|
|
|
|
|
MEM_freeN(boids);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BoidSettings *boid_copy_settings(BoidSettings *boids)
|
|
|
|
{
|
|
|
|
BoidSettings *nboids = NULL;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (boids) {
|
2009-07-20 23:52:53 +00:00
|
|
|
BoidState *state;
|
|
|
|
BoidState *nstate;
|
|
|
|
|
|
|
|
nboids = MEM_dupallocN(boids);
|
|
|
|
|
|
|
|
BLI_duplicatelist(&nboids->states, &boids->states);
|
|
|
|
|
|
|
|
state = boids->states.first;
|
|
|
|
nstate = nboids->states.first;
|
2012-03-24 06:18:31 +00:00
|
|
|
for (; state; state=state->next, nstate=nstate->next) {
|
2009-07-20 23:52:53 +00:00
|
|
|
BLI_duplicatelist(&nstate->rules, &state->rules);
|
|
|
|
BLI_duplicatelist(&nstate->conditions, &state->conditions);
|
|
|
|
BLI_duplicatelist(&nstate->actions, &state->actions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nboids;
|
|
|
|
}
|
|
|
|
BoidState *boid_get_current_state(BoidSettings *boids)
|
|
|
|
{
|
|
|
|
BoidState *state = boids->states.first;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
for (; state; state=state->next) {
|
|
|
|
if (state->flag & BOIDSTATE_CURRENT)
|
2009-07-20 23:52:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
2009-07-25 22:20:26 +00:00
|
|
|
}
|
|
|
|
|