diff options
Diffstat (limited to 'source/blender')
37 files changed, 2037 insertions, 1540 deletions
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index e0df75f41b9..5ca8ad892ac 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -141,6 +141,15 @@ void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], ///////////////////////////////////////////////// Object **get_collisionobjects(struct Scene *scene, Object *self, int *numcollobj); +typedef struct ColliderCache { + struct ColliderCache *next, *prev; + struct Object *ob; + struct CollisionModifierData *collmd; +} ColliderCache; + +struct ListBase *get_collider_cache(struct Scene *scene, Object *self); +void free_collider_cache(struct ListBase **colliders); + ///////////////////////////////////////////////// diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index e21e83bf5cf..83ec7c13946 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -32,6 +32,7 @@ #define BKE_EFFECT_H #include "DNA_object_types.h" +#include "DNA_modifier_types.h" struct Object; struct Scene; @@ -40,20 +41,72 @@ struct ListBase; struct Particle; struct Group; struct RNG; +struct ParticleSimulationData; +struct ParticleData; +struct ParticleKey; -struct PartDeflect *object_add_collision_fields(void); +struct EffectorWeights *BKE_add_effector_weights(struct Group *group); +struct PartDeflect *object_add_collision_fields(int type); -typedef struct pEffectorCache { - struct pEffectorCache *next, *prev; - Object *ob; - - /* precalculated variables */ - float oldloc[3], oldspeed[3]; - float scale, time_scale; - float guide_dist; +/* Input to effector code */ +typedef struct EffectedPoint { + float *loc; + float *vel; + float *ave; /* angular velocity for particles with dynamic rotation */ + float *rot; /* rotation quaternion for particles with dynamic rotation */ + float vel_to_frame; + float vel_to_sec; + + /* only for particles */ + float size, charge; + + unsigned int flag; + int index; + + struct ParticleSystem *psys; /* particle system the point belongs to */ +} EffectedPoint; + +typedef struct GuideEffectorData { + float vec_to_point[3]; + float strength; +} GuideEffectorData; + +typedef struct EffectorData { + /* Effector point */ + float loc[3]; + float nor[3]; + float vel[3]; + + float vec_to_point[3]; + float distance, falloff; + + /* only for effector particles */ + float size, charge; + + /* only for vortex effector with surface falloff */ + float nor2[3], vec_to_point2[3]; + + int *index; /* point index */ +} EffectorData; + +/* used for calculating the effector force */ +typedef struct EffectorCache { + struct EffectorCache *next, *prev; + + struct Scene *scene; + struct Object *ob; + struct ParticleSystem *psys; + struct SurfaceModifierData *surmd; - Object obcopy; /* for restoring transformation data */ -} pEffectorCache; + struct PartDeflect *pd; + + /* precalculated for guides */ + struct GuideEffectorData *guide_data; + float guide_loc[4], guide_dir[3], guide_radius; + + float frame; + int flag; +} EffectorCache; void free_effect(struct Effect *eff); void free_effects(struct ListBase *lb); @@ -61,23 +114,33 @@ struct Effect *copy_effect(struct Effect *eff); void copy_effects(struct ListBase *lbn, struct ListBase *lb); void deselectall_eff(struct Object *ob); -/* particle deflector */ -#define PE_WIND_AS_SPEED 0x00000001 - struct PartEff *give_parteff(struct Object *ob); -struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *obsrc, struct Group *group); -void pdEndEffectors(struct ListBase *lb); -void pdDoEffectors(struct Scene *scene, struct ListBase *lb, float *opco, float *force, - float *speed, float cur_time, float loc_time, unsigned int flags); + + +void free_partdeflect(struct PartDeflect *pd); +struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights); +void pdEndEffectors(struct ListBase **effectors); +void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse); + +void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point); +void pd_point_from_loc(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point); +void pd_point_from_soft(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point); + +/* needed for boids */ +float effector_falloff(struct EffectorCache *eff, struct EffectorData *efd, struct EffectedPoint *point, struct EffectorWeights *weights); +int closest_point_on_surface(struct SurfaceModifierData *surmd, float *co, float *surface_co, float *surface_nor, float *surface_vel); +int get_effector_data(struct EffectorCache *eff, struct EffectorData *efd, struct EffectedPoint *point, int real_velocity); /* required for particle_system.c */ -void do_physical_effector(struct Scene *scene, struct Object *ob, float *opco, short type, float force_val, float distance, - float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, - float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, - float charge, float pa_size); -float effector_falloff(struct PartDeflect *pd, float *eff_velocity, float *vec_to_part); +//void do_physical_effector(struct EffectorData *eff, struct EffectorPoint *point, float *total_force); +//float effector_falloff(struct EffectorData *eff, struct EffectorPoint *point, struct EffectorWeights *weights); +/* EffectedPoint->flag */ +#define PE_WIND_AS_SPEED 1 +#define PE_DYNAMIC_ROTATION 2 +/* EffectorData->flag */ +#define PE_VELOCITY_TO_IMPULSE 1 #endif diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 5850ddaca08..e0259ff10dd 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -76,39 +76,18 @@ typedef struct ParticleSimulationData { struct Object *ob; struct ParticleSystem *psys; struct ParticleSystemModifierData *psmd; - float timestep; + struct ListBase *colliders; } ParticleSimulationData; -typedef struct ParticleEffectorCache { - struct ParticleEffectorCache *next, *prev; - struct Object *ob; - - /* precalculated variables for guides */ - float firstloc[4], firstdir[3]; - float *distances; - float *locations; - /* precalculated variables for deflection */ - float ob_minmax[6]; - float *face_minmax; - float *vert_cos; - /* precalculated variables for boids */ - struct KDTree *tree; - - short type, psys_nbr; - - struct Object obcopy; /* for restoring transformation data */ - struct RNG *rng; /* random noise generator for e.g. wind */ -} ParticleEffectorCache; - -typedef struct ParticleReactEvent { - struct ParticleReactEvent *next, *prev; - int event, pa_num; - Object *ob; - struct ParticleSystem *psys; - struct ParticleKey state; - - float time, size; -}ParticleReactEvent; +//typedef struct ParticleReactEvent { +// struct ParticleReactEvent *next, *prev; +// int event, pa_num; +// Object *ob; +// struct ParticleSystem *psys; +// struct ParticleKey state; +// +// float time, size; +//}ParticleReactEvent; typedef struct ParticleTexture{ float ivel; /* used in reset */ @@ -185,8 +164,8 @@ typedef struct ParticleBillboardData /* container for moving data between deflet_particle and particle_intersect_face */ typedef struct ParticleCollision { - struct Object *ob, *ob_t; // collided and current objects - struct CollisionModifierData *md; // collision modifier for ob_t; + struct Object *ob, *hit_ob; // collided and current objects + struct CollisionModifierData *md, *hit_md; // collision modifiers for current and hit object; float nor[3]; // normal at collision point float vel[3]; // velocity of collision point float co1[3], co2[3]; // ray start and end points @@ -244,7 +223,6 @@ void object_add_particle_system(struct Scene *scene, struct Object *ob); void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); -void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); void make_local_particlesettings(struct ParticleSettings *part); void psys_reset(struct ParticleSystem *psys, int mode); @@ -254,7 +232,8 @@ void psys_find_parents(struct ParticleSimulationData *sim); void psys_cache_paths(struct ParticleSimulationData *sim, float cfra); void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra); void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, int editupdate); -int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb); +int do_guides(struct ListBase *effectors, ParticleKey *state, int pa_num, float time); +void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors); float psys_get_timestep(struct ParticleSimulationData *sim); float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime); float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time); @@ -273,9 +252,7 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] /* particle_system.c */ struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt); void psys_count_keyed_targets(struct ParticleSimulationData *sim); -//void psys_get_reactor_target(struct ParticleSimulationData *sim, struct Object **target_ob, struct ParticleSystem **target_psys); - -int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc); +void psys_update_particle_tree(struct ParticleSystem *psys, float cfra); void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys); void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra); @@ -316,29 +293,17 @@ void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_ /* particle_system.c */ void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, int p); - -int effector_find_co(struct Scene *scene, float *pco, struct SurfaceModifierData *sur, struct Object *ob, struct PartDeflect *pd, float *co, float *nor, float *vel, int *index); -void do_effectors(struct ParticleSimulationData *sim, int pa_no, struct ParticleData *pa, struct ParticleKey *state, float *texco, float *force_field, float *vel,float framestep, float cfra); -void psys_end_effectors(struct ParticleSystem *psys); - void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys); int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node); void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); - /* psys_reset */ #define PSYS_RESET_ALL 1 #define PSYS_RESET_DEPSGRAPH 2 #define PSYS_RESET_CHILDREN 3 #define PSYS_RESET_CACHE_MISS 4 -/* ParticleEffectorCache->type */ -#define PSYS_EC_EFFECTOR 1 -#define PSYS_EC_DEFLECT 2 -#define PSYS_EC_PARTICLE 4 -#define PSYS_EC_REACTOR 8 - /* index_dmcache */ #define DMCACHE_NOTFOUND -1 #define DMCACHE_ISCHILD -2 diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 7c3f3a7876f..76824d3a34a 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -47,6 +47,7 @@ #include "BLI_blenlib.h" #include "BLI_kdtree.h" #include "BLI_kdopbvh.h" +#include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_boids.h" #include "BKE_particle.h" @@ -72,112 +73,91 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, { BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule; BoidSettings *boids = bbd->part->boids; - ParticleEffectorCache *ec; Object *priority_ob = NULL; BoidParticle *bpa = pa->boid; + EffectedPoint epoint; + ListBase *effectors = bbd->sim->psys->effectors; + EffectorCache *cur, *eff = NULL; + EffectorData efd, cur_efd; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0); float priority = 0.0f, len = 0.0f; int ret = 0; - /* first find out goal/predator with highest priority */ - /* if rule->ob specified use it */ - if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) { - PartDeflect *pd = gabr->ob->pd; - float vec_to_part[3]; - - if(pd && pd->forcefield == PFIELD_BOID) { - effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, gabr->ob, pd, loc, vec, NULL, NULL); - - VecSubf(vec_to_part, pa->prev_state.co, loc); + pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint); - priority = mul * pd->f_strength * effector_falloff(pd, vec, vec_to_part); - } - else - priority = 1.0; - - priority = 1.0; - priority_ob = gabr->ob; - } - else for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { - if(ec->type & PSYS_EC_EFFECTOR) { - Object *eob = ec->ob; - PartDeflect *pd = eob->pd; - - /* skip current object */ - if(rule->type == eBoidRuleType_Goal && eob == bpa->ground) - continue; - - if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f) { - float vec_to_part[3], temp; - - effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, vec, NULL, NULL); - - VecSubf(vec_to_part, pa->prev_state.co, loc); - - temp = mul * pd->f_strength * effector_falloff(pd, vec, vec_to_part); - - if(temp == 0.0f) - ; /* do nothing */ - else if(temp > priority) { - priority = temp; - priority_ob = eob; - len = VecLength(vec_to_part); - } - /* choose closest object with same priority */ - else if(temp == priority) { - float len2 = VecLength(vec_to_part); - - if(len2 < len) { - priority_ob = eob; - len = len2; - } + /* first find out goal/predator with highest priority */ + if(effectors) for(cur = effectors->first; cur; cur=cur->next) { + Object *eob = cur->ob; + PartDeflect *pd = cur->pd; + + if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) { + if(gabr->ob == eob) { + /* TODO: objects without any effector and effectors with multiple points */ + if(get_effector_data(cur, &efd, &epoint, 0)) { + if(cur->pd && cur->pd->forcefield == PFIELD_BOID) + priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights); + else + priority = 1.0; + + eff = cur; } + break; + } + } + else if(rule->type == eBoidRuleType_Goal && eob == bpa->ground) + ; /* skip current object */ + else if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(eff, &efd, &epoint, 0)) { + float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights); + + if(temp == 0.0f) + ; /* do nothing */ + else if(temp > priority) { + priority = temp; + eff = cur; + efd = cur_efd; + len = efd.distance; + } + /* choose closest object with same priority */ + else if(temp == priority && efd.distance < len) { + eff = cur; + efd = cur_efd; + len = efd.distance; } } } /* then use that effector */ if(priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */ - Object *eob = priority_ob; + Object *eob = eff->ob; PartDeflect *pd = eob->pd; - float vec_to_part[3]; - float surface = 0.0f; - float nor[3]; + float surface = pd->shape == PFIELD_SHAPE_SURFACE ? 1.0f : 0.0f; if(gabr->options & BRULE_GOAL_AVOID_PREDICT) { /* estimate future location of target */ - surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, vec, NULL); - - VecSubf(vec_to_part, pa->prev_state.co, loc); - len = Normalize(vec_to_part); + get_effector_data(eff, &efd, &epoint, 1); - VecMulf(vec, len / (val->max_speed * bbd->timestep)); - VecAddf(loc, loc, vec); - VecSubf(vec_to_part, pa->prev_state.co, loc); - } - else { - surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, NULL, NULL); - - VecSubf(vec_to_part, pa->prev_state.co, loc); - len = VecLength(vec_to_part); + VecMulf(efd.vel, efd.distance / (val->max_speed * bbd->timestep)); + VecAddf(efd.loc, efd.loc, efd.vel); + VecSubf(efd.vec_to_point, pa->prev_state.co, efd.loc); + efd.distance = VecLength(efd.vec_to_point); } if(rule->type == eBoidRuleType_Goal && boids->options & BOID_ALLOW_CLIMB && surface!=0.0f) { if(!bbd->goal_ob || bbd->goal_priority < priority) { bbd->goal_ob = eob; - VECCOPY(bbd->goal_co, loc); - VECCOPY(bbd->goal_nor, nor); + VECCOPY(bbd->goal_co, efd.loc); + VECCOPY(bbd->goal_nor, efd.nor); } } else if(rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing && priority > 2.0f * gabr->fear_factor) { /* detach from surface and try to fly away from danger */ - VECCOPY(vec_to_part, bpa->gravity); - VecMulf(vec_to_part, -1.0f); + VECCOPY(efd.vec_to_point, bpa->gravity); + VecMulf(efd.vec_to_point, -1.0f); } - VECCOPY(bbd->wanted_co, vec_to_part); + VECCOPY(bbd->wanted_co, efd.vec_to_point); VecMulf(bbd->wanted_co, mul); bbd->wanted_speed = val->max_speed * priority; @@ -188,8 +168,8 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, surface *= pa->size * boids->height; - if(len2 > 0.0f && len - surface < len2) { - len2 = (len - surface)/len2; + if(len2 > 0.0f && efd.distance - surface < len2) { + len2 = (efd.distance - surface)/len2; bbd->wanted_speed *= pow(len2, boids->landing_smoothness); } } @@ -204,9 +184,9 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * { BoidRuleAvoidCollision *acbr = (BoidRuleAvoidCollision*) rule; KDTreeNearest *ptn = NULL; - ParticleEffectorCache *ec; ParticleTarget *pt; BoidParticle *bpa = pa->boid; + ColliderCache *coll; 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; @@ -214,7 +194,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * int ret = 0; //check deflector objects first - if(acbr->options & BRULE_ACOLL_WITH_DEFLECTORS) { + if(acbr->options & BRULE_ACOLL_WITH_DEFLECTORS && bbd->sim->colliders) { ParticleCollision col; BVHTreeRayHit hit; float radius = val->personal_space * pa->size, ray_dir[3]; @@ -228,20 +208,16 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * hit.dist = col.ray_len = VecLength(ray_dir); /* find out closest deflector object */ - for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { - if(ec->type & PSYS_EC_DEFLECT) { - Object *eob = ec->ob; - - /* don't check with current ground object */ - if(eob == bpa->ground) - continue; + for(coll = bbd->sim->colliders->first; coll; coll=coll->next) { + /* don't check with current ground object */ + if(coll->ob == bpa->ground) + continue; - col.md = ( CollisionModifierData * ) ( modifiers_findByType ( eob, eModifierType_Collision ) ); - col.ob_t = eob; + col.ob = coll->ob; + col.md = coll->collmd; - if(col.md && col.md->bvhtree) - BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); - } + if(col.md && col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); } /* then avoid that object */ if(hit.index>=0) { @@ -756,25 +732,28 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro if(bpa->data.mode == eBoidMode_Climbing) { SurfaceModifierData *surmd = NULL; float x[3], v[3]; - + surmd = (SurfaceModifierData *)modifiers_findByType ( bpa->ground, eModifierType_Surface ); /* take surface velocity into account */ - effector_find_co(bbd->sim->scene, pa->state.co, surmd, NULL, NULL, x, NULL, v, NULL); + closest_point_on_surface(surmd, pa->state.co, x, NULL, v); VecAddf(x, x, v); /* get actual position on surface */ - effector_find_co(bbd->sim->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL); + closest_point_on_surface(surmd, x, ground_co, ground_nor, NULL); return bpa->ground; } else { float zvec[3] = {0.0f, 0.0f, 2000.0f}; ParticleCollision col; + ColliderCache *coll; BVHTreeRayHit hit; - ParticleEffectorCache *ec; float radius = 0.0f, t, ray_dir[3]; + if(!bbd->sim->colliders) + return NULL; + VECCOPY(col.co1, pa->state.co); VECCOPY(col.co2, pa->state.co); VecAddf(col.co1, col.co1, zvec); @@ -785,16 +764,12 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro hit.dist = col.ray_len = VecLength(ray_dir); /* find out upmost deflector object */ - for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { - if(ec->type & PSYS_EC_DEFLECT) { - Object *eob = ec->ob; + for(coll = bbd->sim->colliders->first; coll; coll = coll->next){ + col.ob = coll->ob; + col.md = coll->collmd; - col.md = ( CollisionModifierData * ) ( modifiers_findByType ( eob, eModifierType_Collision ) ); - col.ob_t = eob; - - if(col.md && col.md->bvhtree) - BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); - } + if(col.md && col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); } /* then use that object */ if(hit.index>=0) { @@ -802,7 +777,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro VecLerpf(ground_co, col.co1, col.co2, t); VECCOPY(ground_nor, col.nor); Normalize(ground_nor); - return col.ob; + return col.hit_ob; } else { /* default to z=0 */ @@ -1068,6 +1043,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) BoidSettings *boids = bbd->part->boids; BoidParticle *bpa = pa->boid; BoidValues val; + EffectedPoint epoint; 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; @@ -1208,7 +1184,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) } /* account for effectors */ - do_effectors(bbd->sim, p, pa, &pa->state, pa->state.co, force, tvel, bbd->dfra, bbd->cfra); + 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); if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { float length = Normalize(force); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 5cfbd5c18dc..74f88a77e63 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -153,6 +153,9 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->defgoal = 0.0f; clmd->sim_parms->goalspring = 1.0f; clmd->sim_parms->goalfrict = 0.0f; + + if(!clmd->sim_parms->effector_weights) + clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL); } static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) @@ -402,6 +405,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul VECCOPY(verts->xconst, mvert[i].co); Mat4MulVecfl(ob->obmat, verts->xconst); } + + effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights); tstart(); @@ -411,6 +416,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul tend(); + pdEndEffectors(&effectors); + // printf ( "%f\n", ( float ) tval() ); return ret; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 20fc1708454..8c664bc1a57 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1392,6 +1392,97 @@ Object **get_collisionobjects(Scene *scene, Object *self, int *numcollobj) return objs; } +ListBase *get_collider_cache(Scene *scene, Object *self) +{ + Base *base=NULL; + ListBase *objs = NULL; + Object *coll_ob = NULL; + CollisionModifierData *collmd = NULL; + ColliderCache *col; + + // check all collision objects + for ( base = scene->base.first; base; base = base->next ) + { + /*Only proceed for mesh object in same layer */ + if(base->object->type!=OB_MESH) + continue; + + if(self && (base->lay & self->lay)==0) + continue; + + + coll_ob = base->object; + + if(coll_ob == self) + continue; + + if(coll_ob->pd && coll_ob->pd->deflect) + { + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + } + else + collmd = NULL; + + if ( collmd ) + { + if(objs == NULL) + objs = MEM_callocN(sizeof(ListBase), "ColliderCache array"); + + col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); + col->ob = coll_ob; + col->collmd = collmd; + /* make sure collider is properly set up */ + collision_move_object(collmd, 1.0, 0.0); + BLI_addtail(objs, col); + } + else if ( coll_ob->dup_group ) + { + GroupObject *go; + Group *group = coll_ob->dup_group; + + for ( go= group->gobject.first; go; go= go->next ) + { + coll_ob = go->ob; + collmd = NULL; + + if(coll_ob == self) + continue; + + if(coll_ob->pd && coll_ob->pd->deflect) + { + collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision ); + } + else + collmd = NULL; + + if ( !collmd ) + continue; + + if( !collmd->bvhtree) + continue; + + if(objs == NULL) + objs = MEM_callocN(sizeof(ListBase), "ColliderCache array"); + + col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); + col->ob = coll_ob; + col->collmd = collmd; + /* make sure collider is properly set up */ + collision_move_object(collmd, 1.0, 0.0); + BLI_addtail(objs, col); + } + } + } + return objs; +} +void free_collider_cache(ListBase **colliders) +{ + if(*colliders) { + BLI_freelistN(*colliders); + MEM_freeN(*colliders); + *colliders = NULL; + } +} static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) { int i; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 608cfe03b72..a8cec6070a0 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -521,8 +521,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O /* softbody collision */ if((ob->type==OB_MESH) || (ob->type==OB_CURVE) || (ob->type==OB_LATTICE)) - if(modifiers_isSoftbodyEnabled(ob) || modifiers_isClothEnabled(ob)) - dag_add_collision_field_relation(dag, scene, ob, node); + if(modifiers_isSoftbodyEnabled(ob) || modifiers_isClothEnabled(ob) || ob->particlesystem.first) + dag_add_collision_field_relation(dag, scene, ob, node); /* TODO: use effectorweight->group */ if (ob->type==OB_MBALL) { Object *mom= find_basis_mball(scene, ob); @@ -554,14 +554,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O psys= ob->particlesystem.first; if(psys) { - ParticleEffectorCache *nec; GroupObject *go; for(; psys; psys=psys->next) { BoidRule *rule = NULL; BoidState *state = NULL; - ParticleSimulationData sim = {scene, ob, psys, NULL}; ParticleSettings *part= psys->part; + ListBase *effectors = NULL; + EffectorCache *eff; dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); @@ -593,33 +593,17 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } - psys_update_effectors(&sim, 0.0, 0); + effectors = pdInitEffectors(scene, ob, psys, part->effector_weights); - for(nec= psys->effectors.first; nec; nec= nec->next) { - Object *ob1= nec->ob; - - if(nec->type & PSYS_EC_EFFECTOR) { - node2 = dag_get_node(dag, ob1); - if(ob1->pd->forcefield==PFIELD_GUIDE) - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field"); - else - dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Particle Field"); - } - else if(nec->type & PSYS_EC_DEFLECT) { - node2 = dag_get_node(dag, ob1); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Collision"); - } - else if(nec->type & PSYS_EC_PARTICLE) { - node2 = dag_get_node(dag, ob1); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Field"); - } - - if(nec->type & PSYS_EC_REACTOR) { - node2 = dag_get_node(dag, ob1); - dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Reactor"); + if(effectors) for(eff = effectors->first; eff; eff=eff->next) { + if(eff->psys) { + node2 = dag_get_node(dag, eff->ob); + dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field"); } } + pdEndEffectors(&effectors); + if(part->boids) { for(state = part->boids->states.first; state; state=state->next) { for(rule = state->rules.first; rule; rule=rule->next) { @@ -2217,7 +2201,7 @@ void DAG_id_flush_update(ID *id, short flag) /* set flags & pointcache for object */ if(GS(id->name) == ID_OB) { ob= (Object*)id; - ob->recalc |= flag; + ob->recalc |= (flag & OB_RECALC); BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH); if(flag & OB_RECALC_DATA) { @@ -2255,6 +2239,20 @@ void DAG_id_flush_update(ID *id, short flag) } } + /* set flags based on particle settings */ + if(idtype == ID_PA) { + ParticleSystem *psys; + for(obt=bmain->object.first; obt; obt= obt->id.next) { + for(psys=obt->particlesystem.first; psys; psys=psys->next) { + if(&psys->part->id == id) { + BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); + obt->recalc |= (flag & OB_RECALC); + psys->recalc |= (flag & PSYS_RECALC); + } + } + } + } + /* update editors */ dag_editors_update(bmain, id); } diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index acf906e3163..7cc65de827a 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -48,12 +48,15 @@ #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" +#include "DNA_particle_types.h" #include "DNA_texture_types.h" #include "DNA_scene_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_jitter.h" +#include "BLI_listbase.h" +#include "BLI_noise.h" #include "BLI_rand.h" #include "PIL_time.h" @@ -68,6 +71,7 @@ #include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_DerivedMesh.h" +#include "BKE_cdderivedmesh.h" #include "BKE_effect.h" #include "BKE_global.h" #include "BKE_group.h" @@ -79,11 +83,13 @@ #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_object.h" +#include "BKE_particle.h" #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_utildefines.h" #include "RE_render_ext.h" +#include "RE_shader_ext.h" /* fluid sim particle import */ #ifndef DISABLE_ELBEEM @@ -95,17 +101,46 @@ //XXX #include "BIF_screen.h" -PartDeflect *object_add_collision_fields(void) +EffectorWeights *BKE_add_effector_weights(Group *group) +{ + EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights"); + int i; + + for(i=0; i<NUM_PFIELD_TYPES; i++) + weights->weight[i] = 1.0f; + + weights->global_gravity = 1.0f; + + weights->group = group; + + return weights; +} +PartDeflect *object_add_collision_fields(int type) { PartDeflect *pd; pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect"); + pd->forcefield = type; pd->pdef_sbdamp = 0.1f; pd->pdef_sbift = 0.2f; pd->pdef_sboft = 0.02f; pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128; pd->f_strength = 1.0f; + pd->f_damp = 1.0f; + pd->f_size = 1.0f; + + /* set sensible defaults based on type */ + switch(type) { + case PFIELD_VORTEX: + pd->shape = PFIELD_SHAPE_PLANE; + break; + case PFIELD_WIND: + pd->shape = PFIELD_SHAPE_PLANE; + pd->f_flow = 1.0f; /* realistic wind behavior */ + break; + } + pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION; return pd; } @@ -156,93 +191,216 @@ void free_effects(ListBase *lb) } /* -------------------------- Effectors ------------------ */ +void free_partdeflect(PartDeflect *pd) +{ + if(!pd) + return; + + if(pd->tex) + pd->tex->id.us--; -static void add_to_effectorcache(ListBase *lb, Scene *scene, Object *ob, Object *obsrc) + if(pd->rng) + rng_free(pd->rng); + + MEM_freeN(pd); +} + +static void precalculate_effector(EffectorCache *eff) { - pEffectorCache *ec; - PartDeflect *pd= ob->pd; - - if(pd->forcefield == PFIELD_GUIDE) { - if(ob->type==OB_CURVE && obsrc->type==OB_MESH) { /* guides only do mesh particles */ - Curve *cu= ob->data; - if(cu->flag & CU_PATH) { - if(cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(scene, ob, 0); - if(cu->path && cu->path->data) { - ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); - ec->ob= ob; - BLI_addtail(lb, ec); - } + unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra); + if(!eff->pd->rng) + eff->pd->rng = rng_new(eff->pd->seed + cfra); + else + rng_srandom(eff->pd->rng, eff->pd->seed + cfra); + + if(eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) { + Curve *cu= eff->ob->data; + if(cu->flag & CU_PATH) { + if(cu->path==NULL || cu->path->data==NULL) + makeDispListCurveTypes(eff->scene, eff->ob, 0); + + if(cu->path && cu->path->data) { + where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius); + Mat4MulVecfl(eff->ob->obmat, eff->guide_loc); + Mat4Mul3Vecfl(eff->ob->obmat, eff->guide_dir); } } } - else if(pd->forcefield) { - - if(pd->forcefield == PFIELD_WIND) - { - pd->rng = rng_new(pd->seed); - } - - ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); - ec->ob= ob; - BLI_addtail(lb, ec); + else if(eff->pd->shape == PFIELD_SHAPE_SURFACE) { + eff->surmd = (SurfaceModifierData *)modifiers_findByType ( eff->ob, eModifierType_Surface ); + } + else if(eff->psys) + psys_update_particle_tree(eff->psys, eff->scene->r.cfra); +} +static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) +{ + EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache"); + eff->scene = scene; + eff->ob = ob; + eff->psys = psys; + eff->pd = pd; + eff->frame = -1; + + precalculate_effector(eff); + + return eff; +} +static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src) +{ + EffectorCache *eff = NULL; + + if( ob == ob_src || weights->weight[ob->pd->forcefield] == 0.0f ) + return; + + if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal ) + return; + + if(*effectors == NULL) + *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); + + eff = new_effector_cache(scene, ob, NULL, ob->pd); + + BLI_addtail(*effectors, eff); +} +static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src) +{ + ParticleSettings *part= psys->part; + + if( !psys_check_enabled(ob, psys) ) + return; + + if( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0) + return; + + if( part->pd && part->pd->forcefield && weights->weight[part->pd->forcefield] != 0.0f) { + if(*effectors == NULL) + *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); + + BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd)); + } + + if (part->pd2 && part->pd2->forcefield && weights->weight[part->pd2->forcefield] != 0.0f) { + if(*effectors == NULL) + *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); + + BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2)); } } /* returns ListBase handle with objects taking part in the effecting */ -ListBase *pdInitEffectors(Scene *scene, Object *obsrc, Group *group) +ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, EffectorWeights *weights) { - static ListBase listb={NULL, NULL}; - pEffectorCache *ec; Base *base; - unsigned int layer= obsrc->lay; + unsigned int layer= ob_src->lay; + ListBase *effectors = NULL; - if(group) { + if(weights->group) { GroupObject *go; - for(go= group->gobject.first; go; go= go->next) { - if( (go->ob->lay & layer) && go->ob->pd && go->ob!=obsrc) { - add_to_effectorcache(&listb, scene, go->ob, obsrc); + for(go= weights->group->gobject.first; go; go= go->next) { + if( (go->ob->lay & layer) ) { + if( go->ob->pd && go->ob->pd->forcefield ) + add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src); + + if( go->ob->particlesystem.first ) { + ParticleSystem *psys= go->ob->particlesystem.first; + + for( ; psys; psys=psys->next ) + add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src); + } } } } else { for(base = scene->base.first; base; base= base->next) { - if( (base->lay & layer) && base->object->pd && base->object!=obsrc) { - add_to_effectorcache(&listb, scene, base->object, obsrc); + if( (base->lay & layer) ) { + if( base->object->pd && base->object->pd->forcefield ) + add_object_to_effectors(&effectors, scene, weights, base->object, ob_src); + + if( base->object->particlesystem.first ) { + ParticleSystem *psys= base->object->particlesystem.first; + + for( ; psys; psys=psys->next ) + add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src); + } } } } - - /* make a full copy */ - for(ec= listb.first; ec; ec= ec->next) { - ec->obcopy= *(ec->ob); - } - - if(listb.first) - return &listb; - - return NULL; + return effectors; } -void pdEndEffectors(ListBase *lb) +void pdEndEffectors(ListBase **effectors) { - if(lb) { - pEffectorCache *ec; - /* restore full copy */ - for(ec= lb->first; ec; ec= ec->next) - { - if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND)) - rng_free(ec->ob->pd->rng); - - *(ec->ob)= ec->obcopy; + if(*effectors) { + EffectorCache *eff = (*effectors)->first; + + for(; eff; eff=eff->next) { + if(eff->guide_data) + MEM_freeN(eff->guide_data); } - BLI_freelistN(lb); + BLI_freelistN(*effectors); + MEM_freeN(*effectors); + *effectors = NULL; } } +void pd_point_from_particle(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, EffectedPoint *point) +{ + point->loc = state->co; + point->vel = state->vel; + point->index = pa - sim->psys->particles; + point->size = pa->size; + /* TODO: point->charge */ + point->charge = 1.0f; + + point->vel_to_sec = 1.0f; + point->vel_to_frame = psys_get_timestep(sim); + + point->flag = 0; + + if(sim->psys->part->flag & PART_ROT_DYN) { + point->ave = state->ave; + point->rot = state->rot; + } + else + point->ave = point->rot = NULL; + + point->psys = sim->psys; +} + +void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point) +{ + point->loc = loc; + point->vel = vel; + point->index = index; + point->size = 0.0f; + + point->vel_to_sec = (float)scene->r.frs_sec; + point->vel_to_frame = 1.0f; + + point->flag = 0; + + point->ave = point->rot = NULL; + point->psys = NULL; +} +void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point) +{ + point->loc = loc; + point->vel = vel; + point->index = index; + point->size = 0.0f; + + point->vel_to_sec = (float)scene->r.frs_sec; + point->vel_to_frame = 1.0f; + + point->flag = PE_WIND_AS_SPEED; + + point->ave = point->rot = NULL; + + point->psys = NULL; +} /************************************************/ /* Effectors */ /************************************************/ @@ -256,27 +414,33 @@ static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BV } // get visibility of a wind ray -static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir) +static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, EffectorData *efd, EffectedPoint *point) { - Object **collobjs = NULL; - int numcollobj = 0, i; + ListBase *colls = colliders; + ColliderCache *col; float norm[3], len = 0.0; float visibility = 1.0, absorption = 0.0; - collobjs = get_collisionobjects(scene, ob, &numcollobj); - - if(!collobjs) - return 0; + if(!(eff->pd->flag & PFIELD_VISIBILITY)) + return visibility; + + if(!colls) + colls = get_collider_cache(eff->scene, NULL); + + if(!colls) + return visibility; - VECCOPY(norm, dir); + VECCOPY(norm, efd->vec_to_point); VecNegf(norm); len = Normalize(norm); // check all collision objects - for(i = 0; i < numcollobj; i++) + for(col = colls->first; col; col = col->next) { - Object *collob= collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); + CollisionModifierData *collmd = col->collmd; + + if(col->ob == eff->ob) + continue; if(collmd->bvhtree) { @@ -286,9 +450,9 @@ static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir hit.dist = len + FLT_EPSILON; // check if the way is blocked - if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) + if(BLI_bvhtree_ray_cast(collmd->bvhtree, point->loc, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) { - absorption= (collob->pd)? collob->pd->absorption: 0.0f; + absorption= col->ob->pd->absorption; // visibility is only between 0 and 1, calculated from 1-absorption visibility *= CLAMPIS(1.0f-absorption, 0.0f, 1.0f); @@ -298,8 +462,9 @@ static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir } } } - - MEM_freeN(collobjs); + + if(!colliders) + free_collider_cache(&colls); return visibility; } @@ -347,43 +512,39 @@ static float falloff_func_rad(PartDeflect *pd, float fac) return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r); } -float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part) +float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, EffectorWeights *weights) { - float eff_dir[3], temp[3]; - float falloff=1.0, fac, r_fac; - - if(pd->forcefield==PFIELD_LENNARDJ) - return falloff; /* Lennard-Jones field has it's own falloff built in */ + float temp[3]; + float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f; + float fac, r_fac; - VecCopyf(eff_dir,eff_velocity); - Normalize(eff_dir); + fac = Inpf(efd->nor, efd->vec_to_point); - if(pd->flag & PFIELD_POSZ && Inpf(eff_dir,vec_to_part)<0.0f) + if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f) falloff=0.0f; - else switch(pd->falloff){ + else if(eff->pd->zdir == PFIELD_Z_NEG && fac > 0.0f) + falloff=0.0f; + else switch(eff->pd->falloff){ case PFIELD_FALL_SPHERE: - fac=VecLength(vec_to_part); - falloff= falloff_func_dist(pd, fac); + falloff*= falloff_func_dist(eff->pd, efd->distance); break; case PFIELD_FALL_TUBE: - fac=Inpf(vec_to_part,eff_dir); - falloff= falloff_func_dist(pd, ABS(fac)); + falloff*= falloff_func_dist(eff->pd, ABS(fac)); if(falloff == 0.0f) break; - VECADDFAC(temp,vec_to_part,eff_dir,-fac); - r_fac=VecLength(temp); - falloff*= falloff_func_rad(pd, r_fac); + VECADDFAC(temp, efd->vec_to_point, efd->nor, -fac); + r_fac= VecLength(temp); + falloff*= falloff_func_rad(eff->pd, r_fac); break; case PFIELD_FALL_CONE: - fac=Inpf(vec_to_part,eff_dir); - falloff= falloff_func_dist(pd, ABS(fac)); + falloff*= falloff_func_dist(eff->pd, ABS(fac)); if(falloff == 0.0f) break; - r_fac=saacos(fac/VecLength(vec_to_part))*180.0f/(float)M_PI; - falloff*= falloff_func_rad(pd, r_fac); + r_fac=saacos(fac/VecLength(efd->vec_to_point))*180.0f/(float)M_PI; + falloff*= falloff_func_rad(eff->pd, r_fac); break; } @@ -391,127 +552,391 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part) return falloff; } -void do_physical_effector(Scene *scene, Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size) +int closest_point_on_surface(SurfaceModifierData *surmd, float *co, float *surface_co, float *surface_nor, float *surface_vel) { - float mag_vec[3]={0,0,0}; - float temp[3], temp2[3]; - float eff_vel[3]; - float noise = 0, visibility; - - // calculate visibility - visibility = eff_calc_visibility(scene, ob, opco, vec_to_part); - if(visibility <= 0.0) - return; - falloff *= visibility; + BVHTreeNearest nearest; - VecCopyf(eff_vel,eff_velocity); - Normalize(eff_vel); + nearest.index = -1; + nearest.dist = FLT_MAX; - switch(type){ - case PFIELD_WIND: - VECCOPY(mag_vec,eff_vel); - - // add wind noise here, only if we have wind - if((noise_factor > 0.0f) && (force_val > FLT_EPSILON)) - noise = wind_func(rng, noise_factor); + BLI_bvhtree_find_nearest(surmd->bvhtree->tree, co, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree); + + if(nearest.index != -1) { + VECCOPY(surface_co, nearest.co); + + if(surface_nor) { + VECCOPY(surface_nor, nearest.no); + } + + if(surface_vel) { + MFace *mface = CDDM_get_face(surmd->dm, nearest.index); - VecMulf(mag_vec,(force_val+noise)*falloff); - VecAddf(field,field,mag_vec); - break; + VECCOPY(surface_vel, surmd->v[mface->v1].co); + VecAddf(surface_vel, surface_vel, surmd->v[mface->v2].co); + VecAddf(surface_vel, surface_vel, surmd->v[mface->v3].co); + if(mface->v4) + VecAddf(surface_vel, surface_vel, surmd->v[mface->v4].co); - case PFIELD_FORCE: - if(planar) - Projf(mag_vec,vec_to_part,eff_vel); - else - VecCopyf(mag_vec,vec_to_part); + VecMulf(surface_vel, mface->v4 ? 0.25f : 0.333f); + } + return 1; + } - Normalize(mag_vec); + return 0; +} +int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int real_velocity) +{ + float cfra = eff->scene->r.cfra; + int ret = 0; - VecMulf(mag_vec,force_val*falloff); - VecAddf(field,field,mag_vec); - break; + if(eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) { + /* closest point in the object surface is an effector */ + float vec[3]; - case PFIELD_VORTEX: - Crossf(mag_vec,eff_vel,vec_to_part); + /* using velocity corrected location allows for easier sliding over effector surface */ + VecCopyf(vec, point->vel); + VecMulf(vec, point->vel_to_frame); + VecAddf(vec, vec, point->loc); - Normalize(mag_vec); + ret = closest_point_on_surface(eff->surmd, vec, efd->loc, efd->nor, real_velocity ? efd->vel : NULL); - VecMulf(mag_vec,force_val*distance*falloff); - VecAddf(field,field,mag_vec); + efd->size = 0.0f; + } + else if(eff->pd->shape==PFIELD_SHAPE_POINTS) { - break; - case PFIELD_MAGNET: - if(planar) - VecCopyf(temp,eff_vel); - else - /* magnetic field of a moving charge */ - Crossf(temp,eff_vel,vec_to_part); + if(eff->ob->derivedFinal) { + DerivedMesh *dm = eff->ob->derivedFinal; - Normalize(temp); + dm->getVertCo(dm, *efd->index, efd->loc); + dm->getVertNo(dm, *efd->index, efd->nor); - Crossf(temp2,velocity,temp); - VecAddf(mag_vec,mag_vec,temp2); + Mat4MulVecfl(eff->ob->obmat, efd->loc); + Mat4Mul3Vecfl(eff->ob->obmat, efd->nor); - VecMulf(mag_vec,force_val*falloff); - VecAddf(field,field,mag_vec); - break; - case PFIELD_HARMONIC: - if(planar) - Projf(mag_vec,vec_to_part,eff_vel); - else - VecCopyf(mag_vec,vec_to_part); + Normalize(efd->nor); - VecMulf(mag_vec,force_val*falloff); - VecSubf(field,field,mag_vec); + efd->size = 0.0f; - VecCopyf(mag_vec,velocity); - VecMulf(mag_vec,damp*2.0f*(float)sqrt(force_val)); - VecSubf(field,field,mag_vec); - break; - case PFIELD_CHARGE: - if(planar) - Projf(mag_vec,vec_to_part,eff_vel); - else - VecCopyf(mag_vec,vec_to_part); + /**/ + ret = 1; + } + } + else if(eff->psys) { + ParticleSimulationData sim = {eff->scene, eff->ob, eff->psys, NULL, NULL}; + ParticleData *pa = eff->psys->particles + *efd->index; + ParticleKey state; + + /* exclude the particle itself for self effecting particles */ + if(eff->psys == point->psys && *efd->index == point->index) + ; + else { + /* TODO: time from actual previous calculated frame (step might not be 1) */ + state.time = cfra - 1.0; + ret = psys_get_particle_state(&sim, *efd->index, &state, 0); + + /* TODO */ + //if(eff->pd->forcefiled == PFIELD_HARMONIC && ret==0) { + // if(pa->dietime < eff->psys->cfra) + // eff->flag |= PE_VELOCITY_TO_IMPULSE; + //} + + VECCOPY(efd->loc, state.co); + VECCOPY(efd->nor, state.vel); + if(real_velocity) { + VECCOPY(efd->vel, state.vel); + } - Normalize(mag_vec); + efd->size = pa->size; + } + } + else { + /* use center of object for distance calculus */ + Object *ob = eff->ob; + Object obcopy = *ob; + + where_is_object_time(eff->scene, ob, cfra); + + /* use z-axis as normal*/ + VECCOPY(efd->nor, ob->obmat[2]); + Normalize(efd->nor); + + /* for vortex the shape chooses between old / new force */ + if(eff->pd->shape == PFIELD_SHAPE_PLANE) { + /* efd->loc is closes point on effector xy-plane */ + float temp[3]; + VecSubf(temp, point->loc, ob->obmat[3]); + Projf(efd->loc, temp, efd->nor); + VecSubf(efd->loc, point->loc, efd->loc); + } + else { + VECCOPY(efd->loc, ob->obmat[3]); + } - VecMulf(mag_vec,charge*force_val*falloff); - VecAddf(field,field,mag_vec); - break; - case PFIELD_LENNARDJ: - { - float fac; + if(real_velocity) { + VECCOPY(efd->vel, ob->obmat[3]); + + where_is_object_time(eff->scene, ob, cfra - 1.0); + + VecSubf(efd->vel, efd->vel, ob->obmat[3]); + } + + *eff->ob = obcopy; + + efd->size = 0.0f; + + ret = 1; + } + + if(ret) { + VecSubf(efd->vec_to_point, point->loc, efd->loc); + efd->distance = VecLength(efd->vec_to_point); + + /* for some effectors we need the object center every time */ + VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]); + VECCOPY(efd->nor2, eff->ob->obmat[2]); + Normalize(efd->nor2); + } + + return ret; +} +static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p) +{ + if(eff->pd->shape == PFIELD_SHAPE_POINTS) { + efd->index = p; + + *p = 0; + *tot = eff->ob->derivedFinal ? eff->ob->derivedFinal->numVertData : 1; + + if(*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) { + *p = point->index % *tot; + *tot = *p+1; + } + } + else if(eff->psys) { + efd->index = p; + + *p = 0; + *tot = eff->psys->totpart; + + if(eff->pd->forcefield == PFIELD_CHARGE) { + /* Only the charge of the effected particle is used for + interaction, not fall-offs. If the fall-offs aren't the + same this will be unphysical, but for animation this + could be the wanted behavior. If you want physical + correctness the fall-off should be spherical 2.0 anyways. + */ + efd->charge = eff->pd->f_strength; + } + else if(eff->pd->forcefield == PFIELD_HARMONIC) { + /* every particle is mapped to only one harmonic effector particle */ + *p= point->index % eff->psys->totpart; + *tot= *p + 1; + } + } + else { + *p = 0; + *tot = 1; + } +} +static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) +{ + TexResult result[4]; + float tex_co[3], strength, force[3]; + float nabla = eff->pd->tex_nabla; + int hasrgb; + short mode = eff->pd->tex_mode; + + if(!eff->pd->tex) + return; + + result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0; + + strength= eff->pd->f_strength * efd->falloff; + + VECCOPY(tex_co,point->loc); + + if(eff->pd->flag & PFIELD_TEX_2D) { + float fac=-Inpf(tex_co, efd->nor); + VECADDFAC(tex_co, tex_co, efd->nor, fac); + } + + if(eff->pd->flag & PFIELD_TEX_OBJECT) { + Mat4Mul3Vecfl(eff->ob->obmat, tex_co); + } + + hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL,NULL, 1, result); + + if(hasrgb && mode==PFIELD_TEX_RGB) { + force[0] = (0.5f - result->tr) * strength; + force[1] = (0.5f - result->tg) * strength; + force[2] = (0.5f - result->tb) * strength; + } + else { + strength/=nabla; + + tex_co[0] += nabla; + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 1, result+1); + + tex_co[0] -= nabla; + tex_co[1] += nabla; + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 1, result+2); - if(planar) { - Projf(mag_vec,vec_to_part,eff_vel); - distance = VecLength(mag_vec); + tex_co[1] -= nabla; + tex_co[2] += nabla; + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 1, result+3); + + if(mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we dont have rgb fall back to grad */ + force[0] = (result[0].tin - result[1].tin) * strength; + force[1] = (result[0].tin - result[2].tin) * strength; + force[2] = (result[0].tin - result[3].tin) * strength; + } + else { /*PFIELD_TEX_CURL*/ + float dbdy, dgdz, drdz, dbdx, dgdx, drdy; + + dbdy = result[2].tb - result[0].tb; + dgdz = result[3].tg - result[0].tg; + drdz = result[3].tr - result[0].tr; + dbdx = result[1].tb - result[0].tb; + dgdx = result[1].tg - result[0].tg; + drdy = result[2].tr - result[0].tr; + + force[0] = (dbdy - dgdz) * strength; + force[1] = (drdz - dbdx) * strength; + force[2] = (dgdx - drdy) * strength; + } + } + + if(eff->pd->flag & PFIELD_TEX_2D){ + float fac = -Inpf(force, efd->nor); + VECADDFAC(force, force, efd->nor, fac); + } + + VecAddf(total_force, total_force, force); +} +void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) +{ + PartDeflect *pd = eff->pd; + RNG *rng = pd->rng; + float force[3]={0,0,0}; + float temp[3]; + float fac; + float strength = pd->f_strength; + float damp = pd->f_damp; + float noise_factor = pd->f_noise; + + if(noise_factor > 0.0f) { + strength += wind_func(rng, noise_factor); + + if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)) + damp += wind_func(rng, noise_factor); + } + + VECCOPY(force, efd->vec_to_point); + + switch(pd->forcefield){ + case PFIELD_WIND: + Normalize(force); + strength *= (Inpf(force, efd->nor) >= 0.0f ? 1.0f : -1.0f); + VecMulf(force, strength * efd->falloff); + break; + case PFIELD_FORCE: + Normalize(force); + VecMulf(force, strength * efd->falloff); + break; + case PFIELD_VORTEX: + /* old vortex force */ + if(pd->shape == PFIELD_SHAPE_POINT) { + Crossf(force, efd->nor, efd->vec_to_point); + Normalize(force); + VecMulf(force, strength * efd->distance * efd->falloff); } + else { + /* new vortex force */ + Crossf(temp, efd->nor2, efd->vec_to_point2); + VecMulf(temp, strength * efd->falloff); + + Crossf(force, efd->nor2, temp); + VecMulf(force, strength * efd->falloff); + + VECADDFAC(temp, temp, point->vel, -point->vel_to_sec); + VecAddf(force, force, temp); + } + break; + case PFIELD_MAGNET: + if(eff->pd->shape == PFIELD_SHAPE_POINT) + /* magnetic field of a moving charge */ + Crossf(temp, efd->nor, efd->vec_to_point); else - VecCopyf(mag_vec,vec_to_part); - - /* at this distance the field is 60 times weaker than maximum */ - if(distance > 2.22 * (size+pa_size)) - break; + VecCopyf(temp, efd->nor); - fac = pow((size+pa_size)/distance,6.0); + Normalize(temp); + VecMulf(temp, strength * efd->falloff); + Crossf(force, point->vel, temp); + VecMulf(force, point->vel_to_sec); + break; + case PFIELD_HARMONIC: + VecMulf(force, -strength * efd->falloff); + VecCopyf(temp, point->vel); + VecMulf(temp, -damp * 2.0f * (float)sqrt(fabs(strength)) * point->vel_to_sec); + VecAddf(force, force, temp); + break; + case PFIELD_CHARGE: + VecMulf(force, point->charge * strength * efd->falloff); + break; + case PFIELD_LENNARDJ: + fac = pow((efd->size + point->size) / efd->distance, 6.0); - fac = - fac * (1.0 - fac) / distance; + fac = - fac * (1.0 - fac) / efd->distance; /* limit the repulsive term drastically to avoid huge forces */ fac = ((fac>2.0) ? 2.0 : fac); - /* 0.003715 is the fac value at 2.22 times (size+pa_size), - substracted to avoid discontinuity at the border - */ - VecMulf(mag_vec, force_val * (fac-0.0037315)); - VecAddf(field,field,mag_vec); + VecMulf(force, strength * fac); break; - } case PFIELD_BOID: /* Boid field is handled completely in boids code. */ + return; + case PFIELD_TURBULENCE: + if(pd->flag & PFIELD_GLOBAL_CO) { + VECCOPY(temp, point->loc); + } + else { + VECADD(temp, efd->vec_to_point2, efd->nor2); + } + force[0] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[0], temp[1], temp[2], 2,0,2); + force[1] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[1], temp[2], temp[0], 2,0,2); + force[2] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[2], temp[0], temp[1], 2,0,2); + VecMulf(force, strength * efd->falloff); + break; + case PFIELD_DRAG: + VECCOPY(force, point->vel); + fac = Normalize(force) * point->vel_to_sec; + + strength = MIN2(strength, 2.0f); + damp = MIN2(damp, 2.0f); + + VecMulf(force, -efd->falloff * fac * (strength * fac + damp)); break; } + + if(pd->flag & PFIELD_DO_LOCATION) { + VECADDFAC(total_force, total_force, force, 1.0f/point->vel_to_sec); + + if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)==0 && pd->f_flow != 0.0f) { + VECADDFAC(total_force, total_force, point->vel, -pd->f_flow * efd->falloff); + } + } + + if(pd->flag & PFIELD_DO_ROTATION && point->ave && point->rot) { + float xvec[3] = {1.0f, 0.0f, 0.0f}; + float dave[3]; + QuatMulVecf(point->rot, xvec); + Crossf(dave, xvec, force); + if(pd->f_flow != 0.0f) { + VECADDFAC(dave, dave, point->ave, -pd->f_flow * efd->falloff); + } + VecAddf(point->ave, point->ave, dave); + } } /* -------- pdDoEffectors() -------- @@ -528,7 +953,7 @@ void do_physical_effector(Scene *scene, Object *ob, float *opco, short type, flo guide = old speed of particle */ -void pdDoEffectors(Scene *scene, ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags) +void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse) { /* Modifies the force on a particle according to its @@ -543,43 +968,45 @@ void pdDoEffectors(Scene *scene, ListBase *lb, float *opco, float *force, float (particles are guided along a curve bezier or old nurbs) (is independent of other effectors) */ - Object *ob; - pEffectorCache *ec; - PartDeflect *pd; - - float distance, vec_to_part[3]; - float falloff; + EffectorCache *eff; + EffectorData efd; + int p=0, tot = 1; /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */ /* Check for min distance here? (yes would be cool to add that, ton) */ - for(ec = lb->first; ec; ec= ec->next) { + if(effectors) for(eff = effectors->first; eff; eff=eff->next) { /* object effectors were fully checked to be OK to evaluate! */ - ob= ec->ob; - pd= ob->pd; - - /* Get IPO force strength and fall off values here */ - where_is_object_time(scene, ob, cur_time); - - /* use center of object for distance calculus */ - VecSubf(vec_to_part, opco, ob->obmat[3]); - distance = VecLength(vec_to_part); - falloff=effector_falloff(pd,ob->obmat[2],vec_to_part); - - if(falloff<=0.0f) - ; /* don't do anything */ - else { - float field[3]={0,0,0}, tmp[3]; - VECCOPY(field, force); - do_physical_effector(scene, ob, opco, pd->forcefield,pd->f_strength,distance, - falloff, pd->f_dist, pd->f_damp, ob->obmat[2], vec_to_part, - speed,force, pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise, 0.0f, 0.0f); - - // for softbody backward compatibility - if(flags & PE_WIND_AS_SPEED){ - VECSUB(tmp, force, field); - VECSUB(speed, speed, tmp); + get_effector_tot(eff, &efd, point, &tot, &p); + + for(; p<tot; p++) { + if(get_effector_data(eff, &efd, point, 0)) { + efd.falloff= effector_falloff(eff, &efd, point, weights); + + if(efd.falloff > 0.0f) + efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point); + + if(efd.falloff <= 0.0f) + ; /* don't do anything */ + else if(eff->pd->forcefield == PFIELD_TEXTURE) + do_texture_effector(eff, &efd, point, force); + else { + float temp1[3]={0,0,0}, temp2[3]; + VECCOPY(temp1, force); + + do_physical_effector(eff, &efd, point, force); + + // for softbody backward compatibility + if(point->flag & PE_WIND_AS_SPEED && impulse){ + VECSUB(temp2, force, temp1); + VECSUB(impulse, impulse, temp2); + } + } + } + else if(eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) { + /* special case for harmonic effector */ + VECADD(impulse, impulse, efd.vel); } } } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index ae2acd6aef7..de215ae4af9 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -33,6 +33,7 @@ #include "DNA_cloth_types.h" #include "DNA_scene_types.h" +#include "DNA_object_force.h" #include "BKE_effect.h" #include "BKE_global.h" @@ -1482,15 +1483,19 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, Cloth *cloth = clmd->clothObject; int i = 0; float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */ - float gravity[3]; + float gravity[3] = {0.0f, 0.0f, 0.0f}; float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; MFace *mfaces = cloth->mfaces; unsigned int numverts = cloth->numverts; LinkNode *search = cloth->springs; lfVector *winvec; + EffectedPoint epoint; - VECCOPY(gravity, clmd->sim_parms->gravity); - mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ + /* global acceleration (gravitation) */ + if(clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + VECCOPY(gravity, clmd->scene->physics_settings.gravity); + mul_fvector_S(gravity, gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity); /* scale gravity force */ + } /* set dFdX jacobi matrix to zero */ init_bfmatrix(dFdX, ZERO); @@ -1525,10 +1530,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, // precalculate wind forces for(i = 0; i < cloth->numverts; i++) - { - float speed[3] = {0.0f, 0.0f,0.0f}; - - pdDoEffectors(clmd->scene, effectors, lX[i], winvec[i], speed, frame, 0.0f, 0); + { + pd_point_from_loc(clmd->scene, (float*)lX[i], (float*)lV[i], i, &epoint); + pdDoEffectors(effectors, NULL, clmd->sim_parms->effector_weights, &epoint, winvec[i], NULL); } for(i = 0; i < cloth->numfaces; i++) @@ -1656,9 +1660,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase while(step < tf) { // calculate forces - effectors= pdInitEffectors(clmd->scene, ob, NULL); cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M); - if(effectors) pdEndEffectors(effectors); // calculate new velocity simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI); @@ -1741,9 +1743,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase cp_lfvector(id->V, id->Vnew, numverts); // calculate - effectors= pdInitEffectors(clmd->scene, ob, NULL); cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step+dt, id->M); - if(effectors) pdEndEffectors(effectors); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index b9b9ea6b4f3..3b47c2f1830 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5971,6 +5971,8 @@ static void clothModifier_copyData(ModifierData *md, ModifierData *target) tclmd->point_cache = NULL; tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms); + if(clmd->sim_parms->effector_weights) + tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights); tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms); tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches); tclmd->clothObject = NULL; @@ -5992,8 +5994,11 @@ static void clothModifier_freeData(ModifierData *md) cloth_free_modifier_extern (clmd); - if(clmd->sim_parms) + if(clmd->sim_parms) { + if(clmd->sim_parms->effector_weights) + MEM_freeN(clmd->sim_parms->effector_weights); MEM_freeN(clmd->sim_parms); + } if(clmd->coll_parms) MEM_freeN(clmd->coll_parms); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 4c729845745..579466ea626 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -91,6 +91,7 @@ #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_displist.h" +#include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_group.h" #include "BKE_icons.h" @@ -298,11 +299,8 @@ void free_object(Object *ob) free_constraints(&ob->constraints); - if(ob->pd){ - if(ob->pd->tex) - ob->pd->tex->id.us--; - MEM_freeN(ob->pd); - } + free_partdeflect(ob->pd); + if(ob->soft) sbFree(ob->soft); if(ob->bsoft) bsbFree(ob->bsoft); if(ob->gpulamp.first) GPU_lamp_free(ob); @@ -1069,6 +1067,9 @@ SoftBody *copy_softbody(SoftBody *sb) sbn->pointcache= BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches); + if(sb->effector_weights) + sbn->effector_weights = MEM_dupallocN(sb->effector_weights); + return sbn; } @@ -1129,11 +1130,9 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn->pathcache= NULL; psysn->childcache= NULL; psysn->edit= NULL; - psysn->effectors.first= psysn->effectors.last= 0; psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL; psysn->childcachebufs.first = psysn->childcachebufs.last = NULL; - psysn->reactevents.first = psysn->reactevents.last = NULL; psysn->renderdata = NULL; psysn->pointcache= BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches); @@ -1278,6 +1277,8 @@ Object *copy_object(Object *ob) obn->pd= MEM_dupallocN(ob->pd); if(obn->pd->tex) id_us_plus(&(obn->pd->tex->id)); + if(obn->pd->rng) + obn->pd->rng = MEM_dupallocN(ob->pd->rng); } obn->soft= copy_softbody(ob->soft); obn->bsoft = copy_bulletsoftbody(ob->bsoft); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index e18e7f54e49..e63b77a134e 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -53,7 +53,7 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" #include "BLI_kdtree.h" -#include "BLI_linklist.h" +#include "BLI_listbase.h" #include "BLI_rand.h" #include "BLI_threads.h" @@ -61,6 +61,7 @@ #include "BKE_boids.h" #include "BKE_cloth.h" +#include "BKE_effect.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_lattice.h" @@ -96,8 +97,7 @@ int count_particles(ParticleSystem *psys){ int tot=0; LOOP_SHOWN_PARTICLES { - if(pa->alive == PARS_KILLED); - else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); + if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); else tot++; } @@ -109,8 +109,7 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){ int tot=0; LOOP_SHOWN_PARTICLES { - if(pa->alive == PARS_KILLED); - else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); + if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); else if(p%totgr==cur) tot++; } @@ -302,15 +301,11 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) /************************************************/ void psys_free_settings(ParticleSettings *part) { - if(part->pd) { - MEM_freeN(part->pd); - part->pd = NULL; - } - - if(part->pd2) { - MEM_freeN(part->pd2); - part->pd2 = NULL; - } + free_partdeflect(part->pd); + free_partdeflect(part->pd2); + + if(part->effector_weights) + MEM_freeN(part->effector_weights); boid_free_settings(part->boids); } @@ -428,21 +423,23 @@ void psys_free_particles(ParticleSystem *psys) } void psys_free_pdd(ParticleSystem *psys) { - if(psys->pdd->cdata) - MEM_freeN(psys->pdd->cdata); - psys->pdd->cdata = NULL; + if(psys->pdd) { + if(psys->pdd->cdata) + MEM_freeN(psys->pdd->cdata); + psys->pdd->cdata = NULL; - if(psys->pdd->vdata) - MEM_freeN(psys->pdd->vdata); - psys->pdd->vdata = NULL; + if(psys->pdd->vdata) + MEM_freeN(psys->pdd->vdata); + psys->pdd->vdata = NULL; - if(psys->pdd->ndata) - MEM_freeN(psys->pdd->ndata); - psys->pdd->ndata = NULL; + if(psys->pdd->ndata) + MEM_freeN(psys->pdd->ndata); + psys->pdd->ndata = NULL; - if(psys->pdd->vedata) - MEM_freeN(psys->pdd->vedata); - psys->pdd->vedata = NULL; + if(psys->pdd->vedata) + MEM_freeN(psys->pdd->vedata); + psys->pdd->vedata = NULL; + } } /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) @@ -465,9 +462,6 @@ void psys_free(Object *ob, ParticleSystem * psys) psys->child = 0; psys->totchild = 0; } - - if(psys->effectors.first) - psys_end_effectors(psys); // check if we are last non-visible particle system for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){ @@ -493,10 +487,11 @@ void psys_free(Object *ob, ParticleSystem * psys) psys->pointcache = NULL; BLI_freelistN(&psys->targets); - BLI_freelistN(&psys->reactevents); BLI_kdtree_free(psys->tree); + pdEndEffectors(&psys->effectors); + if(psys->frand) MEM_freeN(psys->frand); @@ -1896,124 +1891,135 @@ static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clu VecLerpf(state->co,state->co,par->co,clump); } } +void precalc_guides(ParticleSimulationData *sim, ListBase *effectors) +{ + EffectedPoint point; + ParticleKey state; + EffectorData efd; + EffectorCache *eff; + ParticleSystem *psys = sim->psys; + EffectorWeights *weights = sim->psys->part->effector_weights; + GuideEffectorData *data; + PARTICLE_P; + + if(!effectors) + return; + + LOOP_PARTICLES { + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,state.co,0,0,0,0,0); + pd_point_from_particle(sim, pa, &state, &point); + + for(eff = effectors->first; eff; eff=eff->next) { + if(eff->pd->forcefield != PFIELD_GUIDE) + continue; -int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase *lb) + if(!eff->guide_data) + eff->guide_data = MEM_callocN(sizeof(GuideEffectorData)*psys->totpart, "GuideEffectorData"); + + data = eff->guide_data + p; + + VECSUB(efd.vec_to_point, state.co, eff->guide_loc); + VECCOPY(efd.nor, eff->guide_dir); + efd.distance = VecLength(efd.vec_to_point); + + VECCOPY(data->vec_to_point, efd.vec_to_point); + data->strength = effector_falloff(eff, &efd, &point, weights); + } + } +} +int do_guides(ListBase *effectors, ParticleKey *state, int index, float time) { + EffectorCache *eff; PartDeflect *pd; - ParticleEffectorCache *ec; - Object *eob; Curve *cu; ParticleKey key, par; + GuideEffectorData *data; - float effect[3]={0.0,0.0,0.0}, distance, f_force, mindist, totforce=0.0; - float guidevec[4], guidedir[3], rot2[4], radius, temp[3], angle, pa_loc[3], pa_zero[3]={0.0f,0.0f,0.0f}; - float veffect[3]={0.0,0.0,0.0}, guidetime; + float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f}; + float guidevec[4], guidedir[3], rot2[4], temp[3]; + float guidetime, radius, angle, totstrength = 0.0f; + float vec_to_point[3]; - effect[0]=effect[1]=effect[2]=0.0; + if(effectors) for(eff = effectors->first; eff; eff=eff->next) { + pd = eff->pd; - if(lb->first){ - for(ec = lb->first; ec; ec= ec->next){ - eob= ec->ob; - if(ec->type & PSYS_EC_EFFECTOR){ - pd=eob->pd; - if(pd->forcefield==PFIELD_GUIDE){ - cu = (Curve*)eob->data; - - distance=ec->distances[pa_num]; - mindist=pd->f_strength; + if(pd->forcefield != PFIELD_GUIDE) + continue; - VECCOPY(pa_loc, ec->locations+3*pa_num); - VECCOPY(pa_zero,pa_loc); - VECADD(pa_zero,pa_zero,ec->firstloc); + data = eff->guide_data + index; - guidetime=time/(1.0-pd->free_end); + if(data->strength <= 0.0f) + continue; - /* WARNING: bails out with continue here */ - if(((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist) || guidetime>1.0f) continue; + guidetime = time / (1.0 - pd->free_end); - if(guidetime>1.0f) continue; + if(guidetime>1.0f) + continue; - /* calculate contribution factor for this guide */ - f_force=1.0f; - if(distance<=mindist); - else if(pd->flag & PFIELD_USEMAX) { - if(mindist>=pd->maxdist) f_force= 0.0f; - else if(pd->f_power!=0.0f){ - f_force= 1.0f - (distance-mindist)/(pd->maxdist - mindist); - f_force = (float)pow(f_force, pd->f_power); - } - } - else if(pd->f_power!=0.0f){ - f_force= 1.0f/(1.0f + distance-mindist); - f_force = (float)pow(f_force, pd->f_power); - } + cu = (Curve*)eff->ob->data; - if(pd->flag & PFIELD_GUIDE_PATH_ADD) - where_on_path(eob, f_force*guidetime, guidevec, guidedir, NULL, &radius); - else - where_on_path(eob, guidetime, guidevec, guidedir, NULL, &radius); + if(pd->flag & PFIELD_GUIDE_PATH_ADD) { + if(where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius)==0) + return 0; + } + else { + if(where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius)==0) + return 0; + } - Mat4MulVecfl(ec->ob->obmat,guidevec); - Mat4Mul3Vecfl(ec->ob->obmat,guidedir); + Mat4MulVecfl(eff->ob->obmat, guidevec); + Mat4Mul3Vecfl(eff->ob->obmat, guidedir); - Normalize(guidedir); + Normalize(guidedir); - if(guidetime!=0.0){ - /* curve direction */ - Crossf(temp, ec->firstdir, guidedir); - angle=Inpf(ec->firstdir,guidedir)/(VecLength(ec->firstdir)); - angle=saacos(angle); - VecRotToQuat(temp,angle,rot2); - QuatMulVecf(rot2,pa_loc); + VECCOPY(vec_to_point, data->vec_to_point); - /* curve tilt */ - VecRotToQuat(guidedir,guidevec[3]-ec->firstloc[3],rot2); - QuatMulVecf(rot2,pa_loc); + if(guidetime != 0.0){ + /* curve direction */ + Crossf(temp, eff->guide_dir, guidedir); + angle = Inpf(eff->guide_dir, guidedir)/(VecLength(eff->guide_dir)); + angle = saacos(angle); + VecRotToQuat(temp, angle, rot2); + QuatMulVecf(rot2, vec_to_point); - //vectoquat(guidedir, pd->kink_axis, (pd->kink_axis+1)%3, q); - //QuatMul(par.rot,rot2,q); - } - //else{ - // par.rot[0]=1.0f; - // par.rot[1]=par.rot[2]=par.rot[3]=0.0f; - //} - - /* curve taper */ - if(cu->taperobj) - VecMulf(pa_loc, calc_taper(scene, cu->taperobj, (int)(f_force*guidetime*100.0), 100)); - - else{ /* curve size*/ - if(cu->flag & CU_PATH_RADIUS) { - VecMulf(pa_loc, radius); - } - } - par.co[0]=par.co[1]=par.co[2]=0.0f; - VECCOPY(key.co,pa_loc); - do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0); - do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f); - VECCOPY(pa_loc,key.co); - - VECADD(pa_loc,pa_loc,guidevec); - VECSUB(pa_loc,pa_loc,pa_zero); - VECADDFAC(effect,effect,pa_loc,f_force); - VECADDFAC(veffect,veffect,guidedir,f_force); - totforce+=f_force; - } - } + /* curve tilt */ + VecRotToQuat(guidedir, guidevec[3] - eff->guide_loc[3], rot2); + QuatMulVecf(rot2, vec_to_point); } - if(totforce!=0.0){ - if(totforce>1.0) - VecMulf(effect,1.0f/totforce); - CLAMP(totforce,0.0,1.0); - VECADD(effect,effect,pa_zero); - VecLerpf(state->co,state->co,effect,totforce); + /* curve taper */ + if(cu->taperobj) + VecMulf(vec_to_point, calc_taper(eff->scene, cu->taperobj, (int)(data->strength*guidetime*100.0), 100)); - Normalize(veffect); - VecMulf(veffect,VecLength(state->vel)); - VECCOPY(state->vel,veffect); - return 1; + else{ /* curve size*/ + if(cu->flag & CU_PATH_RADIUS) { + VecMulf(vec_to_point, radius); + } } + par.co[0] = par.co[1] = par.co[2] = 0.0f; + VECCOPY(key.co, vec_to_point); + do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0); + do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f); + VECCOPY(vec_to_point, key.co); + + VECADD(vec_to_point, vec_to_point, guidevec); + //VECSUB(pa_loc,pa_loc,pa_zero); + VECADDFAC(effect, effect, vec_to_point, data->strength); + VECADDFAC(veffect, veffect, guidedir, data->strength); + totstrength += data->strength; + } + + if(totstrength != 0.0){ + if(totstrength > 1.0) + VecMulf(effect, 1.0f / totstrength); + CLAMP(totstrength, 0.0, 1.0); + //VECADD(effect,effect,pa_zero); + VecLerpf(state->co, state->co, effect, totstrength); + + Normalize(veffect); + VecMulf(veffect, VecLength(state->vel)); + VECCOPY(state->vel, veffect); + return 1; } return 0; } @@ -2053,14 +2059,18 @@ static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheK { float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}; ParticleKey eff_key; - ParticleData *pa; + EffectedPoint epoint; + + /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */ + if(sim->psys->flag & PSYS_HAIR_DYNAMICS) + return; VECCOPY(eff_key.co,(ca-1)->co); VECCOPY(eff_key.vel,(ca-1)->vel); QUATCOPY(eff_key.rot,(ca-1)->rot); - pa= sim->psys->particles+i; - do_effectors(sim, i, pa, &eff_key, rootco, force, vel, dfra, cfra); + pd_point_from_particle(sim, sim->psys->particles+i, &eff_key, &epoint); + pdDoEffectors(sim->psys->effectors, sim->colliders, sim->psys->part->effector_weights, &epoint, force, NULL); VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps); @@ -2777,9 +2787,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) do_path_effectors(sim, p, ca, k, steps, cache[p]->co, effector, dfra, cfra, &length, vec); /* apply guide curves to path data */ - if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) + if(sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT)==0) /* ca is safe to cast, since only co and vel are used */ - do_guide(sim->scene, (ParticleKey*)ca, p, (float)k/(float)steps, &psys->effectors); + do_guides(sim->psys->effectors, (ParticleKey*)ca, p, (float)k/(float)steps); /* apply lattice */ if(psys->lattice) @@ -3187,8 +3197,6 @@ void object_remove_particle_system(Scene *scene, Object *ob) } static void default_particle_settings(ParticleSettings *part) { - int i; - part->type= PART_EMITTER; part->distr= PART_DISTR_JIT; part->draw_as = PART_DRAW_REND; @@ -3199,7 +3207,7 @@ static void default_particle_settings(ParticleSettings *part) part->flag=PART_REACT_MULTIPLE|PART_HAIR_GEOMETRY|PART_EDISTR|PART_TRAND; part->sta= 1.0; - part->end= 100.0; + part->end= 200.0; part->lifetime= 50.0; part->jitfac= 1.0; part->totpart= 1000; @@ -3249,10 +3257,6 @@ static void default_particle_settings(ParticleSettings *part) part->keyed_loops = 1; - for(i=0; i<10; i++) - part->effector_weight[i]=1.0f; - - #if 0 // XXX old animation system part->ipo = NULL; #endif // XXX old animation system @@ -3261,6 +3265,9 @@ static void default_particle_settings(ParticleSettings *part) part->simplify_rate= 1.0f; part->simplify_transition= 0.1f; part->simplify_viewport= 0.8; + + if(!part->effector_weights) + part->effector_weights = BKE_add_effector_weights(NULL); } @@ -3348,24 +3355,6 @@ void make_local_particlesettings(ParticleSettings *part) } } } -void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int recalc) -{ - Base *base = scene->base.first; - ParticleSystem *psys; - int flush; - - for(base = scene->base.first; base; base = base->next) { - flush = 0; - for(psys = base->object->particlesystem.first; psys; psys=psys->next) { - if(psys->part == part) { - psys->recalc |= recalc; - flush++; - } - } - if(flush) - DAG_id_flush_update(&base->object->id, OB_RECALC_DATA); - } -} /************************************************/ /* Textures */ @@ -3646,7 +3635,7 @@ static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *pte if(part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ - guided = do_guide(sim->scene, (ParticleKey*)state, cpa->parent, t, &(sim->psys->effectors)); + guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t); if(guided==0){ if(part->kink) @@ -3716,8 +3705,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * Mat4MulVecfl(hairmat, state->co); Mat4Mul3Vecfl(hairmat, state->vel); - if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { - do_guide(sim->scene, state, p, state->time, &psys->effectors); + if(sim->psys->effectors && (part->flag & PART_CHILD_GUIDE)==0) { + do_guides(sim->psys->effectors, state, p, state->time); /* TODO: proper velocity handling */ } @@ -3905,8 +3894,6 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta } if(pa) { - if(pa->alive == PARS_KILLED) return 0; - if(!always) if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0) || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0)) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 1b6d56e6459..77cef689d09 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -58,7 +58,7 @@ #include "BLI_blenlib.h" #include "BLI_kdtree.h" #include "BLI_kdopbvh.h" -#include "BLI_linklist.h" +#include "BLI_listbase.h" #include "BLI_threads.h" #include "BKE_anim.h" @@ -132,9 +132,6 @@ void psys_reset(ParticleSystem *psys, int mode) psys->totkeyed= 0; psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED); - if(psys->reactevents.first) - BLI_freelistN(&psys->reactevents); - if(psys->edit && psys->free_edit) { psys->free_edit(psys->edit); psys->edit = NULL; @@ -1796,8 +1793,9 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* and gravity in r_ve */ bpa->gravity[0] = bpa->gravity[1] = 0.0f; bpa->gravity[2] = -1.0f; - if(part->acc[2]!=0.0f) - bpa->gravity[2] = part->acc[2]; + if((sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) + && sim->scene->physics_settings.gravity[2]!=0.0f) + bpa->gravity[2] = sim->scene->physics_settings.gravity[2]; /* calculate rotation matrix */ Projf(dvec, r_vel, pa->state.ave); @@ -1936,8 +1934,12 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, pa->dietime = pa->time + pa->lifetime; - if(pa->time >= cfra) + if(pa->time > cfra) pa->alive = PARS_UNBORN; + else if(pa->dietime <= cfra) + pa->alive = PARS_DEAD; + else + pa->alive = PARS_ALIVE; pa->state.time = cfra; } @@ -2203,12 +2205,12 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra /************************************************/ /* Effectors */ /************************************************/ -static void update_particle_tree(ParticleSystem *psys) +void psys_update_particle_tree(ParticleSystem *psys, float cfra) { if(psys) { PARTICLE_P; - if(!psys->tree || psys->tree_frame != psys->cfra) { + if(!psys->tree || psys->tree_frame != cfra) { BLI_kdtree_free(psys->tree); @@ -2216,7 +2218,10 @@ static void update_particle_tree(ParticleSystem *psys) LOOP_SHOWN_PARTICLES { if(pa->alive == PARS_ALIVE) - BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); + if(pa->state.time == cfra) + BLI_kdtree_insert(psys->tree, p, pa->prev_state.co, NULL); + else + BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); } BLI_kdtree_balance(psys->tree); @@ -2224,535 +2229,12 @@ static void update_particle_tree(ParticleSystem *psys) } } } -static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, short object, float *pa_co, float obmat[4][4], float force_val, float falloff, float *field) -{ - TexResult result[4]; - float tex_co[3], strength, mag_vec[3]; - int hasrgb; - if(tex==NULL) return; - - result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0; - - strength= force_val*falloff; - - VECCOPY(tex_co,pa_co); - - if(is_2d){ - float fac=-Inpf(tex_co,obmat[2]); - VECADDFAC(tex_co,tex_co,obmat[2],fac); - } - - if(object){ - VecSubf(tex_co,tex_co,obmat[3]); - Mat4Mul3Vecfl(obmat,tex_co); - } - - hasrgb = multitex_ext(tex, tex_co, NULL,NULL, 1, result); - - if(hasrgb && mode==PFIELD_TEX_RGB){ - mag_vec[0]= (0.5f-result->tr)*strength; - mag_vec[1]= (0.5f-result->tg)*strength; - mag_vec[2]= (0.5f-result->tb)*strength; - } - else{ - strength/=nabla; - - tex_co[0]+= nabla; - multitex_ext(tex, tex_co, NULL,NULL, 1, result+1); - - tex_co[0]-= nabla; - tex_co[1]+= nabla; - multitex_ext(tex, tex_co, NULL,NULL, 1, result+2); - - tex_co[1]-= nabla; - tex_co[2]+= nabla; - multitex_ext(tex, tex_co, NULL,NULL, 1, result+3); - - if(mode==PFIELD_TEX_GRAD || !hasrgb){ /* if we dont have rgb fall back to grad */ - mag_vec[0]= (result[0].tin-result[1].tin)*strength; - mag_vec[1]= (result[0].tin-result[2].tin)*strength; - mag_vec[2]= (result[0].tin-result[3].tin)*strength; - } - else{ /*PFIELD_TEX_CURL*/ - float dbdy,dgdz,drdz,dbdx,dgdx,drdy; - - dbdy= result[2].tb-result[0].tb; - dgdz= result[3].tg-result[0].tg; - drdz= result[3].tr-result[0].tr; - dbdx= result[1].tb-result[0].tb; - dgdx= result[1].tg-result[0].tg; - drdy= result[2].tr-result[0].tr; - - mag_vec[0]=(dbdy-dgdz)*strength; - mag_vec[1]=(drdz-dbdx)*strength; - mag_vec[2]=(dgdx-drdy)*strength; - } - } - - if(is_2d){ - float fac=-Inpf(mag_vec,obmat[2]); - VECADDFAC(mag_vec,mag_vec,obmat[2],fac); - } - - VecAddf(field,field,mag_vec); -} -static void add_to_effectors(ParticleSimulationData *sim, ListBase *lb, Object *ob) -{ - ParticleEffectorCache *ec; - PartDeflect *pd= ob->pd; - short type=0,i; - - if(pd && ob != sim->ob){ - if(pd->forcefield == PFIELD_GUIDE) { - if(ob->type==OB_CURVE) { - Curve *cu= ob->data; - if(cu->flag & CU_PATH) { - if(cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(sim->scene, ob, 0); - if(cu->path && cu->path->data) { - type |= PSYS_EC_EFFECTOR; - } - } - } - } - else if(pd->forcefield) - { - type |= PSYS_EC_EFFECTOR; - } - } - - if(pd && pd->deflect) - type |= PSYS_EC_DEFLECT; - - if(type){ - ec= MEM_callocN(sizeof(ParticleEffectorCache), "effector cache"); - ec->ob= ob; - ec->type=type; - ec->distances=0; - ec->locations=0; - ec->rng = rng_new(1); - rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed - - BLI_addtail(lb, ec); - } - - type=0; - - /* add particles as different effectors */ - if(ob->particlesystem.first){ - ParticleSystem *epsys=ob->particlesystem.first; - ParticleSettings *epart=0; - //Object *tob; - - for(i=0; epsys; epsys=epsys->next,i++){ - if(!psys_check_enabled(ob, epsys)) - continue; - type=0; - if(epsys!=sim->psys || (sim->psys->part->flag & PART_SELF_EFFECT)){ - epart=epsys->part; - - if((epsys->part->pd && epsys->part->pd->forcefield) - || (epsys->part->pd2 && epsys->part->pd2->forcefield)) - { - type=PSYS_EC_PARTICLE; - } - - //if(epart->type==PART_REACTOR) { - // tob=epsys->target_ob; - // if(tob==0) - // tob=ob; - // if(BLI_findlink(&tob->particlesystem,epsys->target_psys-1)==sim->psys) - // type|=PSYS_EC_REACTOR; - //} - - if(type){ - ec= MEM_callocN(sizeof(ParticleEffectorCache), "effector cache"); - ec->ob= ob; - ec->type=type; - ec->psys_nbr=i; - ec->rng = rng_new(1); - rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); - - BLI_addtail(lb, ec); - } - } - } - - } -} - -static void psys_init_effectors_recurs(ParticleSimulationData *sim, Object *ob, ListBase *listb, int level) -{ - Group *group; - GroupObject *go; - unsigned int layer= sim->ob->lay; - - if(level>MAX_DUPLI_RECUR) return; - - if(ob->lay & layer) { - if(ob->pd || ob->particlesystem.first) - add_to_effectors(sim, listb, ob); - - if(ob->dup_group) { - group= ob->dup_group; - for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(sim, go->ob, listb, level+1); - } - } -} - -static void psys_init_effectors(ParticleSimulationData *sim, Group *group) -{ - ListBase *listb= &sim->psys->effectors; - Base *base; - - listb->first=listb->last=0; - - if(group) { - GroupObject *go; - - for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(sim, go->ob, listb, 0); - } - else { - for(base = sim->scene->base.first; base; base= base->next) - psys_init_effectors_recurs(sim, base->object, listb, 0); - } -} - -void psys_end_effectors(ParticleSystem *psys) -{ - /* NOTE: - ec->ob is not valid in here anymore! - dg - */ - ParticleEffectorCache *ec = psys->effectors.first; - - for(; ec; ec= ec->next){ - if(ec->distances) - MEM_freeN(ec->distances); - - if(ec->locations) - MEM_freeN(ec->locations); - - if(ec->face_minmax) - MEM_freeN(ec->face_minmax); - - if(ec->vert_cos) - MEM_freeN(ec->vert_cos); - - if(ec->tree) - BLI_kdtree_free(ec->tree); - - if(ec->rng) - rng_free(ec->rng); - } - - BLI_freelistN(&psys->effectors); -} - -/* precalcs effectors and returns 1 if there were any collision object - * so collision checks can be avoided as quickly as possible */ -static int precalc_effectors(ParticleSimulationData *sim, float cfra) -{ - ParticleSystem *psys = sim->psys; - ListBase *lb=&psys->effectors; - ParticleEffectorCache *ec; - ParticleSettings *part=psys->part; - PARTICLE_P; - int totpart, collision = 0; - float vec2[3],loc[3],radius,*co=0; - - for(ec= lb->first; ec; ec= ec->next) { - PartDeflect *pd= ec->ob->pd; - co = NULL; - - if(ec->type==PSYS_EC_EFFECTOR && pd->forcefield==PFIELD_GUIDE && ec->ob->type==OB_CURVE - && part->phystype!=PART_PHYS_BOIDS) { - float vec[4]; - - where_on_path(ec->ob, 0.0, vec, vec2, NULL, &radius); - - Mat4MulVecfl(ec->ob->obmat,vec); - Mat4Mul3Vecfl(ec->ob->obmat,vec2); - - QUATCOPY(ec->firstloc,vec); - VECCOPY(ec->firstdir,vec2); - - /* TODO - use 'radius' to adjust the effector */ - - totpart=psys->totpart; - - if(totpart){ - ec->distances=MEM_callocN(totpart*sizeof(float),"particle distances"); - ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations"); - - LOOP_PARTICLES { - if(part->from == PART_FROM_PARTICLE) { - VECCOPY(loc, pa->fuv); - } - else - psys_particle_on_emitter(sim->psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); - - Mat4MulVecfl(sim->ob->obmat,loc); - ec->distances[p]=VecLenf(loc,vec); - VECSUB(loc,loc,vec); - VECCOPY(ec->locations+3*p,loc); - } - } - } - else if(ec->type==PSYS_EC_PARTICLE){ - ParticleSimulationData esim = {sim->scene, ec->ob, BLI_findlink(&ec->ob->particlesystem, ec->psys_nbr), NULL}; - ParticleSettings *epart = esim.psys->part; - ParticleData *epa; - int p, totepart = esim.psys->totpart; - - if(psys->part->phystype==PART_PHYS_BOIDS){ - ParticleKey state; - PartDeflect *pd; - - pd= epart->pd; - if(pd->forcefield==PFIELD_FORCE && totepart){ - KDTree *tree; - - tree=BLI_kdtree_new(totepart); - ec->tree=tree; - - for(p=0, epa=esim.psys->particles; p<totepart; p++,epa++) - if(epa->alive==PARS_ALIVE && psys_get_particle_state(&esim,p,&state,0)) - BLI_kdtree_insert(tree, p, state.co, NULL); - - BLI_kdtree_balance(tree); - } - } - - } - else if(ec->type==PSYS_EC_DEFLECT) { - CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); - if(collmd) { - collision_move_object(collmd, 1.0, 0.0); - collision = 1; - } - } - } - - return collision; -} -/* updates particle effectors and returns if any collision objects were found */ -int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc) -{ - psys_end_effectors(sim->psys); - psys_init_effectors(sim, sim->psys->part->eff_group); - return (precalc ? precalc_effectors(sim, cfra) : 0); -} -int effector_find_co(Scene *scene, float *pco, SurfaceModifierData *sur, Object *ob, PartDeflect *pd, float *co, float *nor, float *vel, int *index) +static void psys_update_effectors(ParticleSimulationData *sim) { - SurfaceModifierData *surmd = NULL; - int ret = 0; - - if(sur) - surmd = sur; - else if(pd && pd->flag&PFIELD_SURFACE) - { - surmd = (SurfaceModifierData *)modifiers_findByType ( ob, eModifierType_Surface ); - } - - if(surmd) { - /* closest point in the object surface is an effector */ - BVHTreeNearest nearest; - - nearest.index = -1; - nearest.dist = FLT_MAX; - - BLI_bvhtree_find_nearest(surmd->bvhtree->tree, pco, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree); - - if(nearest.index != -1) { - VECCOPY(co, nearest.co); - - if(nor) { - VECCOPY(nor, nearest.no); - } - - if(vel) { - MFace *mface = CDDM_get_face(surmd->dm, nearest.index); - - VECCOPY(vel, surmd->v[mface->v1].co); - VecAddf(vel, vel, surmd->v[mface->v2].co); - VecAddf(vel, vel, surmd->v[mface->v3].co); - if(mface->v4) - VecAddf(vel, vel, surmd->v[mface->v4].co); - - VecMulf(vel, mface->v4 ? 0.25f : 0.333f); - } - - if(index) - *index = nearest.index; - - ret = 1; - } - else { - co[0] = co[1] = co[2] = 0.0f; - - if(nor) - nor[0] = nor[1] = nor[2] = 0.0f; - - if(vel) - vel[0] = vel[1] = vel[2] = 0.0f; - } - } - else { - /* use center of object for distance calculus */ - VECCOPY(co, ob->obmat[3]); - - if(nor) { - VECCOPY(nor, ob->obmat[2]); - } - - if(vel) { - Object obcopy = *ob; - - VECCOPY(vel, ob->obmat[3]); - - where_is_object_time(scene, ob, scene->r.cfra - 1.0); - - VecSubf(vel, vel, ob->obmat[3]); - - *ob = obcopy; - } - } - - return ret; -} -/* calculate forces that all effectors apply to a particle*/ -void do_effectors(ParticleSimulationData *sim, int pa_no, ParticleData *pa, ParticleKey *state, float *rootco, float *force_field, float *vel,float framestep, float cfra) -{ - Object *eob; - ParticleSystem *psys = sim->psys; - ParticleSettings *epart; - ParticleData *epa; - ParticleKey estate; - PartDeflect *pd; - ListBase *lb=&psys->effectors; - ParticleEffectorCache *ec; - float distance, vec_to_part[3], pco[3], co[3]; - float falloff, charge = 0.0f, strength; - int p, face_index=-1; - - /* check all effector objects for interaction */ - if(lb->first){ - if(psys->part->pd && psys->part->pd->forcefield==PFIELD_CHARGE){ - /* Only the charge of the effected particle is used for - interaction, not fall-offs. If the fall-offs aren't the - same this will be unphysical, but for animation this - could be the wanted behavior. If you want physical - correctness the fall-off should be spherical 2.0 anyways. - */ - charge = psys->part->pd->f_strength; - } - if(psys->part->pd2 && psys->part->pd2->forcefield==PFIELD_CHARGE){ - charge += psys->part->pd2->f_strength; - } - for(ec = lb->first; ec; ec= ec->next){ - eob= ec->ob; - if(ec->type & PSYS_EC_EFFECTOR){ - pd=eob->pd; - if(psys->part->type!=PART_HAIR && psys->part->integrator) - where_is_object_time(sim->scene, eob, cfra); - - if(pd && pd->flag&PFIELD_SURFACE) { - float velocity[3]; - /* using velocity corrected location allows for easier sliding over effector surface */ - VecCopyf(velocity, state->vel); - VecMulf(velocity, psys_get_timestep(sim)); - VecAddf(pco, state->co, velocity); - } - else - VECCOPY(pco, state->co); - - effector_find_co(sim->scene, pco, NULL, eob, pd, co, NULL, NULL, &face_index); - - VecSubf(vec_to_part, state->co, co); - - distance = VecLength(vec_to_part); - - falloff=effector_falloff(pd,eob->obmat[2],vec_to_part); - - strength = pd->f_strength * psys->part->effector_weight[0] * psys->part->effector_weight[pd->forcefield]; - - if(falloff<=0.0f) - ; /* don't do anything */ - else if(pd->forcefield==PFIELD_TEXTURE) { - do_texture_effector(pd->tex, pd->tex_mode, pd->flag&PFIELD_TEX_2D, pd->tex_nabla, - pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat, - strength, falloff, force_field); - } else { - do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance, - falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part, - state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); - } - } - if(ec->type & PSYS_EC_PARTICLE){ - ParticleSimulationData esim = {sim->scene, eob, BLI_findlink(&eob->particlesystem,ec->psys_nbr), NULL}; - int totepart, i; - - epart = esim.psys->part; - pd = epart->pd; - totepart = esim.psys->totpart; - - if(totepart <= 0) - continue; - - if(pd && pd->forcefield==PFIELD_HARMONIC){ - /* every particle is mapped to only one harmonic effector particle */ - p= pa_no%esim.psys->totpart; - totepart= p+1; - } - else{ - p=0; - } - - esim.psys->lattice= psys_get_lattice(sim); - - for(; p<totepart; p++){ - /* particle skips itself as effector */ - if(esim.psys == psys && p == pa_no) continue; - - epa = esim.psys->particles + p; - estate.time = cfra; - if(psys_get_particle_state(&esim, p, &estate, 0)){ - VECSUB(vec_to_part, state->co, estate.co); - distance = VecLength(vec_to_part); - - for(i=0, pd = epart->pd; i<2; i++,pd = epart->pd2) { - if(pd==NULL || pd->forcefield==0) continue; - - falloff = effector_falloff(pd, estate.vel, vec_to_part); - - strength = pd->f_strength * psys->part->effector_weight[0] * psys->part->effector_weight[pd->forcefield]; - - if(falloff<=0.0f) - ; /* don't do anything */ - else - do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance, - falloff,epart->size,pd->f_damp,estate.vel,vec_to_part, - state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size); - } - } - else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ - /* first step after key release */ - psys_get_particle_state(&esim, p, &estate, 1); - VECADD(vel, vel, estate.vel); - /* TODO: add rotation handling here too */ - } - } - - if(esim.psys->lattice){ - end_latt_deform(esim.psys->lattice); - esim.psys->lattice= NULL; - } - } - } - } + pdEndEffectors(&sim->psys->effectors); + sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys, sim->psys->part->effector_weights); + precalc_guides(sim, sim->psys->effectors); } /************************************************/ @@ -2763,9 +2245,10 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra { ParticleSettings *part = sim->psys->part; ParticleData *pa = sim->psys->particles + p; + EffectedPoint epoint; ParticleKey states[5], tkey; float timestep = psys_get_timestep(sim); - float force[3],tvel[3],dx[4][3],dv[4][3]; + float force[3],impulse[3],dx[4][3],dv[4][3]; float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=sim->psys->cfra; int i, steps=1; @@ -2791,10 +2274,11 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra for(i=0; i<steps; i++){ force[0]=force[1]=force[2]=0.0; - tvel[0]=tvel[1]=tvel[2]=0.0; + impulse[0]=impulse[1]=impulse[2]=0.0; /* add effectors */ - if(part->type != PART_HAIR) - do_effectors(sim, p, pa, states+i, states->co, force, tvel, dfra, fra); + pd_point_from_particle(sim, pa, states+i, &epoint); + if(part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR) + pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse); /* calculate air-particle interaction */ if(part->dragfac!=0.0f){ @@ -2813,10 +2297,17 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra VecMulf(force,1.0f/pa_mass); /* add global acceleration (gravitation) */ - VECADD(force,force,part->acc); + if(sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY + /* normal gravity is too strong for hair so it's disabled by default */ + && (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) { + float gravity[3]; + VECCOPY(gravity, sim->scene->physics_settings.gravity); + VecMulf(gravity, part->effector_weights->global_gravity); + VECADD(force,force,gravity); + } /* calculate next state */ - VECADD(states[i].vel,states[i].vel,tvel); + VECADD(states[i].vel,states[i].vel,impulse); switch(part->integrator){ case PART_INT_EULER: @@ -2889,6 +2380,8 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra if(part->dampfac!=0.0) VecMulf(pa->state.vel,1.0f-part->dampfac); + VECCOPY(pa->state.ave, states->ave); + /* finally we do guides */ time=(cfra-pa->time)/pa->lifetime; CLAMP(time,0.0,1.0); @@ -2898,7 +2391,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra tkey.time=pa->state.time; if(part->type != PART_HAIR) { - if(do_guide(sim->scene, &tkey, p, time, &sim->psys->effectors)) { + if(do_guides(sim->psys->effectors, &tkey, p, time)) { VECCOPY(pa->state.co,tkey.co); /* guides don't produce valid velocity */ VECSUB(pa->state.vel,tkey.co,pa->prev_state.co); @@ -3129,7 +2622,8 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B VECCOPY(col->vel,vel); - col->ob = col->ob_t; + col->hit_ob = col->ob; + col->hit_md = col->md; } } } @@ -3146,7 +2640,8 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B VECCOPY(col->vel,vel); - col->ob = col->ob_t; + col->hit_ob = col->ob; + col->hit_md = col->md; } } } @@ -3163,13 +2658,11 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){ - Object *ob = NULL, *skip_ob = NULL; + Object *ground_ob = NULL; ParticleSettings *part = sim->psys->part; - ListBase *lb=&sim->psys->effectors; - ParticleEffectorCache *ec; - ParticleKey reaction_state; - ParticleCollision col; ParticleData *pa = sim->psys->particles + p; + ParticleCollision col; + ColliderCache *coll; BVHTreeRayHit hit; float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z = 0.0f; @@ -3185,11 +2678,11 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo BoidParticle *bpa = pa->boid; radius = pa->size; boid_z = pa->state.co[2]; - skip_ob = bpa->ground; + ground_ob = bpa->ground; } /* 10 iterations to catch multiple deflections */ - if(lb->first) while(deflections < max_deflections){ + if(sim->colliders) while(deflections < max_deflections){ /* 1. */ VECSUB(ray_dir, col.co2, col.co1); @@ -3201,32 +2694,25 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo if(hit.dist == 0.0f) hit.dist = col.ray_len = 0.000001f; - for(ec=lb->first; ec; ec=ec->next){ - if(ec->type & PSYS_EC_DEFLECT){ - ob= ec->ob; - - /* for boids: don't check with current ground object */ - if(ob==skip_ob) - continue; - - /* particles should not collide with emitter at birth */ - if(ob==sim->ob && pa->time < cfra && pa->time >= sim->psys->cfra) - continue; + for(coll = sim->colliders->first; coll; coll=coll->next){ + /* for boids: don't check with current ground object */ + if(coll->ob == ground_ob) + continue; - if(part->type!=PART_HAIR) - where_is_object_time(sim->scene, sim->ob, cfra); + /* particles should not collide with emitter at birth */ + if(coll->ob == sim->ob && pa->time < cfra && pa->time >= sim->psys->cfra) + continue; - col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); - col.ob_t = ob; + col.ob = coll->ob; + col.md = coll->collmd; - if(col.md && col.md->bvhtree) - BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); - } + if(col.md && col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); } /* 2. */ if(hit.index>=0) { - PartDeflect *pd = col.ob->pd; + PartDeflect *pd = col.hit_ob->pd; int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; float co[3]; /* point of collision */ float vec[3]; /* movement through collision */ @@ -3253,9 +2739,6 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo /* particle is dead so we don't need to calculate further */ deflections=max_deflections; - - /* store for reactors */ - copy_particle_key(&reaction_state, &pa->state, 0); } else { float nor_vec[3], tan_vec[3], tan_vel[3], vel[3]; @@ -3416,7 +2899,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra) if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) skip = 1; /* only hair, keyed and baked stuff can have paths */ - else if(part->ren_as != PART_DRAW_PATH) + else if(part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))) skip = 1; /* particle visualization must be set as path */ else if(!psys->renderdata) { if(part->draw_as != PART_DRAW_REND) @@ -3555,8 +3038,11 @@ static void do_hair_dynamics(ParticleSimulationData *sim) psys->hair_out_dm->release(psys->hair_out_dm); psys->clmd->point_cache = psys->pointcache; + psys->clmd->sim_parms->effector_weights = psys->part->effector_weights; psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, 0, 0); + + psys->clmd->sim_parms->effector_weights = NULL; } static void hair_step(ParticleSimulationData *sim, float cfra) { @@ -3586,7 +3072,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra) if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) do_hair_dynamics(sim); - psys_update_effectors(sim, cfra, 1); + psys_update_effectors(sim); psys_update_path_cache(sim, cfra); @@ -3653,7 +3139,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) BoidBrainData bbd; PARTICLE_P; float timestep; - int totpart, check_collisions = 0; + int totpart; /* current time */ float ctime, ipotime; // XXX old animation system /* frame & time changes */ @@ -3665,7 +3151,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) totpart=psys->totpart; - timestep=psys_get_timestep(sim); + timestep = psys_get_timestep(sim); dtime= dfra*timestep; ctime= cfra*timestep; ipotime= cfra; // XXX old animation system @@ -3703,15 +3189,6 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) } else{ pa->loop = 0; - if(cfra <= pa->time) - pa->alive = PARS_UNBORN; - /* without dynamics the state is allways known so no need to kill */ - else if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)){ - if(cfra < pa->dietime) - pa->alive = PARS_ALIVE; - } - else - pa->alive = PARS_KILLED; } } @@ -3721,7 +3198,10 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) else{ BLI_srandom(31415926 + (int)cfra + psys->seed); - psys_update_effectors(sim, cfra, 1); + psys_update_effectors(sim); + + if(part->type != PART_HAIR) + sim->colliders = get_collider_cache(sim->scene, NULL); if(part->phystype==PART_PHYS_BOIDS){ ParticleTarget *pt = psys->targets.first; @@ -3731,13 +3211,13 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) bbd.dfra = dfra; bbd.timestep = timestep; - update_particle_tree(psys); + psys_update_particle_tree(psys, cfra); boids_precalc_rules(part, cfra); for(; pt; pt=pt->next) { if(pt->ob) - update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1)); + psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra); } } @@ -3798,7 +3278,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) apply_particle_forces(sim, p, pa_dfra, cfra); /* deflection */ - if(check_collisions) + if(sim->colliders) deflect_particle(sim, p, pa_dfra, cfra); /* rotations */ @@ -3812,7 +3292,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) boid_body(&bbd, pa); /* deflection */ - deflect_particle(sim, p, pa_dfra, cfra); + if(sim->colliders) + deflect_particle(sim, p, pa_dfra, cfra); } break; } @@ -3837,9 +3318,9 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) //push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); } } + + free_collider_cache(&sim->colliders); } - if(psys->reactevents.first) - BLI_freelistN(&psys->reactevents); if(tree) BLI_kdtree_free(tree); @@ -3860,7 +3341,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra) if(part->from!=PART_FROM_PARTICLE) vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); - psys_update_effectors(sim, cfra, 1); + psys_update_effectors(sim); disp= (float)get_current_display_percentage(psys)/100.0f; @@ -4195,6 +3676,13 @@ static void system_step(ParticleSimulationData *sim, float cfra) else if(framenr > endframe) { framenr= endframe; } + + if(framenr == startframe) { + BKE_ptcache_id_reset(sim->scene, &pid, PTCACHE_RESET_OUTDATED); + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->flag &= ~PTCACHE_REDO_NEEDED; + } } /* verify if we need to reallocate */ @@ -4226,7 +3714,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) if(alloc) { realloc_particles(sim, totpart); - if(usecache && !only_children_changed) { + if(oldtotpart && usecache && !only_children_changed) { BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); BKE_ptcache_id_from_particles(&pid, sim->ob, psys); } @@ -4286,7 +3774,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) pa->alive = PARS_ALIVE; } } - else if(sim->ob->id.lib || (cache->flag & PTCACHE_BAKED)) { + else if(cfra != startframe && (sim->ob->id.lib || (cache->flag & PTCACHE_BAKED))) { psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; psys->recalc = 0; @@ -4383,7 +3871,7 @@ static int hair_needs_recalc(ParticleSystem *psys) /* main particle update call, checks that things are ok on the large scale before actual particle calculations */ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) { - ParticleSimulationData sim = {scene, ob, psys, NULL}; + ParticleSimulationData sim = {scene, ob, psys, NULL, NULL}; float cfra; /* drawdata is outdated after ANY change */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 3915a6901a0..bffe4566f74 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -292,6 +292,9 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f else BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + if(cfra > pa->time) + cfra1 = MAX2(cfra1, pa->time); + dfra = cfra2 - cfra1; VecMulf(keys[1].vel, dfra / frs_sec); @@ -2266,6 +2269,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) } } } + BLI_freelistN(&pidlist2); } if(bake || cache->flag & PTCACHE_REDO_NEEDED) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b3f00f884bc..4f72ca96f5f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -400,6 +400,10 @@ Scene *add_scene(char *name) sce->toolsettings->proportional_size = 1.0f; + sce->physics_settings.gravity[0] = 0.0f; + sce->physics_settings.gravity[1] = 0.0f; + sce->physics_settings.gravity[2] = -9.81f; + sce->physics_settings.flag = PHYS_GLOBAL_GRAVITY; sce->unit.scale_length = 1.0f; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 62463b3d555..4f7a8cda81b 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -832,8 +832,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) size_t i = 0; size_t index = 0; int badcell = 0; - if(pa->alive == PARS_KILLED) continue; - else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; + if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; // VECCOPY(pos, pa->state.co); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 450a64d72eb..089f2a5ebfb 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1550,11 +1550,14 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, float f,windfactor = 0.25f; /*see if we have wind*/ if(do_effector) { + EffectedPoint epoint; float speed[3]={0.0f,0.0f,0.0f}; float pos[3]; VecMidf(pos, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos); VecMidf(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec); - pdDoEffectors(scene, do_effector, pos, force, speed, (float)scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + pd_point_from_soft(scene, pos, vel, -1, &epoint); + pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed); + VecMulf(speed,windfactor); VecAddf(vel,vel,speed); } @@ -1589,14 +1592,13 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow) { SoftBody *sb = ob->soft; - ListBase *do_effector= NULL; + ListBase *do_effector = NULL; - do_effector= pdInitEffectors(scene, ob,NULL); + do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights); if (sb){ _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector); } - if(do_effector) - pdEndEffectors(do_effector); + pdEndEffectors(&do_effector); } static void *exec_scan_for_ext_spring_forces(void *data) @@ -1614,7 +1616,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow, int i, totthread,left,dec; int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ - do_effector= pdInitEffectors(scene, ob,NULL); + do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights); /* figure the number of threads while preventing pretty pointless threading overhead */ if(scene->r.mode & R_FIXED_THREADS) @@ -1661,9 +1663,8 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow, exec_scan_for_ext_spring_forces(&sb_threads[0]); /* clean up */ MEM_freeN(sb_threads); - - if(do_effector) - pdEndEffectors(do_effector); + + pdEndEffectors(&do_effector); } @@ -2226,19 +2227,22 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo /* done goal stuff */ /* gravitation */ - if (sb){ - float gravity = sb->grav * sb_grav_force_scale(ob); - bp->force[2]-= gravity*bp->mass; /* individual mass of node here */ + if (sb && scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY){ + float gravity[3]; + VECCOPY(gravity, scene->physics_settings.gravity); + VecMulf(gravity, sb_grav_force_scale(ob)*bp->mass*sb->effector_weights->global_gravity); /* individual mass of node here */ + VecAddf(bp->force, bp->force, gravity); } /* particle field & vortex */ if(do_effector) { + EffectedPoint epoint; float kd; float force[3]= {0.0f, 0.0f, 0.0f}; float speed[3]= {0.0f, 0.0f, 0.0f}; float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */ - - pdDoEffectors(scene, do_effector, bp->pos, force, speed, (float)scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint); + pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed); /* apply forcefield*/ VecMulf(force,fieldfactor* eval_sb_fric_force_scale); @@ -2341,6 +2345,7 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t left = totpoint; dec = totpoint/totthread +1; for(i=0; i<totthread; i++) { + sb_threads[i].scene = scene; sb_threads[i].ob = ob; sb_threads[i].forcetime = forcetime; sb_threads[i].timenow = timenow; @@ -2381,7 +2386,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl */ SoftBody *sb= ob->soft; /* is supposed to be there */ BodyPoint *bproot; - ListBase *do_effector; + ListBase *do_effector = NULL; float iks, gravity; float fieldfactor = -1.0f, windfactor = 0.25; int do_deflector,do_selfcollision,do_springcollision,do_aero; @@ -2401,7 +2406,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl sb_sfesf_threads_run(scene, ob, timenow,sb->totspring,NULL); /* after spring scan because it uses Effoctors too */ - do_effector= pdInitEffectors(scene, ob,NULL); + do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights); if (do_deflector) { float defforce[3]; @@ -2414,7 +2419,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow); /* finish matrix and solve */ - if(do_effector) pdEndEffectors(do_effector); + pdEndEffectors(&do_effector); } @@ -2443,8 +2448,8 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa BodyPoint *bp; BodyPoint *bproot; BodySpring *bs; - ListBase *do_effector; - float iks, ks, kd, gravity; + ListBase *do_effector = NULL; + float iks, ks, kd, gravity[3] = {0.0f,0.0f,0.0f}; float fieldfactor = -1.0f, windfactor = 0.25f; float tune = sb->ballstiff; int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero; @@ -2460,7 +2465,10 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa */ - gravity = sb->grav * sb_grav_force_scale(ob); + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY){ + VECCOPY(gravity, scene->physics_settings.gravity); + VecMulf(gravity, sb_grav_force_scale(ob)*sb->effector_weights->global_gravity); + } /* check conditions for various options */ do_deflector= query_external_colliders(scene, ob); @@ -2473,7 +2481,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow); /* after spring scan because it uses Effoctors too */ - do_effector= pdInitEffectors(scene, ob,NULL); + do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights); if (do_deflector) { float defforce[3]; @@ -2631,16 +2639,17 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa /* gravitation */ - bp->force[2]-= gravity*bp->mass; /* individual mass of node here */ + VECADDFAC(bp->force, bp->force, gravity, bp->mass); /* individual mass of node here */ /* particle field & vortex */ if(do_effector) { + EffectedPoint epoint; float force[3]= {0.0f, 0.0f, 0.0f}; float speed[3]= {0.0f, 0.0f, 0.0f}; float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */ - - pdDoEffectors(scene, do_effector, bp->pos, force, speed, (float)scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint); + pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed); /* apply forcefield*/ VecMulf(force,fieldfactor* eval_sb_fric_force_scale); @@ -2819,7 +2828,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa } /* cleanup */ #endif - if(do_effector) pdEndEffectors(do_effector); + pdEndEffectors(&do_effector); } } @@ -3635,6 +3644,9 @@ SoftBody *sbNew(Scene *scene) sb->pointcache = BKE_ptcache_add(&sb->ptcaches); + if(!sb->effector_weights) + sb->effector_weights = BKE_add_effector_weights(NULL); + return sb; } @@ -3644,6 +3656,8 @@ void sbFree(SoftBody *sb) free_softbody_intern(sb); BKE_ptcache_free_list(&sb->ptcaches); sb->pointcache = NULL; + if(sb->effector_weights) + MEM_freeN(sb->effector_weights); MEM_freeN(sb); } @@ -3684,6 +3698,9 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo BodyPoint *bp; int a; + if(!sb || !sb->bpoint) + return; + for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { /* store where goals are now */ VECCOPY(bp->origS, bp->origE); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 94478b0d235..d1da29bef70 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3044,6 +3044,10 @@ static void lib_link_particlesettings(FileData *fd, Main *main) part->dup_group = newlibadr(fd, part->id.lib, part->dup_group); part->eff_group = newlibadr(fd, part->id.lib, part->eff_group); part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob); + + if(part->effector_weights) + part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group); + if(part->boids) { BoidState *state = part->boids->states.first; BoidRule *rule; @@ -3079,6 +3083,11 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part) part->pd= newdataadr(fd, part->pd); part->pd2= newdataadr(fd, part->pd2); + if(part->effector_weights) + part->effector_weights = newdataadr(fd, part->effector_weights); + else + part->effector_weights = BKE_add_effector_weights(part->eff_group); + part->boids= newdataadr(fd, part->boids); if(part->boids) { @@ -3155,18 +3164,17 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) } - psys->child=newdataadr(fd,psys->child); - psys->effectors.first=psys->effectors.last=0; + psys->child = newdataadr(fd,psys->child); + psys->effectors = NULL; link_list(fd, &psys->targets); psys->edit = NULL; psys->free_edit = NULL; - psys->pathcache = 0; - psys->childcache = 0; - psys->pathcachebufs.first = psys->pathcachebufs.last = 0; - psys->childcachebufs.first = psys->childcachebufs.last = 0; - psys->reactevents.first = psys->reactevents.last = 0; + psys->pathcache = NULL; + psys->childcache = NULL; + psys->pathcachebufs.first = psys->pathcachebufs.last = NULL; + psys->childcachebufs.first = psys->childcachebufs.last = NULL; psys->frand = NULL; psys->pdd = NULL; @@ -3642,12 +3650,24 @@ static void lib_link_object(FileData *fd, Main *main) smd->domain->fluid_group = newlibadr_us(fd, ob->id.lib, smd->domain->fluid_group); } } + + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + + if(clmd) + { + clmd->sim_parms->effector_weights->group = newlibadr(fd, ob->id.lib, clmd->sim_parms->effector_weights->group); + } + } /* texture field */ if(ob->pd) if(ob->pd->tex) ob->pd->tex=newlibadr_us(fd, ob->id.lib, ob->pd->tex); + if(ob->soft) + ob->soft->effector_weights->group = newlibadr(fd, ob->id.lib, ob->soft->effector_weights->group); + lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem); lib_link_modifiers(fd, ob); } @@ -3727,6 +3747,11 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) if(clmd->sim_parms->presets > 10) clmd->sim_parms->presets = 0; } + + if(clmd->sim_parms->effector_weights) + clmd->sim_parms->effector_weights = newdataadr(fd, clmd->sim_parms->effector_weights); + else + clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL); } else if (md->type==eModifierType_Fluidsim) { @@ -3948,6 +3973,8 @@ static void direct_link_object(FileData *fd, Object *ob) } ob->pd= newdataadr(fd, ob->pd); + if(ob->pd) + ob->pd->rng=NULL; ob->soft= newdataadr(fd, ob->soft); if(ob->soft) { SoftBody *sb= ob->soft; @@ -3965,6 +3992,11 @@ static void direct_link_object(FileData *fd, Object *ob) } } + if(sb->effector_weights) + sb->effector_weights = newdataadr(fd, sb->effector_weights); + else + sb->effector_weights = BKE_add_effector_weights(NULL); + direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache); } ob->bsoft= newdataadr(fd, ob->bsoft); @@ -9702,6 +9734,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Object *ob; Material *ma; Tex *tex; + ParticleSettings *part; + int do_gravity = 0; for(sce = main->scene.first; sce; sce = sce->id.next) if(sce->unit.scale_length == 0.0f) @@ -9741,6 +9775,48 @@ static void do_versions(FileData *fd, Library *lib, Main *main) sce->audio.doppler_factor = 1.0; sce->audio.speed_of_sound = 343.3; } + + /* Add default gravity to scenes */ + for(sce= main->scene.first; sce; sce= sce->id.next) { + if((sce->physics_settings.flag & PHYS_GLOBAL_GRAVITY) == 0 + && VecLength(sce->physics_settings.gravity) == 0.0f) { + + sce->physics_settings.gravity[0] = sce->physics_settings.gravity[1] = 0.0f; + sce->physics_settings.gravity[2] = -9.81f; + sce->physics_settings.flag = PHYS_GLOBAL_GRAVITY; + do_gravity = 1; + } + } + + /* Assign proper global gravity weights for dynamics (only z-coordinate is taken into account) */ + if(do_gravity) for(part= main->particle.first; part; part= part->id.next) + part->effector_weights->global_gravity = part->acc[2]/-9.81f; + + for(ob = main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + + if(do_gravity) { + for(md= ob->modifiers.first; md; md= md->next) { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + clmd->sim_parms->effector_weights->global_gravity = clmd->sim_parms->gravity[2]/-9.81; + } + + if(ob->soft) + ob->soft->effector_weights->global_gravity = ob->soft->grav/9.81; + } + + /* Normal wind shape is plane */ + if(ob->pd) { + if(ob->pd->forcefield == PFIELD_WIND) + ob->pd->shape = PFIELD_SHAPE_PLANE; + + if(ob->pd->flag & PFIELD_PLANAR) + ob->pd->shape = PFIELD_SHAPE_PLANE; + else if(ob->pd->flag & PFIELD_SURFACE) + ob->pd->shape = PFIELD_SHAPE_SURFACE; + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index fda35d28d0e..52870420833 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -620,6 +620,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) if (part->adt) write_animdata(wd, part->adt); writestruct(wd, DATA, "PartDeflect", 1, part->pd); writestruct(wd, DATA, "PartDeflect", 1, part->pd2); + writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights); if(part->boids && part->phystype == PART_PHYS_BOIDS) { BoidState *state = part->boids->states.first; @@ -1140,6 +1141,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms); writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms); + writestruct(wd, DATA, "EffectorWeights", 1, clmd->sim_parms->effector_weights); write_pointcaches(wd, &clmd->ptcaches); } else if(md->type==eModifierType_Smoke) { @@ -1227,7 +1229,10 @@ static void write_objects(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "PartDeflect", 1, ob->pd); writestruct(wd, DATA, "SoftBody", 1, ob->soft); - if(ob->soft) write_pointcaches(wd, &ob->soft->ptcaches); + if(ob->soft) { + write_pointcaches(wd, &ob->soft->ptcaches); + writestruct(wd, DATA, "EffectorWeights", 1, ob->soft->effector_weights); + } writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft); write_particlesystems(wd, &ob->particlesystem); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 05905cd42a4..7188368a95f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -38,6 +38,7 @@ #include "DNA_meta_types.h" #include "DNA_object_fluidsim.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" @@ -56,6 +57,7 @@ #include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" +#include "BKE_effect.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_lattice.h" @@ -190,6 +192,90 @@ void OBJECT_OT_add(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", object_type_items, 0, "Type", ""); } +/********************* Add Effector Operator ********************/ +/* copy from rna_object_force.c*/ +static EnumPropertyItem field_type_items[] = { + {0, "NONE", 0, "None", ""}, + {PFIELD_FORCE, "FORCE", 0, "Force", ""}, + {PFIELD_WIND, "WIND", 0, "Wind", ""}, + {PFIELD_VORTEX, "VORTEX", 0, "Vortex", ""}, + {PFIELD_MAGNET, "MAGNET", 0, "Magnetic", ""}, + {PFIELD_HARMONIC, "HARMONIC", 0, "Harmonic", ""}, + {PFIELD_CHARGE, "CHARGE", 0, "Charge", ""}, + {PFIELD_LENNARDJ, "LENNARDJ", 0, "Lennard-Jones", ""}, + {PFIELD_TEXTURE, "TEXTURE", 0, "Texture", ""}, + {PFIELD_GUIDE, "GUIDE", 0, "Curve Guide", ""}, + {PFIELD_BOID, "BOID", 0, "Boid", ""}, + {PFIELD_TURBULENCE, "TURBULENCE", 0, "Turbulence", ""}, + {PFIELD_DRAG, "DRAG", 0, "Drag", ""}, + {0, NULL, 0, NULL, NULL}}; + +void add_effector_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menus, only non-editmode stuff */ +{ + /* keep here to get things compile, remove later */ +} + +/* for effector add primitive operators */ +static Object *effector_add_type(bContext *C, int type) +{ + Scene *scene= CTX_data_scene(C); + Object *ob; + + /* for as long scene has editmode... */ + if (CTX_data_edit_object(C)) + ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */ + + /* deselects all, sets scene->basact */ + if(type==PFIELD_GUIDE) { + ob = add_object(scene, OB_CURVE); + ((Curve*)ob->data)->flag |= CU_PATH|CU_3D; + ED_object_enter_editmode(C, 0); + BLI_addtail(curve_get_editcurve(ob), add_nurbs_primitive(C, CU_NURBS|CU_PRIM_PATH, 1)); + ED_object_exit_editmode(C, EM_FREEDATA); + } + else + ob= add_object(scene, OB_EMPTY); + + ob->pd= object_add_collision_fields(type); + + /* editor level activate, notifiers */ + ED_base_object_activate(C, BASACT); + + /* more editor stuff */ + ED_object_base_init_from_view(C, BASACT); + + DAG_scene_sort(scene); + + return ob; +} + +/* for object add operator */ +static int effector_add_exec(bContext *C, wmOperator *op) +{ + effector_add_type(C, RNA_int_get(op->ptr, "type")); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_effector_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Effector"; + ot->description = "Add an empty object with a physics effector to the scene."; + ot->idname= "OBJECT_OT_effector_add"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= effector_add_exec; + + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", ""); +} + /* ***************** add primitives *************** */ /* ****** work both in and outside editmode ****** */ @@ -616,6 +702,8 @@ static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *eve uiItemS(layout); uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_CAMERA, "OBJECT_OT_add", "type", OB_CAMERA); uiItemMenuEnumO(layout, "Lamp", ICON_OUTLINER_OB_LAMP, "OBJECT_OT_lamp_add", "type"); + uiItemS(layout); + uiItemMenuEnumO(layout, "Force Field", ICON_OUTLINER_OB_EMPTY, "OBJECT_OT_effector_add", "type"); uiPupMenuEnd(C, pup); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index ee0b043a9a1..54df3ae92da 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -346,6 +346,7 @@ void ED_object_exit_editmode(bContext *C, int flag) if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ pid->cache->flag |= PTCACHE_OUTDATED; } + BLI_freelistN(&pidlist); BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index c5499ef8f5d..474715c593b 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -91,6 +91,7 @@ void OBJECT_OT_text_add(struct wmOperatorType *ot); void OBJECT_OT_armature_add(struct wmOperatorType *ot); void OBJECT_OT_lamp_add(struct wmOperatorType *ot); void OBJECT_OT_primitive_add(struct wmOperatorType *ot); /* only used as menu */ +void OBJECT_OT_effector_add(struct wmOperatorType *ot); void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot); void OBJECT_OT_duplicate(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index cc8cc420bf7..7f0f1876417 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -110,7 +110,7 @@ int ED_object_modifier_add(ReportList *reports, Scene *scene, Object *ob, int ty } else if(type == eModifierType_Collision) { if(!ob->pd) - ob->pd= object_add_collision_fields(); + ob->pd= object_add_collision_fields(0); ob->pd->deflect= 1; DAG_scene_sort(scene); @@ -159,8 +159,8 @@ int ED_object_modifier_remove(ReportList *reports, Scene *scene, Object *ob, Mod DAG_scene_sort(scene); } else if(md->type == eModifierType_Surface) { - if(ob->pd) - ob->pd->flag &= ~PFIELD_SURFACE; + if(ob->pd && ob->pd->shape == PFIELD_SHAPE_SURFACE) + ob->pd->shape = PFIELD_SHAPE_PLANE; DAG_scene_sort(scene); } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 3f975d1e807..9bfd6a4201c 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -117,6 +117,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_armature_add); WM_operatortype_append(OBJECT_OT_lamp_add); WM_operatortype_append(OBJECT_OT_add); + WM_operatortype_append(OBJECT_OT_effector_add); WM_operatortype_append(OBJECT_OT_primitive_add); WM_operatortype_append(OBJECT_OT_mesh_add); WM_operatortype_append(OBJECT_OT_metaball_add); diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c index 47d073e2dbb..0b63f1a98ff 100644 --- a/source/blender/editors/physics/particle_boids.c +++ b/source/blender/editors/physics/particle_boids.c @@ -78,7 +78,7 @@ static int rule_add_exec(bContext *C, wmOperator *op) BLI_addtail(&state->rules, rule); - psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET); + DAG_id_flush_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); return OPERATOR_FINISHED; @@ -129,7 +129,7 @@ static int rule_del_exec(bContext *C, wmOperator *op) rule->flag |= BOIDRULE_CURRENT; DAG_scene_sort(scene); - psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET); + DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); @@ -168,7 +168,7 @@ static int rule_move_up_exec(bContext *C, wmOperator *op) BLI_remlink(&state->rules, rule); BLI_insertlink(&state->rules, rule->prev->prev, rule); - psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET); + DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); break; } @@ -207,7 +207,7 @@ static int rule_move_down_exec(bContext *C, wmOperator *op) BLI_remlink(&state->rules, rule); BLI_insertlink(&state->rules, rule->next, rule); - psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET); + DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); break; } @@ -303,7 +303,7 @@ static int state_del_exec(bContext *C, wmOperator *op) state->flag |= BOIDSTATE_CURRENT; DAG_scene_sort(scene); - psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET); + DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); @@ -378,7 +378,7 @@ static int state_move_down_exec(bContext *C, wmOperator *op) if(state->flag & BOIDSTATE_CURRENT && state->next) { BLI_remlink(&boids->states, state); BLI_insertlink(&boids->states, state->next, state); - psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET); + DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET); break; } } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 60ae91e7a89..db3b7130ab3 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3159,9 +3159,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv ma_g = ma->g; ma_b = ma->b; - pdd->ma_r = &ma_r; - pdd->ma_g = &ma_g; - pdd->ma_b = &ma_b; + if(pdd) { + pdd->ma_r = &ma_r; + pdd->ma_g = &ma_g; + pdd->ma_b = &ma_b; + } create_cdata = 1; } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 8d709d1b38a..f6d30a7bec9 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4848,6 +4848,7 @@ void special_aftertrans_update(TransInfo *t) if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ pid->cache->flag |= PTCACHE_OUTDATED; } + BLI_freelistN(&pidlist); /* pointcache refresh */ if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 5cfecf7cc01..9423e871c77 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -79,6 +79,8 @@ typedef struct ClothSimSettings short vgroup_struct; /* vertex group for scaling structural stiffness */ short presets; /* used for presets on GUI */ short pad; + + struct EffectorWeights *effector_weights; } ClothSimSettings; diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 468ad35de85..e7e785e605b 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -35,47 +35,91 @@ extern "C" { #endif #include "DNA_listBase.h" + +/* pd->forcefield: Effector Fields types */ +typedef enum PFieldType { + PFIELD_NULL = 0, /* (this is used for general effector weight) */ + PFIELD_FORCE, /* Force away/towards a point depending on force strength */ + PFIELD_VORTEX, /* Force around the effector normal */ + PFIELD_MAGNET, /* Force from the cross product of effector normal and point velocity */ + PFIELD_WIND, /* Force away and towards a point depending which side of the effector */ + /* normal the point is */ + PFIELD_GUIDE, /* Force along curve for dynamics, a shaping curve for hair paths */ + PFIELD_TEXTURE, /* Force based on texture values calculated at point coordinates */ + PFIELD_HARMONIC, /* Force of a harmonic (damped) oscillator */ + PFIELD_CHARGE, /* Force away/towards a point depending on point charge */ + PFIELD_LENNARDJ, /* Force due to a Lennard-Jones potential */ + PFIELD_BOID, /* Defines predator / goal for boids */ + PFIELD_TURBULENCE, /* Force defined by BLI_gTurbulence */ + PFIELD_DRAG, /* Linear & quadratic drag */ + NUM_PFIELD_TYPES +} PFieldType; typedef struct PartDeflect { - short deflect; /* Deflection flag - does mesh deflect particles*/ - short forcefield; /* Force field type, do the vertices attract / repel particles ? */ - short flag; /* general settings flag */ - short falloff; /* fall-off type*/ + short deflect; /* Deflection flag - does mesh deflect particles */ + short forcefield; /* Force field type, do the vertices attract / repel particles? */ + short flag; /* general settings flag */ + short falloff; /* fall-off type */ + short shape; /* point, plane or surface */ + short tex_mode; /* texture effector */ + short kink, kink_axis; /* for curve guide */ + short zdir, rt; + /* Main effector values */ + float f_strength; /* The strength of the force (+ or - ) */ + float f_damp; /* Damping ratio of the harmonic effector. */ + float f_flow; /* How much force is converted into "air flow", i.e. */ + /* force used as the velocity of surrounding medium. */ + + float f_size; + + /* fall-off */ + float f_power; /* The power law - real gravitation is 2 (square) */ + float maxdist; /* if indicated, use this maximum */ + float mindist; /* if indicated, use this minimum */ + float f_power_r; /* radial fall-off power */ + float maxrad; /* radial versions of above */ + float minrad; + + /* particle collisions */ float pdef_damp; /* Damping factor for particle deflection */ float pdef_rdamp; /* Random element of damping for deflection */ float pdef_perm; /* Chance of particle passing through mesh */ float pdef_frict; /* Friction factor for particle deflection */ float pdef_rfrict; /* Random element of friction for deflection */ - float f_strength; /* The strength of the force (+ or - ) */ - float f_power; /* The power law - real gravitation is 2 (square) */ - float f_dist; - float f_damp; /* The dampening factor, currently only for harmonic force */ - float maxdist; /* if indicated, use this maximum */ - float mindist; /* if indicated, use this minimum */ - float maxrad; /* radial versions of above */ - float minrad; - float f_power_r; /* radial fall-off power*/ + float absorption, pad; /* used for forces */ + /* softbody collisions */ float pdef_sbdamp; /* Damping factor for softbody deflection */ float pdef_sbift; /* inner face thickness for softbody deflection */ float pdef_sboft; /* outer face thickness for softbody deflection */ - float absorption, pad; /* used for forces */ - - /* variables for guide curve */ + /* guide curve, same as for particle child effects */ float clump_fac, clump_pow; float kink_freq, kink_shape, kink_amp, free_end; - float tex_nabla; - short tex_mode, kink, kink_axis, rt2; - struct Tex *tex; /* Texture of the texture effector */ - struct RNG *rng; /* random noise generator for e.g. wind */ - float f_noise; /* noise of force (currently used for wind) */ - int seed; /* wind noise random seed */ + /* texture effector */ + float tex_nabla; /* Used for calculating partial derivatives */ + struct Tex *tex; /* Texture of the texture effector */ + + /* effector noise */ + struct RNG *rng; /* random noise generator for e.g. wind */ + float f_noise; /* noise of force */ + int seed; /* noise random seed */ } PartDeflect; +typedef struct EffectorWeights { + struct Group *group; /* only use effectors from this group of objects */ + + float weight[13]; /* effector type specific weights */ + float global_gravity; + short flag, rt[3]; +} EffectorWeights; + +/* EffectorWeights->flag */ +#define EFF_WEIGHT_DO_HAIR 1 + /* Point cache file data types: * - used as (1<<flag) so poke jahka if you reach the limit of 15 * - to add new data types update: @@ -256,48 +300,51 @@ typedef struct SoftBody { struct PointCache *pointcache; struct ListBase ptcaches; -} SoftBody; + struct EffectorWeights *effector_weights; -/* pd->forcefield: Effector Fields types */ -#define PFIELD_FORCE 1 -#define PFIELD_VORTEX 2 -#define PFIELD_MAGNET 3 -#define PFIELD_WIND 4 -#define PFIELD_GUIDE 5 -#define PFIELD_TEXTURE 6 -#define PFIELD_HARMONIC 7 -#define PFIELD_CHARGE 8 -#define PFIELD_LENNARDJ 9 -#define PFIELD_BOID 10 +} SoftBody; /* pd->flag: various settings */ #define PFIELD_USEMAX 1 #define PDEFLE_DEFORM 2 -#define PFIELD_GUIDE_PATH_ADD 4 -#define PFIELD_PLANAR 8 +#define PFIELD_GUIDE_PATH_ADD 4 /* TODO: do_versions for below */ +#define PFIELD_PLANAR 8 /* used for do_versions */ #define PDEFLE_KILL_PART 16 -#define PFIELD_POSZ 32 +#define PFIELD_POSZ 32 /* used for do_versions */ #define PFIELD_TEX_OBJECT 64 +#define PFIELD_GLOBAL_CO 64 /* used for turbulence */ #define PFIELD_TEX_2D 128 #define PFIELD_USEMIN 256 #define PFIELD_USEMAXR 512 #define PFIELD_USEMINR 1024 #define PFIELD_TEX_ROOTCO 2048 -#define PFIELD_SURFACE 4096 +#define PFIELD_SURFACE (1<<12) /* used for do_versions */ +#define PFIELD_VISIBILITY (1<<13) +#define PFIELD_DO_LOCATION (1<<14) +#define PFIELD_DO_ROTATION (1<<15) /* pd->falloff */ #define PFIELD_FALL_SPHERE 0 #define PFIELD_FALL_TUBE 1 #define PFIELD_FALL_CONE 2 -//reserved for near future -//#define PFIELD_FALL_INSIDE 3 + +/* pd->shape */ +#define PFIELD_SHAPE_POINT 0 +#define PFIELD_SHAPE_PLANE 1 +#define PFIELD_SHAPE_SURFACE 2 +#define PFIELD_SHAPE_POINTS 3 /* pd->tex_mode */ #define PFIELD_TEX_RGB 0 #define PFIELD_TEX_GRAD 1 #define PFIELD_TEX_CURL 2 +/* pd->zdir */ +#define PFIELD_Z_BOTH 0 +#define PFIELD_Z_POS 1 +#define PFIELD_Z_NEG 2 + /* pointcache->flag */ #define PTCACHE_BAKED 1 #define PTCACHE_OUTDATED 2 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 089c1c76bcf..4c620ae527e 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -114,6 +114,8 @@ typedef struct ParticleSettings { struct BoidSettings *boids; + struct EffectorWeights *effector_weights; + int flag; short type, from, distr; /* physics modes */ @@ -176,10 +178,8 @@ typedef struct ParticleSettings { /* keyed particles */ int keyed_loops; - float effector_weight[10]; - struct Group *dup_group; - struct Group *eff_group; + struct Group *eff_group; // deprecated struct Object *dup_ob; struct Object *bb_ob; struct Ipo *ipo; // xxx depreceated... old animation system @@ -209,8 +209,6 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in struct Object *lattice; struct Object *parent; /* particles from global space -> parent space */ - struct ListBase effectors, reactevents; /* runtime */ - struct ListBase targets; /* used for keyed and boid physics */ char name[32]; /* particle system name */ @@ -233,6 +231,8 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in struct PointCache *pointcache; struct ListBase ptcaches; + struct ListBase *effectors; + struct KDTree *tree; /* used for interactions with self and other systems */ struct ParticleDrawData *pdd; @@ -270,7 +270,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PART_ROT_DYN (1<<14) /* dynamic rotation */ #define PART_SIZEMASS (1<<16) -//#define PART_KEYED_TIMING (1<<15) +//#define PART_HAIR_GRAVITY (1<<15) //#define PART_ABS_TIME (1<<17) //#define PART_GLOB_TIME (1<<18) @@ -407,11 +407,13 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PART_CHILD_FACES 2 /* psys->recalc */ -#define PSYS_RECALC_REDO 1 /* only do pathcache etc */ -#define PSYS_RECALC_RESET 2 /* reset everything including pointcache */ -#define PSYS_RECALC_TYPE 4 /* handle system type change */ -#define PSYS_RECALC_CHILD 16 /* only child settings changed */ -#define PSYS_RECALC_PHYS 32 /* physics type changed */ +/* starts from 8 so that the first bits can be ob->recalc */ +#define PSYS_RECALC_REDO 8 /* only do pathcache etc */ +#define PSYS_RECALC_RESET 16 /* reset everything including pointcache */ +#define PSYS_RECALC_TYPE 32 /* handle system type change */ +#define PSYS_RECALC_CHILD 64 /* only child settings changed */ +#define PSYS_RECALC_PHYS 128 /* physics type changed */ +#define PSYS_RECALC 248 /* psys->flag */ #define PSYS_CURRENT 1 @@ -436,7 +438,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PARS_REKEY 8 /* pars->alive */ -#define PARS_KILLED 0 +//#define PARS_KILLED 0 /* deprecated */ #define PARS_DEAD 1 #define PARS_UNBORN 2 #define PARS_ALIVE 3 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 5521f0e9315..c5691b47157 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -667,6 +667,11 @@ typedef struct UnitSettings { short flag; /* imperial, metric etc */ } UnitSettings; +typedef struct PhysicsSettings { + float gravity[3]; + int flag; +} PhysicsSettings; + typedef struct Scene { ID id; struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */ @@ -731,6 +736,9 @@ typedef struct Scene { /* Grease Pencil */ struct bGPdata *gpd; + + /* Physics simulation settings */ + struct PhysicsSettings physics_settings; } Scene; @@ -1127,6 +1135,9 @@ typedef enum SculptFlags { #define SK_RETARGET_ROLL_VIEW 1 #define SK_RETARGET_ROLL_JOINT 2 +/* physics_settings->flag */ +#define PHYS_GLOBAL_GRAVITY 1 + /* UnitSettings */ /* UnitSettings->system */ diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 8002aa89313..36a648c8a82 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -74,44 +74,33 @@ EnumPropertyItem boidruleset_type_items[] ={ static void rna_Boids_reset(bContext *C, PointerRNA *ptr) { - Scene *scene = CTX_data_scene(C); - ParticleSettings *part; - if(ptr->type==&RNA_ParticleSystem) { ParticleSystem *psys = (ParticleSystem*)ptr->data; - Object *ob = psys_find_object(scene, psys); psys->recalc = PSYS_RECALC_RESET; - if(ob) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - else { - part = ptr->id.data; - psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET); + DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA); } + else + DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); } static void rna_Boids_reset_deps(bContext *C, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); - ParticleSettings *part; if(ptr->type==&RNA_ParticleSystem) { ParticleSystem *psys = (ParticleSystem*)ptr->data; - Object *ob = psys_find_object(scene, psys); psys->recalc = PSYS_RECALC_RESET; - if(ob) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - else { - part = ptr->id.data; - psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET); - DAG_scene_sort(scene); + DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA); } + else + DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET); + + DAG_scene_sort(scene); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); } diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 22cc2e2c9c3..d64e2c7119b 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -306,6 +306,11 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bending Stiffness Vertex Group", "Vertex group for fine control over bending stiffness."); RNA_def_property_update(prop, 0, "rna_cloth_update"); + prop= RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "EffectorWeights"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Effector Weights", ""); + /* unused */ /* unused still diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index a2b4d6d7335..afc82016502 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -741,7 +741,7 @@ static PointerRNA rna_Object_field_get(PointerRNA *ptr) /* weak */ if(!ob->pd) - ob->pd= object_add_collision_fields(); + ob->pd= object_add_collision_fields(0); return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, ob->pd); } @@ -752,7 +752,7 @@ static PointerRNA rna_Object_collision_get(PointerRNA *ptr) /* weak */ if(!ob->pd) - ob->pd= object_add_collision_fields(); + ob->pd= object_add_collision_fields(0); return rna_pointer_inherit_refine(ptr, &RNA_CollisionSettings, ob->pd); } diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 1f0d01ce784..652a80a24eb 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -31,11 +31,40 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" +#include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "WM_api.h" #include "WM_types.h" +EnumPropertyItem effector_shape_items[] = { + {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, + {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""}, + {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface", ""}, + {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point", ""}, + {0, NULL, 0, NULL, NULL} +}; + +EnumPropertyItem empty_shape_items[] = { + {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, + {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""}, + {0, NULL, 0, NULL, NULL} +}; + +EnumPropertyItem vortex_shape_items[] = { + {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""}, + {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""}, + {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface falloff (New)", ""}, + {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point (New)", ""}, + {0, NULL, 0, NULL, NULL} +}; + +EnumPropertyItem empty_vortex_shape_items[] = { + {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""}, + {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME #include "MEM_guardedalloc.h" @@ -358,65 +387,115 @@ static void rna_SoftBodySettings_goal_vgroup_set(PointerRNA *ptr, const char *va rna_object_vgroup_name_index_set(ptr, value, &sb->vertgroup); } +static int particle_field_check(PointerRNA *ptr) +{ + ID *id= ptr->id.data; + + return (GS(id->name) == ID_PA); +} static void rna_FieldSettings_update(bContext *C, PointerRNA *ptr) { - Object *ob= (Object*)ptr->id.data; + if(particle_field_check(ptr)) { + ParticleSettings *part = (ParticleSettings*)ptr->id.data; + + if(part->pd->forcefield != PFIELD_TEXTURE && part->pd->tex) { + part->pd->tex->id.us--; + part->pd->tex= 0; + } + + if(part->pd2->forcefield != PFIELD_TEXTURE && part->pd2->tex) { + part->pd2->tex->id.us--; + part->pd2->tex= 0; + } + + DAG_id_flush_update(&part->id, OB_RECALC|PSYS_RECALC_RESET); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL); - if(ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) { - ob->pd->tex->id.us--; - ob->pd->tex= 0; } + else { + Object *ob = (Object*)ptr->id.data; - DAG_id_flush_update(&ob->id, OB_RECALC_OB); - WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + if(ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) { + ob->pd->tex->id.us--; + ob->pd->tex= 0; + } + + DAG_id_flush_update(&ob->id, OB_RECALC_OB); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + } } -static void rna_FieldSettings_surface_update(bContext *C, PointerRNA *ptr) +static void rna_FieldSettings_shape_update(bContext *C, PointerRNA *ptr) { Scene *scene= CTX_data_scene(C); - Object *ob= (Object*)ptr->id.data; - PartDeflect *pd= ob->pd; - ModifierData *md= modifiers_findByType(ob, eModifierType_Surface); - /* add/remove modifier as needed */ - if(!md) { - if(pd && (pd->flag & PFIELD_SURFACE)) - if(ELEM6(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ,PFIELD_BOID)) + if(!particle_field_check(ptr)) { + Object *ob= (Object*)ptr->id.data; + PartDeflect *pd= ob->pd; + ModifierData *md= modifiers_findByType(ob, eModifierType_Surface); + + /* add/remove modifier as needed */ + if(!md) { + if(pd && (pd->shape == PFIELD_SHAPE_SURFACE) && ELEM(pd->forcefield,PFIELD_GUIDE,PFIELD_TEXTURE)==0) if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) ED_object_modifier_add(NULL, scene, ob, eModifierType_Surface); - } - else { - if(!pd || !(pd->flag & PFIELD_SURFACE)) - ED_object_modifier_remove(NULL, scene, ob, md); - } + } + else { + if(!pd || pd->shape != PFIELD_SHAPE_SURFACE) + ED_object_modifier_remove(NULL, scene, ob, md); + } - WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + } } static void rna_FieldSettings_dependency_update(bContext *C, PointerRNA *ptr) { Scene *scene= CTX_data_scene(C); - Object *ob= (Object*)ptr->id.data; - /* do this before scene sort, that one checks for CU_PATH */ - /* XXX if(ob->type==OB_CURVE && ob->pd->forcefield==PFIELD_GUIDE) { - Curve *cu= ob->data; - cu->flag |= (CU_PATH|CU_3D); - do_curvebuts(B_CU3D); // all curves too - }*/ + if(particle_field_check(ptr)) { + DAG_id_flush_update((ID*)ptr->id.data, OB_RECALC|PSYS_RECALC_RESET); + } + else { + Object *ob= (Object*)ptr->id.data; - rna_FieldSettings_surface_update(C, ptr); + /* do this before scene sort, that one checks for CU_PATH */ + /* XXX if(ob->type==OB_CURVE && ob->pd->forcefield==PFIELD_GUIDE) { + Curve *cu= ob->data; + cu->flag |= (CU_PATH|CU_3D); + do_curvebuts(B_CU3D); // all curves too + }*/ - DAG_scene_sort(scene); + rna_FieldSettings_shape_update(C, ptr); - if(ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE) - DAG_id_flush_update(&ob->id, OB_RECALC); - else - DAG_id_flush_update(&ob->id, OB_RECALC_OB); + DAG_scene_sort(scene); - WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + if(ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE) + DAG_id_flush_update(&ob->id, OB_RECALC); + else + DAG_id_flush_update(&ob->id, OB_RECALC_OB); + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + } +} + +static void rna_EffectorWeight_update(bContext *C, PointerRNA *ptr) +{ + DAG_id_flush_update((ID*)ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET); + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL); } +static void rna_EffectorWeight_dependency_update(bContext *C, PointerRNA *ptr) +{ + Scene *scene= CTX_data_scene(C); + + DAG_scene_sort(scene); + + DAG_id_flush_update((ID*)ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET); + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL); +} static void rna_CollisionSettings_dependency_update(bContext *C, PointerRNA *ptr) { Scene *scene= CTX_data_scene(C); @@ -448,6 +527,47 @@ static void rna_softbody_update(bContext *C, PointerRNA *ptr) WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); } + +static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr, int *free) +{ + Object *ob= NULL; + + if(C==NULL) { + EnumPropertyItem *item= NULL; + int totitem= 0; + + /* needed for doc generation */ + RNA_enum_items_add(&item, &totitem, effector_shape_items); + RNA_enum_items_add(&item, &totitem, empty_shape_items); + RNA_enum_items_add(&item, &totitem, vortex_shape_items); + RNA_enum_items_add(&item, &totitem, empty_shape_items); + RNA_enum_item_end(&item, &totitem); + + *free= 1; + + return item; + } + + if(particle_field_check(ptr)) + return empty_shape_items; + + ob= (Object*)ptr->id.data; + + if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) { + if(ob->pd->forcefield == PFIELD_VORTEX) + return vortex_shape_items; + + return effector_shape_items; + } + else { + if(ob->pd->forcefield == PFIELD_VORTEX) + return empty_vortex_shape_items; + + return empty_shape_items; + } +} + + #else static void rna_def_pointcache(BlenderRNA *brna) @@ -625,6 +745,129 @@ static void rna_def_collision(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); } +static void rna_def_effector_weight(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "EffectorWeights", NULL); + RNA_def_struct_ui_text(srna, "Effector Weights", "Effector weights for physics simulation."); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); + + /* Flags */ + prop= RNA_def_property(srna, "do_growing_hair", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", EFF_WEIGHT_DO_HAIR); + RNA_def_property_ui_text(prop, "Use For Growing Hair", "Use force fields when growing hair."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + /* General */ + prop= RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "group"); + RNA_def_property_struct_type(prop, "Group"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this Group."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_dependency_update"); + + prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "global_gravity"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Gravity", "Global gravity weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + /* Effector weights */ + prop= RNA_def_property(srna, "all", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[0]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "All", "All effector's weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "spherical", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[1]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "vortex", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[2]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Vortex", "Vortex effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "magnetic", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[3]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Magnetic", "Magnetic effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "wind", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[4]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Wind", "Wind effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "curveguide", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[5]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Curve Guide", "Curve guide effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "texture", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[6]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Texture", "Texture effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "harmonic", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[7]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Harmonic", "Harmonic effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "charge", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[8]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Charge", "Charge effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "lennardjones", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[9]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Lennard-Jones", "Lennard-Jones effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "boid", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[10]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Boid", "Boid effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "turbulence", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[11]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Turbulence", "Turbulence effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop= RNA_def_property(srna, "drag", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[12]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Drag", "Drag effector weight."); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); +} + static void rna_def_field(BlenderRNA *brna) { StructRNA *srna; @@ -632,18 +875,20 @@ static void rna_def_field(BlenderRNA *brna) static EnumPropertyItem field_type_items[] = { {0, "NONE", 0, "None", ""}, - {PFIELD_FORCE, "SPHERICAL", 0, "Spherical", ""}, + {PFIELD_FORCE, "FORCE", 0, "Force", ""}, + {PFIELD_WIND, "WIND", 0, "Wind", ""}, {PFIELD_VORTEX, "VORTEX", 0, "Vortex", ""}, {PFIELD_MAGNET, "MAGNET", 0, "Magnetic", ""}, - {PFIELD_WIND, "WIND", 0, "Wind", ""}, - {PFIELD_GUIDE, "GUIDE", 0, "Curve Guide", ""}, - {PFIELD_TEXTURE, "TEXTURE", 0, "Texture", ""}, {PFIELD_HARMONIC, "HARMONIC", 0, "Harmonic", ""}, {PFIELD_CHARGE, "CHARGE", 0, "Charge", ""}, {PFIELD_LENNARDJ, "LENNARDJ", 0, "Lennard-Jones", ""}, + {PFIELD_TEXTURE, "TEXTURE", 0, "Texture", ""}, + {PFIELD_GUIDE, "GUIDE", 0, "Curve Guide", ""}, {PFIELD_BOID, "BOID", 0, "Boid", ""}, + {PFIELD_TURBULENCE, "TURBULENCE", 0, "Turbulence", ""}, + {PFIELD_DRAG, "DRAG", 0, "Drag", ""}, {0, NULL, 0, NULL, NULL}}; - + static EnumPropertyItem falloff_items[] = { {PFIELD_FALL_SPHERE, "SPHERE", 0, "Sphere", ""}, {PFIELD_FALL_TUBE, "TUBE", 0, "Tube", ""}, @@ -656,6 +901,12 @@ static void rna_def_field(BlenderRNA *brna) {PFIELD_TEX_CURL, "CURL", 0, "Curl", ""}, {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem zdirection_items[] = { + {PFIELD_Z_BOTH, "BOTH", 0, "Both Z", ""}, + {PFIELD_Z_POS, "POSITIVE", 0, "+Z", ""}, + {PFIELD_Z_NEG, "NEGATIVE", 0, "-Z", ""}, + {0, NULL, 0, NULL, NULL}}; + srna= RNA_def_struct(brna, "FieldSettings", NULL); RNA_def_struct_sdna(srna, "PartDeflect"); RNA_def_struct_ui_text(srna, "Field Settings", "Field settings for an object in physics simulation."); @@ -668,6 +919,12 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_enum_items(prop, field_type_items); RNA_def_property_ui_text(prop, "Type", "Type of field."); RNA_def_property_update(prop, 0, "rna_FieldSettings_dependency_update"); + + prop= RNA_def_property(srna, "shape", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, effector_shape_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Effector_shape_itemf"); + RNA_def_property_ui_text(prop, "Shape", "Which direction is used to calculate the effector force."); + RNA_def_property_update(prop, 0, "rna_FieldSettings_shape_update"); prop= RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "falloff"); @@ -680,6 +937,12 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_enum_items(prop, texture_items); RNA_def_property_ui_text(prop, "Texture Mode", "How the texture effect is calculated (RGB & Curl need a RGB texture else Gradient will be used instead)"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "z_direction", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "zdir"); + RNA_def_property_enum_items(prop, zdirection_items); + RNA_def_property_ui_text(prop, "Z Direction", "Effect in full or only positive/negative Z direction."); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); /* Float */ @@ -688,18 +951,51 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Strength", "Strength of force field"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - - prop= RNA_def_property(srna, "falloff_power", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "f_power"); - RNA_def_property_range(prop, 0.0f, 10.0f); - RNA_def_property_ui_text(prop, "Falloff Power", "Falloff power (real gravitational falloff = 2)"); + + /* different ui range to above */ + prop= RNA_def_property(srna, "linear_drag", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f_strength"); + RNA_def_property_range(prop, -2.0f, 2.0f); + RNA_def_property_ui_text(prop, "Linear Drag", "Drag component proportional to velocity."); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop= RNA_def_property(srna, "harmonic_damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f_damp"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Harmonic Damping", "Damping of the harmonic force"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + /* different ui range to above */ + prop= RNA_def_property(srna, "quadratic_drag", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f_damp"); + RNA_def_property_range(prop, -2.0f, 2.0f); + RNA_def_property_ui_text(prop, "Quadratic Drag", "Drag component proportional to the square of velocity."); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "flow", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f_flow"); + RNA_def_property_range(prop, 0.0f, 10.0f); + RNA_def_property_ui_text(prop, "Flow", "Convert effector force into air flow velocity"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + /* different ui range to above */ + prop= RNA_def_property(srna, "inflow", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f_flow"); + RNA_def_property_range(prop, -10.0f, 10.0f); + RNA_def_property_ui_text(prop, "Inflow", "Inwards component of the vortex force"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f_size"); + RNA_def_property_range(prop, 0.0f, 10.0f); + RNA_def_property_ui_text(prop, "Size", "Size of the noise"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "falloff_power", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f_power"); + RNA_def_property_range(prop, 0.0f, 10.0f); + RNA_def_property_ui_text(prop, "Falloff Power", "Falloff power (real gravitational falloff = 2)"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); prop= RNA_def_property(srna, "minimum_distance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "mindist"); @@ -776,26 +1072,16 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_GUIDE_PATH_ADD); RNA_def_property_ui_text(prop, "Additive", "Based on distance/falloff it adds a portion of the entire path"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - - prop= RNA_def_property(srna, "planar", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_PLANAR); - RNA_def_property_ui_text(prop, "Planar", "Create planar field"); - RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - - prop= RNA_def_property(srna, "surface", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_SURFACE); - RNA_def_property_ui_text(prop, "Surface", "Use closest point on surface"); - RNA_def_property_update(prop, 0, "rna_FieldSettings_surface_update"); - - prop= RNA_def_property(srna, "positive_z", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_POSZ); - RNA_def_property_ui_text(prop, "Positive", "Effect only in direction of positive Z axis"); - RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); - + prop= RNA_def_property(srna, "use_coordinates", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_TEX_OBJECT); RNA_def_property_ui_text(prop, "Use Coordinates", "Use object/global coordinates for texture"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "global_coordinates", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_GLOBAL_CO); + RNA_def_property_ui_text(prop, "Use Global Coordinates", "Use effector/global coordinates for turbulence"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); prop= RNA_def_property(srna, "force_2d", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_TEX_2D); @@ -806,6 +1092,16 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_TEX_ROOTCO); RNA_def_property_ui_text(prop, "Root Texture Coordinates", "Texture coordinates from root particle locations"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "do_location", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_DO_LOCATION); + RNA_def_property_ui_text(prop, "Location", "Effect particles' location"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "do_rotation", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_DO_ROTATION); + RNA_def_property_ui_text(prop, "Rotation", "Effect particles' dynamic rotation"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); /* Pointer */ @@ -1115,12 +1411,18 @@ static void rna_def_softbody(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_self_collision_get", "rna_SoftBodySettings_self_collision_set"); RNA_def_property_ui_text(prop, "Self Collision", "Enable naive vertex ball self collision."); RNA_def_property_update(prop, 0, "rna_softbody_update"); + + prop= RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "EffectorWeights"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Effector Weights", ""); } void RNA_def_object_force(BlenderRNA *brna) { rna_def_pointcache(brna); rna_def_collision(brna); + rna_def_effector_weight(brna); rna_def_field(brna); rna_def_game_softbody(brna); rna_def_softbody(brna); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 04b4b1142be..453b5f9f91a 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -99,6 +99,7 @@ EnumPropertyItem part_hair_ren_as_items[] = { #include "BKE_context.h" #include "BKE_cloth.h" #include "BKE_depsgraph.h" +#include "BKE_effect.h" #include "BKE_modifier.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -106,48 +107,43 @@ EnumPropertyItem part_hair_ren_as_items[] = { #include "BLI_arithb.h" /* property update functions */ -static void rna_Particle_redo(bContext *C, PointerRNA *ptr) +static void particle_recalc(bContext *C, PointerRNA *ptr, short flag) { - Scene *scene = CTX_data_scene(C); - ParticleSettings *part; if(ptr->type==&RNA_ParticleSystem) { ParticleSystem *psys = (ParticleSystem*)ptr->data; - Object *ob = psys_find_object(scene, psys); - psys->recalc = PSYS_RECALC_REDO; + psys->recalc = flag; - if(ob) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - else { - part = ptr->id.data; - psys_flush_particle_settings(scene, part, PSYS_RECALC_REDO); + DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA); } + else + DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA|flag); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); } +static void rna_Particle_redo(bContext *C, PointerRNA *ptr) +{ + particle_recalc(C, ptr, PSYS_RECALC_REDO); +} static void rna_Particle_reset(bContext *C, PointerRNA *ptr) { - Scene *scene = CTX_data_scene(C); - ParticleSettings *part; + particle_recalc(C, ptr, PSYS_RECALC_RESET); +} - if(ptr->type==&RNA_ParticleSystem) { - ParticleSystem *psys = (ParticleSystem*)ptr->data; - Object *ob = psys_find_object(scene, psys); - - psys->recalc = PSYS_RECALC_RESET; +static void rna_Particle_change_type(bContext *C, PointerRNA *ptr) +{ + particle_recalc(C, ptr, PSYS_RECALC_RESET|PSYS_RECALC_TYPE); +} - if(ob) { - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - } - else { - part = ptr->id.data; - psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET); - } +static void rna_Particle_change_physics(bContext *C, PointerRNA *ptr) +{ + particle_recalc(C, ptr, PSYS_RECALC_RESET|PSYS_RECALC_PHYS); +} - WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); +static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr) +{ + particle_recalc(C, ptr, PSYS_RECALC_CHILD); } static void rna_Particle_target_reset(bContext *C, PointerRNA *ptr) @@ -199,59 +195,6 @@ static void rna_Particle_target_redo(bContext *C, PointerRNA *ptr) } } -static void rna_Particle_change_type(bContext *C, PointerRNA *ptr) -{ - Scene *scene = CTX_data_scene(C); - ParticleSettings *part; - - if(ptr->type==&RNA_ParticleSystem) { - ParticleSystem *psys = (ParticleSystem*)ptr->data; - Object *ob = psys_find_object(scene, psys); - - psys->recalc = PSYS_RECALC_RESET|PSYS_RECALC_TYPE; - - if(ob) { - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - } - else { - part = ptr->id.data; - psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET|PSYS_RECALC_TYPE); - } - - WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); -} - -static void rna_Particle_change_physics(bContext *C, PointerRNA *ptr) -{ - Scene *scene = CTX_data_scene(C); - ParticleSettings *part = ptr->id.data; - psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET|PSYS_RECALC_PHYS); - WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); -} - -static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr) -{ - Scene *scene = CTX_data_scene(C); - ParticleSettings *part; - - if(ptr->type==&RNA_ParticleSystem) { - ParticleSystem *psys = (ParticleSystem*)ptr->data; - Object *ob = psys_find_object(scene, psys); - - psys->recalc = PSYS_RECALC_CHILD; - - if(ob) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - else { - part = ptr->id.data; - - psys_flush_particle_settings(scene, part, PSYS_RECALC_CHILD); - } - - WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); -} static void rna_Particle_hair_dynamics(bContext *C, PointerRNA *ptr) { /* Scene *scene = CTX_data_scene(C); */ @@ -577,6 +520,28 @@ static EnumPropertyItem *rna_Particle_ren_as_itemf(bContext *C, PointerRNA *ptr, return part_ren_as_items; } +static PointerRNA rna_Particle_field1_get(PointerRNA *ptr) +{ + ParticleSettings *part= (ParticleSettings*)ptr->id.data; + + /* weak */ + if(!part->pd) + part->pd= object_add_collision_fields(0); + + return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, part->pd); +} + +static PointerRNA rna_Particle_field2_get(PointerRNA *ptr) +{ + ParticleSettings *part= (ParticleSettings*)ptr->id.data; + + /* weak */ + if(!part->pd2) + part->pd2= object_add_collision_fields(0); + + return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, part->pd2); +} + #else @@ -650,7 +615,7 @@ static void rna_def_particle(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem alive_items[] = { - {PARS_KILLED, "KILLED", 0, "Killed", ""}, + //{PARS_KILLED, "KILLED", 0, "Killed", ""}, {PARS_DEAD, "DEAD", 0, "Dead", ""}, {PARS_UNBORN, "UNBORN", 0, "Unborn", ""}, {PARS_ALIVE, "ALIVE", 0, "Alive", ""}, @@ -1714,89 +1679,25 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Billboard Object", "Billboards face this object (default is active camera)"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); - /* effectors */ - prop= RNA_def_property(srna, "effector_group", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "eff_group"); - RNA_def_property_struct_type(prop, "Group"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this Group."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_all", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[0]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "All", "All effector's weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_spherical", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[1]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_vortex", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[2]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Vortex", "Vortex effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_magnetic", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[3]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Magnetic", "Magnetic effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_wind", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[4]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Wind", "Wind effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_curveguide", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[5]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Curve Guide", "Curve guide effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_texture", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[6]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Texture", "Texture effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_harmonic", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[7]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Harmonic", "Harmonic effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_charge", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[8]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Charge", "Charge effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "eweight_lennardjones", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "effector_weight[9]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Lennard-Jones", "Lennard-Jones effector weight."); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); + prop= RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "EffectorWeights"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Effector Weights", ""); /* animation here? */ rna_def_animdata_common(srna); -// struct PartDeflect *pd; -// struct PartDeflect *pd2; + prop= RNA_def_property(srna, "force_field_1", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "pd"); + RNA_def_property_struct_type(prop, "FieldSettings"); + RNA_def_property_pointer_funcs(prop, "rna_Particle_field1_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Force Field 1", ""); + + prop= RNA_def_property(srna, "force_field_2", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "pd2"); + RNA_def_property_struct_type(prop, "FieldSettings"); + RNA_def_property_pointer_funcs(prop, "rna_Particle_field2_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Force Field 2", ""); } static void rna_def_particle_target(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 95678678569..d6cd81aced2 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -62,6 +62,7 @@ EnumPropertyItem prop_mode_items[] ={ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_node.h" +#include "BKE_pointcache.h" #include "BLI_threads.h" @@ -415,6 +416,14 @@ static void rna_Scene_use_nodes_set(PointerRNA *ptr, int value) ED_node_composit_default(scene); } +static void rna_Physics_update(bContext *C, PointerRNA *ptr) +{ + Scene *scene= (Scene*)ptr->id.data; + Base *base; + + for(base = scene->base.first; base; base=base->next) + BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH); +} #else static void rna_def_tool_settings(BlenderRNA *brna) @@ -596,7 +605,6 @@ static void rna_def_unit_settings(BlenderRNA *brna) RNA_def_property_update(prop, NC_WINDOW, NULL); } - void rna_def_render_layer_common(StructRNA *srna, int scene) { PropertyRNA *prop; @@ -2131,6 +2139,19 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "unit"); RNA_def_property_struct_type(prop, "UnitSettings"); RNA_def_property_ui_text(prop, "Unit Settings", "Unit editing settings"); + + /* Physics Settings */ + prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION); + RNA_def_property_float_sdna(prop, NULL, "physics_settings.gravity"); + RNA_def_property_array(prop, 3); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_text(prop, "Gravity", "Constant acceleration in a given direction"); + RNA_def_property_update(prop, 0, "rna_Physics_update"); + + prop= RNA_def_property(srna, "use_gravity", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "physics_settings.flag", PHYS_GLOBAL_GRAVITY); + RNA_def_property_ui_text(prop, "Global Gravity", "Use global gravity for all dynamics."); + RNA_def_property_update(prop, 0, "rna_Physics_update"); /* Render Data */ prop= RNA_def_property(srna, "render_data", PROP_POINTER, PROP_NONE); |