diff options
author | Lukas Steiblys <imbusy@imbusy.org> | 2009-10-02 02:29:15 +0400 |
---|---|---|
committer | Lukas Steiblys <imbusy@imbusy.org> | 2009-10-02 02:29:15 +0400 |
commit | 0677398a649b6b8c293df3ce3c6668f0a3be3bc8 (patch) | |
tree | 9d510a5bd23559bf4fae670ed04d7e5d6c12578c /source/blender/blenkernel | |
parent | 59248e9f62006ba05e3098e4d213f3dcb23fe711 (diff) | |
parent | bc942eceacb638735dc4f4f68252c4c207147a70 (diff) |
merge from 23153 to 23595soc-2009-imbusy
Diffstat (limited to 'source/blender/blenkernel')
67 files changed, 3917 insertions, 3663 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 4724ee19aaa..17b56864d1e 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -41,6 +41,7 @@ struct bAction; struct bActionGroup; struct FCurve; struct bPose; +struct bItasc; struct bPoseChannel; struct Object; struct Scene; @@ -51,7 +52,7 @@ struct ID; extern "C" { #endif -/* Action API ----------------- */ +/* Action Lib Stuff ----------------- */ /* Allocate a new bAction with the given name */ struct bAction *add_empty_action(const char name[]); @@ -65,6 +66,31 @@ void free_action(struct bAction *act); // XXX is this needed? void make_local_action(struct bAction *act); + +/* Action API ----------------- */ + +/* types of transforms applied to the given item + * - these are the return falgs for action_get_item_transforms() + */ +typedef enum eAction_TransformFlags { + /* location */ + ACT_TRANS_LOC = (1<<0), + /* rotation */ + ACT_TRANS_ROT = (1<<1), + /* scaling */ + ACT_TRANS_SCALE = (1<<2), + + /* all flags */ + ACT_TRANS_ALL = (ACT_TRANS_LOC|ACT_TRANS_ROT|ACT_TRANS_SCALE), +} eAction_TransformFlags; + +/* Return flags indicating which transforms the given object/posechannel has + * - if 'curves' is provided, a list of links to these curves are also returned + * whose nodes WILL NEED FREEING + */ +short action_get_item_transforms(struct bAction *act, struct Object *ob, struct bPoseChannel *pchan, ListBase *curves); + + /* Some kind of bounding box operation on the action */ void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers); @@ -73,6 +99,9 @@ short action_has_motion(const struct bAction *act); /* Action Groups API ----------------- */ +/* Get the active action-group for an Action */ +struct bActionGroup *get_active_actiongroup(struct bAction *act); + /* Make the given Action Group the active one */ void set_active_action_group(struct bAction *act, struct bActionGroup *agrp, short select); @@ -126,11 +155,21 @@ struct bPoseChannel *get_active_posechannel(struct Object *ob); */ struct bPoseChannel *verify_pose_channel(struct bPose* pose, const char* name); - +/* Copy the data from the action-pose (src) into the pose */ +void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); /* sets constraint flags */ void update_pose_constraint_flags(struct bPose *pose); +/* return the name of structure pointed by pose->ikparam */ +const char *get_ikparam_name(struct bPose *pose); + +/* allocate and initialize pose->ikparam according to pose->iksolver */ +void init_pose_ikparam(struct bPose *pose); + +/* initialize a bItasc structure with default value */ +void init_pose_itasc(struct bItasc *itasc); + /* clears BONE_UNKEYED flags for frame changing */ // XXX to be depreceated for a more general solution in animsys... void framechange_poses_clear_unkeyed(void); @@ -153,16 +192,6 @@ void copy_pose_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void rest_pose(struct bPose *pose); -/* Game Engine ------------------------- */ - -/* exported for game engine */ -void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */ -void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); - -/* functions used by the game engine */ -void game_copy_pose(struct bPose **dst, struct bPose *src); -void game_free_pose(struct bPose *pose); - #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 4b1e758da54..32c5ff81740 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -39,14 +39,7 @@ struct PartEff; struct Scene; struct ListBase; -typedef struct DupliObject { - struct DupliObject *next, *prev; - struct Object *ob; - unsigned int origlay; - int index, no_draw, type, animated; - float mat[4][4], omat[4][4]; - float orco[3], uv[2]; -} DupliObject; +#include "DNA_object_types.h" void free_path(struct Path *path); void calc_curvepath(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 1cbb2331782..e5d0c4274b3 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -89,6 +89,7 @@ void where_is_armature (struct bArmature *arm); void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone); void armature_rebuild_pose(struct Object *ob, struct bArmature *arm); void where_is_pose (struct Scene *scene, struct Object *ob); +void where_is_pose_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime); /* get_objectspace_bone_matrix has to be removed still */ void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed); @@ -102,10 +103,8 @@ void armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[][4], flo void armature_loc_pose_to_bone(struct bPoseChannel *pchan, float *inloc, float *outloc); void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4]); -/* Animation functions */ -struct PoseTree *ik_tree_to_posetree(struct Object *ob, struct Bone *bone); -void solve_posetree(PoseTree *tree); -void free_posetree(PoseTree *tree); +/* Rotation Mode Conversions - Used for PoseChannels + Objects... */ +void BKE_rotMode_change_values(float quat[4], float eul[3], short oldMode, short newMode); /* B-Bone support */ typedef struct Mat4 { diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index d60737d62fe..3549d3e372d 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 4 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h index acceff863b9..fb65c9c8920 100644 --- a/source/blender/blenkernel/BKE_boids.h +++ b/source/blender/blenkernel/BKE_boids.h @@ -35,9 +35,7 @@ #include "DNA_boid_types.h" typedef struct BoidBrainData { - Scene *scene; - struct Object *ob; - struct ParticleSystem *psys; + struct ParticleSimulationData *sim; struct ParticleSettings *part; float timestep, cfra, dfra; float wanted_co[3], wanted_speed; diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 4d24a2433b3..f302618e60d 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -60,10 +60,10 @@ typedef enum { BRUSH_PRESET_MAX } BrushCurvePreset; void brush_curve_preset(struct Brush *b, BrushCurvePreset preset); -float brush_curve_strength(struct Brush *br, float p, const float len); +float brush_curve_strength_clamp(struct Brush *br, float p, const float len); +float brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -float brush_sample_falloff(struct Brush *brush, float dist); void brush_sample_tex(struct Brush *brush, float *xy, float *rgba); void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf); diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index e4eed084a3d..5ca8ad892ac 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -139,7 +139,16 @@ void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], ///////////////////////////////////////////////// // used in effect.c ///////////////////////////////////////////////// -CollisionModifierData **get_collisionobjects(struct Scene *scene, Object *self, int *numcollobj); +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_constraint.h b/source/blender/blenkernel/BKE_constraint.h index a0061173438..126816f5a95 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -38,6 +38,9 @@ struct Scene; struct bPoseChannel; /* ---------------------------------------------------------------------------- */ +#ifdef __cplusplus +extern "C" { +#endif /* special struct for use in constraint evaluation */ typedef struct bConstraintOb { @@ -131,6 +134,9 @@ void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, void get_constraint_target_matrix(struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime); void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime); +#ifdef __cplusplus +} +#endif #endif diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index e242ead3b87..44f8238d4d9 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -96,19 +96,27 @@ void draw_all_deps(void); /* ********** API *************** */ /* Note that the DAG never executes changes in Objects, only sets flags in Objects */ + /* (re)-create dependency graph for scene */ void DAG_scene_sort(struct Scene *sce); /* flag all objects that need recalc because they're animated */ void DAG_scene_update_flags(struct Scene *sce, unsigned int lay); - /* flag all objects that need recalc because they're animated, influencing this object only */ -void DAG_object_update_flags(struct Scene *sce, struct Object *ob, unsigned int lay); - /* flushes all recalc flags in objects down the dependency tree */ void DAG_scene_flush_update(struct Scene *sce, unsigned int lay, int time); + + /* flag all IDs that need recalc because they're animated, influencing + this ID only. only for objects currently */ +void DAG_id_update_flags(struct ID *id); /* flushes all recalc flags for this object down the dependency tree, - but not the DAG only supports objects and object data currently */ + but note the DAG only supports objects and object data currently */ void DAG_id_flush_update(struct ID *id, short flag); + /* when setting manual RECALC flags, call this afterwards */ +void DAG_ids_flush_update(int time); + /* (re)-create dependency graph for armature pose */ void DAG_pose_sort(struct Object *ob); + + /* callback for editors module to do updates */ +void DAG_editors_update_cb(void (*func)(struct Main *bmain, struct ID *id)); #endif 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_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index cda64c6b241..94d0864024b 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -35,6 +35,8 @@ struct DriverTarget; struct BezTriple; +#include "DNA_curve_types.h" + /* ************** Keyframe Tools ***************** */ // XXX this stuff is defined in BKE_ipo.h too, so maybe skip for now? @@ -153,6 +155,11 @@ void copy_fcurves(ListBase *dst, ListBase *src); /* find matching F-Curve in the given list of F-Curves */ struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index); +/* Binary search algorithm for finding where to 'insert' BezTriple with given frame number. + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +int binarysearch_bezt_index(struct BezTriple array[], float frame, int arraylen, short *replace); + /* get the time extents for F-Curve */ void calc_fcurve_range(struct FCurve *fcu, float *min, float *max); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 816baa20467..85c3c716b8b 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -107,6 +107,11 @@ struct RenderResult; /* always call to make signals work */ struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser); +/* same as above, but can be used to retrieve images being rendered in + * a thread safe way, always call both acquire and release */ +struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); +void BKE_image_release_ibuf(struct Image *ima, void *lock); + /* returns existing Image when filename/type is same (frame optional) */ struct Image *BKE_add_image_file(const char *name, int frame); @@ -125,6 +130,9 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); /* called on frame change or before render */ void BKE_image_user_calc_imanr(struct ImageUser *iuser, int cfra, int fieldnr); +/* produce image export path */ +int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size); + /* fix things in ImageUser when new image gets assigned */ void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser); @@ -132,7 +140,8 @@ void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser); struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser); /* for multilayer images as well as for render-viewer */ -struct RenderResult *BKE_image_get_renderresult(struct Scene *scene, struct Image *ima); +struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima); +void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima); /* goes over all textures that use images */ void BKE_image_free_all_textures(void); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 54722dac910..0e978128cf6 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -77,6 +77,7 @@ void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListB void flag_listbase_ids(ListBase *lb, short flag, short value); void flag_all_listbases_ids(short flag, short value); +void recalc_all_library_objects(struct Main *main); void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowManager *) ); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index cbb37918d04..b1e7dcaff02 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -42,7 +42,7 @@ struct bNode; struct bNodeLink; struct bNodeSocket; struct bNodeStack; -struct uiBlock; +struct uiLayout; struct rctf; struct ListBase; struct RenderData; @@ -52,6 +52,7 @@ struct Tex; struct GPUMaterial; struct GPUNode; struct GPUNodeStack; +struct PointerRNA; /* ************** NODE TYPE DEFINITIONS ***** */ @@ -82,7 +83,7 @@ typedef struct bNodeType { void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **); /* this line is set on startup of blender */ - int (*butfunc)(struct uiBlock *, struct bNodeTree *, struct bNode *, struct rctf *); + void (*uifunc)(struct uiLayout *, struct PointerRNA *ptr); void (*initfunc)(struct bNode *); void (*freestoragefunc)(struct bNode *); @@ -425,7 +426,7 @@ extern struct ListBase node_all_textures; /* API */ int ntreeTexTagAnimated(struct bNodeTree *ntree); void ntreeTexSetPreviewFlag(int); -void ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, float *dxt, float *dyt, short thread, struct Tex *tex, short which_output, int cfra); +void ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, float *dxt, float *dyt, short thread, struct Tex *tex, short which_output, int cfra, int preview); void ntreeTexCheckCyclics(struct bNodeTree *ntree); char* ntreeTexOutputMenu(struct bNodeTree *ntree); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index c22778f5a30..e0259ff10dd 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -61,37 +61,33 @@ struct BVHTreeRayHit; #define PARTICLE_P ParticleData *pa; int p #define LOOP_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) +#define LOOP_EXISTING_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(!(pa->flag & PARS_UNEXIST)) +#define LOOP_SHOWN_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(!(pa->flag & (PARS_UNEXIST|PARS_NO_DISP))) -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; +#define PSYS_FRAND_COUNT 1024 +#define PSYS_FRAND(seed) psys->frand[(seed) % PSYS_FRAND_COUNT] - short type, psys_nbr; - - struct Object obcopy; /* for restoring transformation data */ - struct RNG *rng; /* random noise generator for e.g. wind */ -} ParticleEffectorCache; +/* fast but sure way to get the modifier*/ +#define PARTICLE_PSMD ParticleSystemModifierData *psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys) -typedef struct ParticleReactEvent { - struct ParticleReactEvent *next, *prev; - int event, pa_num; - Object *ob; +/* common stuff that many particle functions need */ +typedef struct ParticleSimulationData { + struct Scene *scene; + struct Object *ob; struct ParticleSystem *psys; - struct ParticleKey state; - - float time, size; -}ParticleReactEvent; + struct ParticleSystemModifierData *psmd; + struct ListBase *colliders; +} ParticleSimulationData; + +//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 */ @@ -118,11 +114,8 @@ typedef struct ParticleCacheKey{ typedef struct ParticleThreadContext { /* shared */ - struct Scene *scene; - struct Object *ob; + struct ParticleSimulationData sim; struct DerivedMesh *dm; - struct ParticleSystemModifierData *psmd; - struct ParticleSystem *psys; struct Material *ma; /* distribution */ @@ -166,53 +159,52 @@ typedef struct ParticleBillboardData int lock, num; int totnum; short align, uv_split, anim, split_offset; -} -ParticleBillboardData; +} 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 float ray_len; // original length of co2-co1, needed for collision time evaluation float t; // time of previous collision, needed for substracting face velocity -} -ParticleCollision; +} ParticleCollision; + +typedef struct ParticleDrawData { + float *vdata, *vd; /* vertice data */ + float *ndata, *nd; /* normal data */ + float *cdata, *cd; /* color data */ + float *vedata, *ved; /* velocity data */ + float *ma_r, *ma_g, *ma_b; + int tot_vec_size, flag; + int totpoint, totve; +} ParticleDrawData; + +#define PARTICLE_DRAW_DATA_UPDATED 1 /* ----------- functions needed outside particlesystem ---------------- */ /* particle.c */ int count_particles(struct ParticleSystem *psys); int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur); -int psys_count_keys(struct ParticleSystem *psys); -char *psys_menu_string(struct Object *ob, int for_sb); struct ParticleSystem *psys_get_current(struct Object *ob); +/* for rna */ short psys_get_current_num(struct Object *ob); void psys_set_current_num(Object *ob, int index); struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); -//struct ParticleSystem *psys_get(struct Object *ob, int index); -struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index); -struct ParticleKey *psys_get_selected_key(struct ParticleSystem *psys, int pa_index, int *key_index); -void psys_change_act(void *ob_v, void *act_v); -struct Object *psys_get_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); -void psys_disable_all(struct Object *ob); -void psys_enable_all(struct Object *ob); -int psys_ob_has_hair(struct Object *ob); + +struct Object *psys_get_lattice(struct ParticleSimulationData *sim); + int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys); int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); -void psys_free_boid_rules(struct ListBase *list); +/* free */ void psys_free_settings(struct ParticleSettings *part); -void free_child_path_cache(struct ParticleSystem *psys); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); -void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics); -void free_keyed_keys(struct ParticleSystem *psys); -void psys_free_particles(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); -void psys_free_children(struct ParticleSystem *psys); void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset); void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); @@ -231,48 +223,39 @@ 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); -struct LinkNode *psys_using_settings(struct Scene *scene, struct ParticleSettings *part, int flush_update); void psys_reset(struct ParticleSystem *psys, int mode); -void psys_find_parents(struct Object *ob, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys); +void psys_find_parents(struct ParticleSimulationData *sim); -void psys_cache_paths(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float cfra); +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 Scene *scene, struct Object *ob, struct ParticleSystem *psys, float cfra, int editupdate); -int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb); -float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size); -float psys_get_timestep(struct ParticleSettings *part); +void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, int editupdate); +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); -void psys_get_particle_on_path(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel); -int psys_get_particle_state(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always); +void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, int vel); +int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always); + +/* for anim.c */ void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco); -void psys_get_dupli_path_transform(struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); +void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); -ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); -int psys_threads_init_distribution(ParticleThread *threads, struct Scene *scene, struct DerivedMesh *dm, int from); -int psys_threads_init_path(ParticleThread *threads, struct Scene *scene, float cfra, int editupdate); +ParticleThread *psys_threads_create(struct ParticleSimulationData *sim); void psys_threads_free(ParticleThread *threads); -void psys_thread_distribute_particle(ParticleThread *thread, struct ParticleData *pa, struct ChildParticle *cpa, int p); -void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i); - void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]); /* particle_system.c */ struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt); -void psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys); -void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys); - -void psys_init_effectors(struct Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys); -void psys_end_effectors(struct ParticleSystem *psys); +void psys_count_keyed_targets(struct ParticleSimulationData *sim); +void psys_update_particle_tree(struct ParticleSystem *psys, float cfra); void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys); -void psys_end_temp_pointcache(struct ParticleSystem *psys); -void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra); +void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra); void psys_check_boid_data(struct ParticleSystem *psys); @@ -280,40 +263,40 @@ void particle_system_update(struct Scene *scene, struct Object *ob, struct Parti /* ----------- functions needed only inside particlesystem ------------ */ /* particle.c */ +void psys_disable_all(struct Object *ob); +void psys_enable_all(struct Object *ob); + +void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics); +void free_keyed_keys(struct ParticleSystem *psys); +void psys_free_particles(struct ParticleSystem *psys); +void psys_free_children(struct ParticleSystem *psys); + void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity); -void psys_key_to_object(struct Object *ob, struct ParticleKey *key, float imat[][4]); -//void psys_key_to_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key); -//void psys_key_from_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key); -//void psys_face_mat(struct DerivedMesh *dm, struct ParticleData *pa, float mat[][4]); void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); -//void psys_vec_rot_from_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); +void psys_free_pdd(struct ParticleSystem *psys); + float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); -void psys_get_texture(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys, struct ParticleData *pa, struct ParticleTexture *ptex, int event); +void psys_get_texture(struct ParticleSimulationData *sim, struct Material *ma, struct ParticleData *pa, struct ParticleTexture *ptex, int event); void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float *uv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values); -float psys_interpolate_value_from_verts(struct DerivedMesh *dm, short from, int index, float *fw, float *values); void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time); +/* only in edisparticle.c*/ int psys_intersect_dm(struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_uv, float *face_minmax, float *pa_minmax, float radius, float *ipoint); +/* BLI_bvhtree_ray_cast callback */ void particle_intersect_face(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit); void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); /* particle_system.c */ -void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd); - -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(int pa_no, struct ParticleData *pa, struct ParticleKey *state, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float *texco, float *force_field, float *vel,float framestep, float cfra); - +void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, int p); 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 Scene *scene, struct ParticleData *pa, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct Object *ob, - float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot); - +void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); /* psys_reset */ #define PSYS_RESET_ALL 1 @@ -321,12 +304,6 @@ void reset_particle(struct Scene *scene, struct ParticleData *pa, struct Particl #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/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 4fcb7c881be..ee04d4f47bc 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -230,11 +230,11 @@ void BKE_spacedata_copyfirst(ListBase *lb1, ListBase *lb2); /* area/regions */ struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar); void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar); +void BKE_screen_area_free(struct ScrArea *sa); -void BKE_screen_area_free(struct ScrArea *sa); - +/* screen */ void free_screen(struct bScreen *sc); - +unsigned int BKE_screen_visible_layers(struct bScreen *screen); #endif diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index e9f6eb21e36..cbce4663d6f 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -71,7 +71,7 @@ void sound_update_playing(struct bContext *C); void sound_scrub(struct bContext *C); #ifdef AUD_CAPI -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end); +AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume); #endif void sound_stop_all(struct bContext *C); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index bd14053d121..185e32ecdfa 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -48,6 +48,8 @@ int reopen_text (struct Text *text); struct Text* add_text (char *file, const char *relpath); struct Text* copy_text (struct Text *ta); void unlink_text (struct Main *bmain, struct Text *text); +void clear_text(struct Text *text); +void write_text(struct Text *text, char *str); char* txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); @@ -74,7 +76,7 @@ void txt_delete_selected (struct Text *text); void txt_sel_all (struct Text *text); void txt_sel_line (struct Text *text); char* txt_sel_to_buf (struct Text *text); -void txt_insert_buf (struct Text *text, char *in_buffer); +void txt_insert_buf (struct Text *text, const char *in_buffer); void txt_print_undo (struct Text *text); void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc); void txt_do_undo (struct Text *text); @@ -102,6 +104,14 @@ struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marke struct TextMarker *txt_prev_marker_color (struct Text *text, struct TextMarker *marker); struct TextMarker *txt_next_marker_color (struct Text *text, struct TextMarker *marker); +/* utility functions, could be moved somewhere more generic but are python/text related */ +int text_check_bracket(char ch); +int text_check_delim(char ch); +int text_check_digit(char ch); +int text_check_identifier(char ch); +int text_check_whitespace(char ch); + + /* Undo opcodes */ /* Simple main cursor movement */ diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 4d43518901e..7d8cb41db82 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -193,5 +193,54 @@ #define SET_INT_IN_POINTER(i) ((void*)(intptr_t)(i)) #define GET_INT_FROM_POINTER(i) ((int)(intptr_t)(i)) +/*little array macro library. example of usage: + +int *arr = NULL; +V_DECLARE(arr); +int i; + +for (i=0; i<10; i++) { + V_GROW(arr); + arr[i] = something; +} +V_FREE(arr); + +arrays are buffered, using double-buffering (so on each reallocation, +the array size is doubled). supposedly this should give good Big Oh +behaviour, though it may not be the best in practice. +*/ + +#define V_DECLARE(vec) int _##vec##_count=0; void *_##vec##_tmp + +/*in the future, I plan on having V_DECLARE allocate stack memory it'll + use at first, and switch over to heap when it needs more. that'll mess + up cases where you'd want to use this API to build a dynamic list for + non-local use, so all such cases should use this macro.*/ +#define V_DYNDECLARE(vec) V_DECLARE(vec) + +/*this returns the entire size of the array, including any buffering.*/ +#define V_SIZE(vec) ((signed int)((vec)==NULL ? 0 : MEM_allocN_len(vec) / sizeof(*vec))) + +/*this returns the logical size of the array, not including buffering.*/ +#define V_COUNT(vec) _##vec##_count + +/*grow the array by one. zeroes the new elements.*/ +#define V_GROW(vec) \ + V_SIZE(vec) > _##vec##_count ? _##vec##_count++ : \ + ((_##vec##_tmp = MEM_callocN(sizeof(*vec)*(_##vec##_count*2+2), #vec " " __FILE__ " ")),\ + (vec && memcpy(_##vec##_tmp, vec, sizeof(*vec) * _##vec##_count)),\ + (vec && (MEM_freeN(vec),1)),\ + (vec = _##vec##_tmp),\ + _##vec##_count++) + +#define V_FREE(vec) if (vec) MEM_freeN(vec); + +/*resets the logical size of an array to zero, but doesn't + free the memory.*/ +#define V_RESET(vec) _##vec##_count=0 + +/*set the count of the array*/ +#define V_SETCOUNT(vec, count) _##vec##_count = (count) + #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 68aed2b0184..f60cade61ed 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -30,12 +30,10 @@ SET(INC . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../render/extern/include ../../../intern/decimation/extern ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern - ../../../intern/iksolver/extern ../blenloader + ../../../intern/iksolver/extern ../blenloader ../ikplugin ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern ../../../intern/bsp/extern ../blenfont ../../../intern/audaspace/intern - ../../../extern/lzo/minilzo - ../../../extern/lzma ${ZLIB_INC} ) @@ -76,6 +74,16 @@ IF(NOT WITH_ELBEEM) ADD_DEFINITIONS(-DDISABLE_ELBEEM) ENDIF(NOT WITH_ELBEEM) +IF(WITH_LZO) + SET(INC ${INC} ../../../extern/lzo/minilzo) + ADD_DEFINITIONS(-DWITH_LZO) +ENDIF(WITH_LZO) + +IF(WITH_LZMA) + SET(INC ${INC} ../../../extern/lzma) + ADD_DEFINITIONS(-DWITH_LZMA) +ENDIF(WITH_LZMA) + IF(WIN32) SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 1f42390504d..63631ddc40f 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -5,14 +5,12 @@ sources = env.Glob('intern/*.c') incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include ../blenlib ../blenfont ../makesdna' incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna' -incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes' +incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes' incs += ' #/intern/iksolver/extern ../blenloader' incs += ' #/extern/bullet2/src' incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' incs += ' #/intern/smoke/extern' -incs += ' #/extern/lzo/minilzo' -incs += ' #/extern/lzma' incs += ' #/intern/audaspace/intern' incs += ' ' + env['BF_OPENGL_INC'] @@ -61,7 +59,15 @@ if env['BF_NO_ELBEEM']: if env['WITH_BF_LCMS']: defs.append('WITH_LCMS') - + +if env['WITH_BF_LZO']: + incs += ' #/extern/lzo/minilzo' + defs.append('WITH_LZO') + +if env['WITH_BF_LZMA']: + incs += ' #/extern/lzma' + defs.append('WITH_LZMA') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 6c2edc9e25f..26b9b9ef0dd 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -47,6 +47,7 @@ CPPFLAGS += -I$(NAN_AUDASPACE)/include CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../ikplugin # This mod uses the BLI and BLO module CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenloader @@ -85,14 +86,24 @@ CPPFLAGS += -I../../gpu # path to our own external headerfiles CPPFLAGS += -I.. -# path to bullet2, for cloth -CPPFLAGS += -I$(NAN_BULLET2)/include CPPFLAGS += -I$(NAN_FREETYPE)/include CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2 +# path to bullet2, for cloth +ifeq ($(NAN_USE_BULLET), true) + CPPFLAGS += -I$(NAN_BULLET2)/include +endif + # lzo and lzma, for pointcache -CPPFLAGS += -I$(NAN_LZO)/minilzo -CPPFLAGS += -I$(NAN_LZMA) +ifeq ($(WITH_LZO),true) + CPPFLAGS += -I$(NAN_LZO)/minilzo + CPPFLAGS += -DWITH_LZO +endif + +ifeq ($(WITH_LZO),true) + CPPFLAGS += -I$(NAN_LZMA) + CPPFLAGS += -DWITH_LZMA +endif ifeq ($(WITH_FFMPEG),true) CPPFLAGS += -DWITH_FFMPEG diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 47de044ea25..b8dc9fd049d 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -62,6 +62,7 @@ #include "BKE_main.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -212,6 +213,7 @@ bAction *copy_action (bAction *src) return dst; } +/* *************** Action Groups *************** */ /* Get the active action-group for an Action */ bActionGroup *get_active_actiongroup (bAction *act) @@ -404,7 +406,7 @@ bActionGroup *action_groups_find_named (bAction *act, const char name[]) return NULL; } -/* ************************ Pose channels *************** */ +/* *************** Pose channels *************** */ /* usually used within a loop, so we got a N^2 slowdown */ bPoseChannel *get_pose_channel(const bPose *pose, const char *name) @@ -450,7 +452,7 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f; chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f; chan->stiffness[0]= chan->stiffness[1]= chan->stiffness[2]= 0.0f; - + chan->ikrotweight = chan->iklinweight = 0.0f; Mat4One(chan->constinv); BLI_addtail(&pose->chanbase, chan); @@ -476,7 +478,18 @@ bPoseChannel *get_active_posechannel (Object *ob) return NULL; } - +const char *get_ikparam_name(bPose *pose) +{ + if (pose) { + switch (pose->iksolver) { + case IKSOLVER_LEGACY: + return NULL; + case IKSOLVER_ITASC: + return "bItasc"; + } + } + return NULL; +} /* dst should be freed already, makes entire duplicate */ void copy_pose (bPose **dst, bPose *src, int copycon) { @@ -498,7 +511,10 @@ void copy_pose (bPose **dst, bPose *src, int copycon) outPose= MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); - + outPose->iksolver = src->iksolver; + outPose->ikdata = NULL; + outPose->ikparam = MEM_dupallocN(src->ikparam); + if (copycon) { for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) { copy_constraints(&listb, &pchan->constraints); // copy_constraints NULLs listb @@ -510,6 +526,39 @@ void copy_pose (bPose **dst, bPose *src, int copycon) *dst=outPose; } +void init_pose_itasc(bItasc *itasc) +{ + if (itasc) { + itasc->iksolver = IKSOLVER_ITASC; + itasc->minstep = 0.01f; + itasc->maxstep = 0.06f; + itasc->numiter = 100; + itasc->numstep = 4; + itasc->precision = 0.005f; + itasc->flag = ITASC_AUTO_STEP|ITASC_INITIAL_REITERATION|ITASC_SIMULATION; + itasc->feedback = 20.f; + itasc->maxvel = 50.f; + itasc->solver = ITASC_SOLVER_SDLS; + itasc->dampmax = 0.5; + itasc->dampeps = 0.15; + } +} +void init_pose_ikparam(bPose *pose) +{ + bItasc *itasc; + switch (pose->iksolver) { + case IKSOLVER_ITASC: + itasc = MEM_callocN(sizeof(bItasc), "itasc"); + init_pose_itasc(itasc); + pose->ikparam = itasc; + break; + case IKSOLVER_LEGACY: + default: + pose->ikparam = NULL; + break; + } +} + void free_pose_channels(bPose *pose) { bPoseChannel *pchan; @@ -533,133 +582,15 @@ void free_pose(bPose *pose) /* free pose-groups */ if (pose->agroups.first) BLI_freelistN(&pose->agroups); - - /* free pose */ - MEM_freeN(pose); - } -} - -void game_copy_pose(bPose **dst, bPose *src) -{ - bPose *out; - bPoseChannel *pchan, *outpchan; - GHash *ghash; - - /* the game engine copies the current armature pose and then swaps - * the object pose pointer. this makes it possible to change poses - * without affecting the original blender data. */ - - if (!src) { - *dst=NULL; - return; - } - else if (*dst==src) { - printf("copy_pose source and target are the same\n"); - *dst=NULL; - return; - } - - out= MEM_dupallocN(src); - out->agroups.first= out->agroups.last= NULL; - BLI_duplicatelist(&out->chanbase, &src->chanbase); - - /* remap pointers */ - ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - - pchan= src->chanbase.first; - outpchan= out->chanbase.first; - for (; pchan; pchan=pchan->next, outpchan=outpchan->next) - BLI_ghash_insert(ghash, pchan, outpchan); - - for (pchan=out->chanbase.first; pchan; pchan=pchan->next) { - pchan->parent= BLI_ghash_lookup(ghash, pchan->parent); - pchan->child= BLI_ghash_lookup(ghash, pchan->child); - pchan->path= NULL; - } - - BLI_ghash_free(ghash, NULL, NULL); - - *dst=out; -} + /* free IK solver state */ + BIK_clear_data(pose); -/* Only allowed for Poses with identical channels */ -void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/) -{ - short mode= ACTSTRIPMODE_BLEND; - - bPoseChannel *dchan; - const bPoseChannel *schan; - bConstraint *dcon, *scon; - float dstweight; - int i; + /* free IK solver param */ + if (pose->ikparam) + MEM_freeN(pose->ikparam); - switch (mode){ - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default : - dstweight = 1.0F; - } - - schan= src->chanbase.first; - for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){ - if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) { - /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ - - /* Do the transformation blend */ - if (schan->flag & POSE_ROT) { - /* quat interpolation done separate */ - if (schan->rotmode == PCHAN_ROT_QUAT) { - float dquat[4], squat[4]; - - QUATCOPY(dquat, dchan->quat); - QUATCOPY(squat, schan->quat); - if (mode==ACTSTRIPMODE_BLEND) - QuatInterpol(dchan->quat, dquat, squat, srcweight); - else { - QuatMulFac(squat, srcweight); - QuatMul(dchan->quat, dquat, squat); - } - - NormalQuat(dchan->quat); - } - } - - for (i=0; i<3; i++) { - /* blending for loc and scale are pretty self-explanatory... */ - if (schan->flag & POSE_LOC) - dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); - if (schan->flag & POSE_SIZE) - dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); - - /* euler-rotation interpolation done here instead... */ - // FIXME: are these results decent? - if ((schan->flag & POSE_ROT) && (schan->rotmode)) - dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); - } - dchan->flag |= schan->flag; - } - for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) { - /* no 'add' option for constraint blending */ - dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; - } - } - - /* this pose is now in src time */ - dst->ctime= src->ctime; -} - -void game_free_pose(bPose *pose) -{ - if (pose) { - /* we don't free constraints, those are owned by the original pose */ - if(pose->chanbase.first) - BLI_freelistN(&pose->chanbase); - + /* free pose */ MEM_freeN(pose); } } @@ -818,7 +749,7 @@ void pose_remove_group (Object *ob) } } -/* ************** time ****************** */ +/* ************** F-Curve Utilities for Actions ****************** */ /* Check if the given action has any keyframes */ short action_has_motion(const bAction *act) @@ -916,6 +847,98 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ } } +/* Return flags indicating which transforms the given object/posechannel has + * - if 'curves' is provided, a list of links to these curves are also returned + */ +short action_get_item_transforms (bAction *act, Object *ob, bPoseChannel *pchan, ListBase *curves) +{ + PointerRNA ptr; + FCurve *fcu; + char *basePath=NULL; + short flags=0; + + /* build PointerRNA from provided data to obtain the paths to use */ + if (pchan) + RNA_pointer_create((ID *)ob, &RNA_PoseChannel, pchan, &ptr); + else if (ob) + RNA_id_pointer_create((ID *)ob, &ptr); + else + return 0; + + /* get the basic path to the properties of interest */ + basePath= RNA_path_from_ID_to_struct(&ptr); + if (basePath == NULL) + return 0; + + /* search F-Curves for the given properties + * - we cannot use the groups, since they may not be grouped in that way... + */ + for (fcu= act->curves.first; fcu; fcu= fcu->next) { + char *bPtr=NULL, *pPtr=NULL; + + /* if enough flags have been found, we can stop checking unless we're also getting the curves */ + if ((flags == ACT_TRANS_ALL) && (curves == NULL)) + break; + + /* just in case... */ + if (fcu->rna_path == NULL) + continue; + + /* step 1: check for matching base path */ + bPtr= strstr(fcu->rna_path, basePath); + + if (bPtr) { + /* step 2: check for some property with transforms + * - to speed things up, only check for the ones not yet found + * unless we're getting the curves too + * - if we're getting the curves, the BLI_genericNodeN() creates a LinkData + * node wrapping the F-Curve, which then gets added to the list + * - once a match has been found, the curve cannot possibly be any other one + */ + if ((curves) || (flags & ACT_TRANS_LOC) == 0) { + pPtr= strstr(fcu->rna_path, "location"); + if ((pPtr) && (pPtr >= bPtr)) { + flags |= ACT_TRANS_LOC; + + if (curves) + BLI_addtail(curves, BLI_genericNodeN(fcu)); + continue; + } + } + + if ((curves) || (flags & ACT_TRANS_SCALE) == 0) { + pPtr= strstr(fcu->rna_path, "scale"); + if ((pPtr) && (pPtr >= bPtr)) { + flags |= ACT_TRANS_SCALE; + + if (curves) + BLI_addtail(curves, BLI_genericNodeN(fcu)); + continue; + } + } + + if ((curves) || (flags & ACT_TRANS_ROT) == 0) { + pPtr= strstr(fcu->rna_path, "rotation"); + if ((pPtr) && (pPtr >= bPtr)) { + flags |= ACT_TRANS_ROT; + + if (curves) + BLI_addtail(curves, BLI_genericNodeN(fcu)); + continue; + } + } + } + } + + /* free basePath */ + MEM_freeN(basePath); + + /* return flags found */ + return flags; +} + +/* ************** Pose Management Tools ****************** */ + /* Copy the data from the action-pose (src) into the pose */ /* both args are assumed to be valid */ /* exported to game engine */ @@ -1158,138 +1181,6 @@ static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, VecAddf(dst->cyclic_offset, dst->cyclic_offset, src->cyclic_offset); } -typedef struct NlaIpoChannel { - struct NlaIpoChannel *next, *prev; - float val; - void *poin; - int type; -} NlaIpoChannel; - -void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime) -{ - bActionChannel *achan= get_action_channel(act, name); - IpoCurve *icu; - NlaIpoChannel *nic; - - if(achan==NULL) return; - - if(achan->ipo) { - calc_ipo(achan->ipo, ctime); - - for(icu= achan->ipo->curve.first; icu; icu= icu->next) { - /* skip IPO_BITS, is for layers and cannot be blended */ - if(icu->vartype != IPO_BITS) { - nic= MEM_callocN(sizeof(NlaIpoChannel), "NlaIpoChannel"); - BLI_addtail(lb, nic); - nic->val= icu->curval; - nic->poin= get_ipo_poin(id, icu, &nic->type); - } - } - } - - /* constraint channels only for objects */ - if(GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - bConstraint *con; - bConstraintChannel *conchan; - - for (con=ob->constraints.first; con; con=con->next) { - conchan = get_constraint_channel(&achan->constraintChannels, con->name); - - if(conchan && conchan->ipo) { - calc_ipo(conchan->ipo, ctime); - - icu= conchan->ipo->curve.first; // only one ipo now - if(icu) { - nic= MEM_callocN(sizeof(NlaIpoChannel), "NlaIpoChannel constr"); - BLI_addtail(lb, nic); - nic->val= icu->curval; - nic->poin= &con->enforce; - nic->type= IPO_FLOAT; - } - } - } - } -} - -static NlaIpoChannel *find_nla_ipochannel(ListBase *lb, void *poin) -{ - NlaIpoChannel *nic; - - if(poin) { - for(nic= lb->first; nic; nic= nic->next) { - if(nic->poin==poin) - return nic; - } - } - return NULL; -} - - -static void blend_ipochannels(ListBase *dst, ListBase *src, float srcweight, int mode) -{ - NlaIpoChannel *snic, *dnic, *next; - float dstweight; - - switch (mode){ - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default : - dstweight = 1.0F; - } - - for(snic= src->first; snic; snic= next) { - next= snic->next; - - dnic= find_nla_ipochannel(dst, snic->poin); - if(dnic==NULL) { - /* remove from src list, and insert in dest */ - BLI_remlink(src, snic); - BLI_addtail(dst, snic); - } - else { - /* we do the blend */ - dnic->val= dstweight*dnic->val + srcweight*snic->val; - } - } -} - -int execute_ipochannels(ListBase *lb) -{ - NlaIpoChannel *nic; - int count = 0; - - for(nic= lb->first; nic; nic= nic->next) { - if(nic->poin) { - write_ipo_poin(nic->poin, nic->type, nic->val); - count++; - } - } - return count; -} - -/* nla timing */ - -/* this now only used for repeating cycles, to enable fields and blur. */ -/* the whole time control in blender needs serious thinking... */ -static float nla_time(Scene *scene, float cfra, float unit) -{ - extern float bluroffs; // bad construct, borrowed from object.c for now - extern float fieldoffs; - - /* motion blur & fields */ - cfra+= unit*(bluroffs+fieldoffs); - - /* global time */ - cfra*= scene->r.framelen; - - return cfra; -} - /* added "sizecorr" here, to allow armatures to be scaled and still have striding. Only works for uniform scaling. In general I'd advise against scaling armatures ever though! (ton) */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 8cb88cdb786..bd779935d55 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -280,17 +280,27 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, if (quat) { float totfac, q1[4], q2[4]; + /* checks for totfac are needed when 'fac' is 1.0 key_curve_position_weights can assign zero + * to more then one index in data which can give divide by zero error */ +/* totfac= data[0]+data[1]; - QuatInterpol(q1, p0->quat, p1->quat, data[0] / totfac); + if(totfac>0.000001) QuatInterpol(q1, p0->quat, p1->quat, data[0] / totfac); + else QUATCOPY(q1, p1->quat); + NormalQuat(q1); totfac= data[2]+data[3]; - QuatInterpol(q2, p2->quat, p3->quat, data[2] / totfac); + if(totfac>0.000001) QuatInterpol(q2, p2->quat, p3->quat, data[2] / totfac); + else QUATCOPY(q1, p3->quat); NormalQuat(q2); totfac = data[0]+data[1]+data[2]+data[3]; - QuatInterpol(quat, q1, q2, (data[0]+data[1]) / totfac); + if(totfac>0.000001) QuatInterpol(quat, q1, q2, (data[0]+data[1]) / totfac); + else QUATCOPY(quat, q2); NormalQuat(quat); + */ + // XXX - find some way to make quat interpolation work correctly, above code fails in rare but nasty cases. + QUATCOPY(quat, p1->quat); } if(radius) @@ -766,12 +776,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; DupliObject *dob; + ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=0; ParticleKey state; ParticleCacheKey *cache; - ParticleSystemModifierData *psmd; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; float (*obmat)[4], (*oldobmat)[4]; @@ -784,7 +794,6 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if(level>MAX_DUPLI_RECUR) return; part=psys->part; - psmd= psys_get_modifier(par, psys); if(part==0) return; @@ -816,7 +825,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p totpart = psys->totcached; } - psys->lattice = psys_get_lattice(scene, par, psys); + psys->lattice = psys_get_lattice(&sim); /* gather list of objects or single object */ if(part->ren_as==PART_DRAW_GR) { @@ -887,11 +896,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p /* hair we handle separate and compute transform based on hair keys */ if(a < totpart) { cache = psys->pathcache[a]; - psys_get_dupli_path_transform(par, psys, psmd, pa, 0, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, pa, 0, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; - psys_get_dupli_path_transform(par, psys, psmd, 0, cpa, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, 0, cpa, cache, pamat, &scale); } VECCOPY(pamat[3], cache->co); @@ -901,7 +910,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else { /* first key */ state.time = ctime; - if(psys_get_particle_state(scene, par, psys, a, &state, 0) == 0) + if(psys_get_particle_state(&sim, a, &state, 0) == 0) continue; QuatToMat4(state.rot, pamat); @@ -921,7 +930,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, obcopylist[b].obmat); if(G.rendering) - psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); + psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { @@ -940,7 +949,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p dob= new_dupli_object(lb, ob, mat, ob->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, oldobmat); if(G.rendering) - psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); + psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 2d6a97c48ae..ab902bbbae5 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -40,6 +40,7 @@ #include "BLI_dynstr.h" #include "DNA_anim_types.h" +#include "DNA_scene_types.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -71,7 +72,7 @@ static short id_has_animdata (ID *id) switch (GS(id->name)) { /* has AnimData */ case ID_OB: - case ID_MB: case ID_CU: + case ID_MB: case ID_CU: case ID_AR: case ID_KE: case ID_PA: case ID_MA: case ID_TE: case ID_NT: @@ -186,8 +187,6 @@ AnimData *BKE_copy_animdata (AnimData *adt) dadt= MEM_dupallocN(adt); /* make a copy of action - at worst, user has to delete copies... */ - // XXX review this... it might not be optimal behaviour yet... - //id_us_plus((ID *)dadt->action); dadt->action= copy_action(adt->action); dadt->tmpact= copy_action(adt->tmpact); @@ -210,26 +209,113 @@ static void make_local_strips(ListBase *strips) { NlaStrip *strip; - for(strip=strips->first; strip; strip=strip->next) { - if(strip->act) make_local_action(strip->act); - if(strip->remap && strip->remap->target) make_local_action(strip->remap->target); - + for (strip=strips->first; strip; strip=strip->next) { + if (strip->act) make_local_action(strip->act); + //if (strip->remap && strip->remap->target) make_local_action(strip->remap->target); + make_local_strips(&strip->strips); } } +/* Use local copy instead of linked copy of various ID-blocks */ void BKE_animdata_make_local(AnimData *adt) { NlaTrack *nlt; + + /* Actions - Active and Temp */ + if (adt->action) make_local_action(adt->action); + if (adt->tmpact) make_local_action(adt->tmpact); + /* Remaps */ + if (adt->remap && adt->remap->target) make_local_action(adt->remap->target); + + /* Drivers */ + // TODO: need to remap the ID-targets too? + + /* NLA Data */ + for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next) + make_local_strips(&nlt->strips); +} - if(adt->action) make_local_action(adt->action); - if(adt->tmpact) make_local_action(adt->tmpact); - if(adt->remap && adt->remap->target) make_local_action(adt->remap->target); +/* Path Validation -------------------------------------------- */ - for(nlt=adt->nla_tracks.first; nlt; nlt=nlt->next) - make_local_strips(&nlt->strips); +#if 0 +/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate */ +static char *rna_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, char *oldpath) +{ + + + return oldpath; // FIXME!!! +} + +/* Check RNA-Paths for a list of F-Curves */ +static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *curves) +{ + FCurve *fcu; + + /* we need to check every curve... */ + for (fcu= curves->first; fcu; fcu= fcu->next) { + /* firstly, handle the F-Curve's own path */ + fcu->rna_path= rna_path_rename_fix(owner_id, modPtr, newName, fcu->rna_path); + + /* driver? */ + if (fcu->driver) { + ChannelDriver *driver= fcu->driver; + DriverTarget *dtar; + + /* driver targets */ + for (dtar= driver->targets.first; dtar; dtar=dtar->next) { + dtat->rna_path= rna_path_rename_fix(dtar->id, modPtr, newName, dtar->rna_path); + } + } + } } +/* Fix all RNA-Paths for Actions linked to NLA Strips */ +static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *strips) +{ + NlaStrip *strip; + + /* recursively check strips, fixing only actions... */ + for (strip= strips->first; strip; strip= strip->next) { + /* fix strip's action */ + if (strip->act) + fcurves_path_rename_fix(owner_id, modPtr, newName, &strip->act->curves); + /* ignore own F-Curves, since those are local... */ + + /* check sub-strips (if metas) */ + nlastrips_path_rename_fix(owner_id, modPtr, newName, &strip->strips); + } +} + +/* Fix all RNA-Paths in the AnimData block used by the given ID block + * - the pointer of interest must not have had its new name assigned already, otherwise + * path matching for this will never work + */ +void BKE_animdata_fix_paths_rename (ID *owner_id, PointerRNA *modPtr, char *newName) +{ + AnimData *adt= BKE_animdata_from_id(owner_id); + NlaTrack *nlt; + + /* if no AnimData, no need to proceed */ + if (ELEM4(NULL, owner_id, adt, modPtr, newName)) + return; + + /* Active action and temp action */ + if (adt->action) + fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->action->curves); + if (adt->tmpact) + fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->tmpact->curves); + + /* Drivers - Drivers are really F-Curves */ + fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->drivers); + + /* NLA Data - Animation Data for Strips */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + + } +} +#endif + /* *********************************** */ /* KeyingSet API */ @@ -438,7 +524,7 @@ void BKE_keyingsets_free (ListBase *list) * - path: original path string (as stored in F-Curve data) * - dst: destination string to write data to */ -short animsys_remap_path (AnimMapper *remap, char *path, char **dst) +static short animsys_remap_path (AnimMapper *remap, char *path, char **dst) { /* is there a valid remapping table to use? */ //if (remap) { @@ -1378,7 +1464,11 @@ static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt, float ct * * Unresolved things: * - Handling of multi-user settings (i.e. time-offset, group-instancing) -> big cache grids or nodal system? but stored where? - * - Multiple-block dependencies (i.e. drivers for settings are in both local and higher levels) -> split into separate lists? + * - Multiple-block dependencies (i.e. drivers for settings are in both local and higher levels) -> split into separate lists? + * + * Current Status: + * - Currently (as of September 2009), overrides we haven't needed to (fully) implement overrides. + * However, the code fo this is relatively harmless, so is left in the code for now. */ /* Evaluation loop for evaluation animation data @@ -1485,7 +1575,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) } /* nodes */ - // TODO... + EVAL_ANIM_IDS(main->nodetree.first, ADT_RECALC_ANIM); /* textures */ EVAL_ANIM_IDS(main->tex.first, ADT_RECALC_ANIM); @@ -1517,10 +1607,16 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) AnimData *adt= BKE_animdata_from_id(id); Curve *cu= (Curve *)id; + /* set ctime variable for curve */ cu->ctime= ctime; + + /* now execute animation data on top of this as per normal */ BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); } + /* armatures */ + EVAL_ANIM_IDS(main->armature.first, ADT_RECALC_ANIM); + /* meshes */ // TODO... @@ -1529,15 +1625,28 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets - * this tagged by Depsgraph on framechange + * this tagged by Depsgraph on framechange. This optimisation means that objects + * linked from other (not-visible) scenes will not need their data calculated. */ - EVAL_ANIM_IDS(main->object.first, /*ADT_RECALC_ANIM*/0); + EVAL_ANIM_IDS(main->object.first, 0); /* worlds */ EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM); /* scenes */ - EVAL_ANIM_IDS(main->scene.first, ADT_RECALC_ANIM); + for (id= main->scene.first; id; id= id->next) { + AnimData *adt= BKE_animdata_from_id(id); + Scene *scene= (Scene *)id; + + /* do compositing nodes first (since these aren't included in main tree) */ + if (scene->nodetree) { + AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); + BKE_animsys_evaluate_animdata((ID *)scene->nodetree, adt2, ctime, ADT_RECALC_ANIM); + } + + /* now execute scene animation data as per normal */ + BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); + } } /* ***************************************** */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index c880925aa94..6220835a620 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -66,10 +66,9 @@ #include "BKE_object.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BKE_sketch.h" -#include "IK_solver.h" - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -1280,6 +1279,65 @@ void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float Mat4MulMat4(delta_mat, pose_mat, imat); } +/* **************** Rotation Mode Conversions ****************************** */ +/* Used for Objects and Pose Channels, since both can have multiple rotation representations */ + +/* Called from RNA when rotation mode changes + * - the result should be that the rotations given in the provided pointers have had conversions + * applied (as appropriate), such that the rotation of the element hasn't 'visually' changed + * + * - as in SDNA data, quat is used to store quaternions AND axis-angle rotations... + */ +void BKE_rotMode_change_values (float quat[4], float eul[3], short oldMode, short newMode) +{ + /* check if any change - if so, need to convert data */ + if (newMode > 0) { /* to euler */ + if (oldMode == ROT_MODE_AXISANGLE) { + /* axis-angle to euler */ + AxisAngleToEulO(&quat[1], quat[0], eul, newMode); + } + else if (oldMode == ROT_MODE_QUAT) { + /* quat to euler */ + QuatToEulO(quat, eul, newMode); + } + /* else { no conversion needed } */ + } + else if (newMode == ROT_MODE_QUAT) { /* to quat */ + if (oldMode == ROT_MODE_AXISANGLE) { + /* axis angle to quat */ + float q[4]; + + /* copy to temp var first, since quats and axis-angle are stored in same place */ + QuatCopy(q, quat); + AxisAngleToQuat(q, &quat[1], quat[0]); + } + else if (oldMode > 0) { + /* euler to quat */ + EulOToQuat(eul, oldMode, quat); + } + /* else { no conversion needed } */ + } + else { /* to axis-angle */ + if (oldMode > 0) { + /* euler to axis angle */ + EulOToAxisAngle(eul, oldMode, &quat[1], &quat[0]); + } + else if (oldMode == ROT_MODE_QUAT) { + /* quat to axis angle */ + float q[4]; + + /* copy to temp var first, since quats and axis-angle are stored in same place */ + QuatCopy(q, quat); + QuatToAxisAngle(q, &quat[1], &quat[0]); + } + + /* when converting to axis-angle, we need a special exception for the case when there is no axis */ + if (IS_EQ(quat[1], quat[2]) && IS_EQ(quat[2], quat[3])) { + /* for now, rotate around y-axis then (so that it simply becomes the roll) */ + quat[2]= 1.0f; + } + } +} /* **************** The new & simple (but OK!) armature evaluation ********* */ @@ -1569,409 +1627,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm) DAG_pose_sort(ob); ob->pose->flag &= ~POSE_RECALC; + ob->pose->flag |= POSE_WAS_REBUILT; } -/* ********************** THE IK SOLVER ******************* */ - - - -/* allocates PoseTree, and links that to root bone/channel */ -/* Note: detecting the IK chain is duplicate code... in drawarmature.c and in transform_conversions.c */ -static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) -{ - bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan; - PoseTree *tree; - PoseTarget *target; - bConstraint *con; - bKinematicConstraint *data= NULL; - int a, segcount= 0, size, newsize, *oldparent, parent; - - /* find IK constraint, and validate it */ - for(con= pchan_tip->constraints.first; con; con= con->next) { - if(con->type==CONSTRAINT_TYPE_KINEMATIC) { - data=(bKinematicConstraint*)con->data; - if (data->flag & CONSTRAINT_IK_AUTO) break; - if (data->tar==NULL) continue; - if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue; - if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) break; - } - } - if(con==NULL) return; - - /* exclude tip from chain? */ - if(!(data->flag & CONSTRAINT_IK_TIP)) - pchan_tip= pchan_tip->parent; - - /* Find the chain's root & count the segments needed */ - for (curchan = pchan_tip; curchan; curchan=curchan->parent){ - pchan_root = curchan; - - curchan->flag |= POSE_CHAIN; // don't forget to clear this - chanlist[segcount]=curchan; - segcount++; - - if(segcount==data->rootbone || segcount>255) break; // 255 is weak - } - if (!segcount) return; - - /* setup the chain data */ - - /* we make tree-IK, unless all existing targets are in this chain */ - for(tree= pchan_root->iktree.first; tree; tree= tree->next) { - for(target= tree->targets.first; target; target= target->next) { - curchan= tree->pchan[target->tip]; - if(curchan->flag & POSE_CHAIN) - curchan->flag &= ~POSE_CHAIN; - else - break; - } - if(target) break; - } - - /* create a target */ - target= MEM_callocN(sizeof(PoseTarget), "posetarget"); - target->con= con; - pchan_tip->flag &= ~POSE_CHAIN; - - if(tree==NULL) { - /* make new tree */ - tree= MEM_callocN(sizeof(PoseTree), "posetree"); - - tree->iterations= data->iterations; - tree->totchannel= segcount; - tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); - - tree->pchan= MEM_callocN(segcount*sizeof(void*), "ik tree pchan"); - tree->parent= MEM_callocN(segcount*sizeof(int), "ik tree parent"); - for(a=0; a<segcount; a++) { - tree->pchan[a]= chanlist[segcount-a-1]; - tree->parent[a]= a-1; - } - target->tip= segcount-1; - - /* AND! link the tree to the root */ - BLI_addtail(&pchan_root->iktree, tree); - } - else { - tree->iterations= MAX2(data->iterations, tree->iterations); - tree->stretch= tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH); - - /* skip common pose channels and add remaining*/ - size= MIN2(segcount, tree->totchannel); - for(a=0; a<size && tree->pchan[a]==chanlist[segcount-a-1]; a++); - parent= a-1; - - segcount= segcount-a; - target->tip= tree->totchannel + segcount - 1; - - if (segcount > 0) { - /* resize array */ - newsize= tree->totchannel + segcount; - oldchan= tree->pchan; - oldparent= tree->parent; - - tree->pchan= MEM_callocN(newsize*sizeof(void*), "ik tree pchan"); - tree->parent= MEM_callocN(newsize*sizeof(int), "ik tree parent"); - memcpy(tree->pchan, oldchan, sizeof(void*)*tree->totchannel); - memcpy(tree->parent, oldparent, sizeof(int)*tree->totchannel); - MEM_freeN(oldchan); - MEM_freeN(oldparent); - - /* add new pose channels at the end, in reverse order */ - for(a=0; a<segcount; a++) { - tree->pchan[tree->totchannel+a]= chanlist[segcount-a-1]; - tree->parent[tree->totchannel+a]= tree->totchannel+a-1; - } - tree->parent[tree->totchannel]= parent; - - tree->totchannel= newsize; - } - - /* move tree to end of list, for correct evaluation order */ - BLI_remlink(&pchan_root->iktree, tree); - BLI_addtail(&pchan_root->iktree, tree); - } - - /* add target to the tree */ - BLI_addtail(&tree->targets, target); -} - -/* called from within the core where_is_pose loop, all animsystems and constraints -were executed & assigned. Now as last we do an IK pass */ -static void execute_posetree(Object *ob, PoseTree *tree) -{ - float R_parmat[3][3], identity[3][3]; - float iR_parmat[3][3]; - float R_bonemat[3][3]; - float goalrot[3][3], goalpos[3]; - float rootmat[4][4], imat[4][4]; - float goal[4][4], goalinv[4][4]; - float irest_basis[3][3], full_basis[3][3]; - float end_pose[4][4], world_pose[4][4]; - float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; - float resultinf=0.0f; - int a, flag, hasstretch=0, resultblend=0; - bPoseChannel *pchan; - IK_Segment *seg, *parent, **iktree, *iktarget; - IK_Solver *solver; - PoseTarget *target; - bKinematicConstraint *data, *poleangledata=NULL; - Bone *bone; - - if (tree->totchannel == 0) - return; - - iktree= MEM_mallocN(sizeof(void*)*tree->totchannel, "ik tree"); - - for(a=0; a<tree->totchannel; a++) { - pchan= tree->pchan[a]; - bone= pchan->bone; - - /* set DoF flag */ - flag= 0; - if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) - flag |= IK_XDOF; - if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) - flag |= IK_YDOF; - if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) - flag |= IK_ZDOF; - - if(tree->stretch && (pchan->ikstretch > 0.0)) { - flag |= IK_TRANS_YDOF; - hasstretch = 1; - } - - seg= iktree[a]= IK_CreateSegment(flag); - - /* find parent */ - if(a == 0) - parent= NULL; - else - parent= iktree[tree->parent[a]]; - - IK_SetParent(seg, parent); - - /* get the matrix that transforms from prevbone into this bone */ - Mat3CpyMat4(R_bonemat, pchan->pose_mat); - - /* gather transformations for this IK segment */ - - if (pchan->parent) - Mat3CpyMat4(R_parmat, pchan->parent->pose_mat); - else - Mat3One(R_parmat); - - /* bone offset */ - if (pchan->parent && (a > 0)) - VecSubf(start, pchan->pose_head, pchan->parent->pose_tail); - else - /* only root bone (a = 0) has no parent */ - start[0]= start[1]= start[2]= 0.0f; - - /* change length based on bone size */ - length= bone->length*VecLength(R_bonemat[1]); - - /* compute rest basis and its inverse */ - Mat3CpyMat3(rest_basis, bone->bone_mat); - Mat3CpyMat3(irest_basis, bone->bone_mat); - Mat3Transp(irest_basis); - - /* compute basis with rest_basis removed */ - Mat3Inv(iR_parmat, R_parmat); - Mat3MulMat3(full_basis, iR_parmat, R_bonemat); - Mat3MulMat3(basis, irest_basis, full_basis); - - /* basis must be pure rotation */ - Mat3Ortho(basis); - - /* transform offset into local bone space */ - Mat3Ortho(iR_parmat); - Mat3MulVecfl(iR_parmat, start); - - IK_SetTransform(seg, start, rest_basis, basis, length); - - if (pchan->ikflag & BONE_IK_XLIMIT) - IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]); - if (pchan->ikflag & BONE_IK_YLIMIT) - IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]); - if (pchan->ikflag & BONE_IK_ZLIMIT) - IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]); - - IK_SetStiffness(seg, IK_X, pchan->stiffness[0]); - IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); - IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); - - if(tree->stretch && (pchan->ikstretch > 0.0f)) { - float ikstretch = pchan->ikstretch*pchan->ikstretch; - IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0f-ikstretch, 0.99f)); - IK_SetLimit(seg, IK_TRANS_Y, 0.001f, 1e10); - } - } - - solver= IK_CreateSolver(iktree[0]); - - /* set solver goals */ - - /* first set the goal inverse transform, assuming the root of tree was done ok! */ - pchan= tree->pchan[0]; - if (pchan->parent) - /* transform goal by parent mat, so this rotation is not part of the - segment's basis. otherwise rotation limits do not work on the - local transform of the segment itself. */ - Mat4CpyMat4(rootmat, pchan->parent->pose_mat); - else - Mat4One(rootmat); - VECCOPY(rootmat[3], pchan->pose_head); - - Mat4MulMat4 (imat, rootmat, ob->obmat); - Mat4Invert (goalinv, imat); - - for (target=tree->targets.first; target; target=target->next) { - float polepos[3]; - int poleconstrain= 0; - - data= (bKinematicConstraint*)target->con->data; - - /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though - * strictly speaking, it is a posechannel) - */ - get_constraint_target_matrix(target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); - - /* and set and transform goal */ - Mat4MulMat4(goal, rootmat, goalinv); - - VECCOPY(goalpos, goal[3]); - Mat3CpyMat4(goalrot, goal); - - /* same for pole vector target */ - if(data->poletar) { - get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); - - if(data->flag & CONSTRAINT_IK_SETANGLE) { - /* don't solve IK when we are setting the pole angle */ - break; - } - else { - Mat4MulMat4(goal, rootmat, goalinv); - VECCOPY(polepos, goal[3]); - poleconstrain= 1; - - /* for pole targets, we blend the result of the ik solver - * instead of the target position, otherwise we can't get - * a smooth transition */ - resultblend= 1; - resultinf= target->con->enforce; - - if(data->flag & CONSTRAINT_IK_GETANGLE) { - poleangledata= data; - data->flag &= ~CONSTRAINT_IK_GETANGLE; - } - } - } - - /* do we need blending? */ - if (!resultblend && target->con->enforce!=1.0f) { - float q1[4], q2[4], q[4]; - float fac= target->con->enforce; - float mfac= 1.0f-fac; - - pchan= tree->pchan[target->tip]; - - /* end effector in world space */ - Mat4CpyMat4(end_pose, pchan->pose_mat); - VECCOPY(end_pose[3], pchan->pose_tail); - Mat4MulSerie(world_pose, goalinv, ob->obmat, end_pose, 0, 0, 0, 0, 0); - - /* blend position */ - goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0]; - goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1]; - goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2]; - - /* blend rotation */ - Mat3ToQuat(goalrot, q1); - Mat4ToQuat(world_pose, q2); - QuatInterpol(q, q1, q2, mfac); - QuatToMat3(q, goalrot); - } - - iktarget= iktree[target->tip]; - - if(data->weight != 0.0f) { - if(poleconstrain) - IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, - polepos, data->poleangle*(float)M_PI/180.0f, (poleangledata == data)); - IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); - } - if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f)) - if((data->flag & CONSTRAINT_IK_AUTO)==0) - IK_SolverAddGoalOrientation(solver, iktarget, goalrot, - data->orientweight); - } - - /* solve */ - IK_Solve(solver, 0.0f, tree->iterations); - - if(poleangledata) - poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180.0f/(float)M_PI; - - IK_FreeSolver(solver); - - /* gather basis changes */ - tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); - if(hasstretch) - ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); - - for(a=0; a<tree->totchannel; a++) { - IK_GetBasisChange(iktree[a], tree->basis_change[a]); - - if(hasstretch) { - /* have to compensate for scaling received from parent */ - float parentstretch, stretch; - - pchan= tree->pchan[a]; - parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0f; - - if(tree->stretch && (pchan->ikstretch > 0.0f)) { - float trans[3], length; - - IK_GetTranslationChange(iktree[a], trans); - length= pchan->bone->length*VecLength(pchan->pose_mat[1]); - - ikstretch[a]= (length == 0.0f)? 1.0f: (trans[1]+length)/length; - } - else - ikstretch[a] = 1.0f; - - stretch= (parentstretch == 0.0f)? 1.0f: ikstretch[a]/parentstretch; - - VecMulf(tree->basis_change[a][0], stretch); - VecMulf(tree->basis_change[a][1], stretch); - VecMulf(tree->basis_change[a][2], stretch); - } - - if(resultblend && resultinf!=1.0f) { - Mat3One(identity); - Mat3BlendMat3(tree->basis_change[a], identity, - tree->basis_change[a], resultinf); - } - - IK_FreeSegment(iktree[a]); - } - - MEM_freeN(iktree); - if(ikstretch) MEM_freeN(ikstretch); -} - -void free_posetree(PoseTree *tree) -{ - BLI_freelistN(&tree->targets); - if(tree->pchan) MEM_freeN(tree->pchan); - if(tree->parent) MEM_freeN(tree->parent); - if(tree->basis_change) MEM_freeN(tree->basis_change); - MEM_freeN(tree); -} - /* ********************** THE POSE SOLVER ******************* */ @@ -1991,7 +1650,7 @@ void chan_calc_mat(bPoseChannel *chan) /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ EulOToMat3(chan->eul, chan->rotmode, rmat); } - else if (chan->rotmode == PCHAN_ROT_AXISANGLE) { + else if (chan->rotmode == ROT_MODE_AXISANGLE) { /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ AxisAngleToMat3(&chan->quat[1], chan->quat[0], rmat); } @@ -2012,41 +1671,6 @@ void chan_calc_mat(bPoseChannel *chan) } } -/* transform from bone(b) to bone(b+1), store in chan_mat */ -static void make_dmats(bPoseChannel *pchan) -{ - if (pchan->parent) { - float iR_parmat[4][4]; - Mat4Invert(iR_parmat, pchan->parent->pose_mat); - Mat4MulMat4(pchan->chan_mat, pchan->pose_mat, iR_parmat); // delta mat - } - else Mat4CpyMat4(pchan->chan_mat, pchan->pose_mat); -} - -/* applies IK matrix to pchan, IK is done separated */ -/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */ -/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */ -static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = to detect if this is first bone -{ - float vec[3], ikmat[4][4]; - - Mat4CpyMat3(ikmat, ik_mat); - - if (pchan->parent) - Mat4MulSerie(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL); - else - Mat4MulMat4(pchan->pose_mat, ikmat, pchan->chan_mat); - - /* calculate head */ - VECCOPY(pchan->pose_head, pchan->pose_mat[3]); - /* calculate tail */ - VECCOPY(vec, pchan->pose_mat[1]); - VecMulf(vec, pchan->bone->length); - VecAddf(pchan->pose_tail, pchan->pose_head, vec); - - pchan->flag |= POSE_DONE; -} - /* NLA strip modifiers */ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseChannel *pchan) { @@ -2172,7 +1796,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha /* The main armature solver, does all constraints excluding IK */ /* pchan is validated, as having bone and parent pointer */ -static void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) +void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) { Bone *bone, *parbone; bPoseChannel *parchan; @@ -2312,48 +1936,27 @@ void where_is_pose (Scene *scene, Object *ob) else { Mat4Invert(ob->imat, ob->obmat); // imat is needed - /* 1. construct the PoseTrees, clear flags */ + /* 1. clear flags */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - pchan->flag &= ~(POSE_DONE|POSE_CHAIN); - if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints - initialize_posetree(ob, pchan); // will attach it to root! + pchan->flag &= ~(POSE_DONE|POSE_CHAIN|POSE_IKTREE); } - - /* 2. the main loop, channels are already hierarchical sorted from root to children */ + /* 2. construct the IK tree */ + BIK_initialize_tree(scene, ob, ctime); + + /* 3. the main loop, channels are already hierarchical sorted from root to children */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - /* 3. if we find an IK root, we handle it separated */ - if(pchan->iktree.first) { - while(pchan->iktree.first) { - PoseTree *tree= pchan->iktree.first; - int a; - - /* 4. walk over the tree for regular solving */ - for(a=0; a<tree->totchannel; a++) { - if(!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag - where_is_pose_bone(scene, ob, tree->pchan[a], ctime); - } - /* 5. execute the IK solver */ - execute_posetree(ob, tree); - - /* 6. apply the differences to the channels, - we need to calculate the original differences first */ - for(a=0; a<tree->totchannel; a++) - make_dmats(tree->pchan[a]); - - for(a=0; a<tree->totchannel; a++) - /* sets POSE_DONE */ - where_is_ik_bone(tree->pchan[a], tree->basis_change[a]); - - /* 7. and free */ - BLI_remlink(&pchan->iktree, tree); - free_posetree(tree); - } + /* 4. if we find an IK root, we handle it separated */ + if(pchan->flag & POSE_IKTREE) { + BIK_execute_tree(scene, ob, pchan, ctime); } + /* 5. otherwise just call the normal solver */ else if(!(pchan->flag & POSE_DONE)) { where_is_pose_bone(scene, ob, pchan, ctime); } } + /* 6. release the IK tree */ + BIK_release_tree(scene, ob, ctime); } /* calculating deform matrices */ diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 18f065b59d9..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->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->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->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->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->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->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) { @@ -261,12 +237,12 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * //check boids in own system if(acbr->options & BRULE_ACOLL_WITH_BOIDS) { - neighbors = BLI_kdtree_range_search(bbd->psys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); + neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); if(neighbors > 1) for(n=1; n<neighbors; n++) { VECCOPY(co1, pa->prev_state.co); VECCOPY(vel1, pa->prev_state.vel); - VECCOPY(co2, (bbd->psys->particles + ptn[n].index)->prev_state.co); - VECCOPY(vel2, (bbd->psys->particles + ptn[n].index)->prev_state.vel); + VECCOPY(co2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.co); + VECCOPY(vel2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.vel); VecSubf(loc, co1, co2); @@ -303,8 +279,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* check boids in other systems */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { neighbors = BLI_kdtree_range_search(epsys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); @@ -362,11 +338,11 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa ParticleTarget *pt; float len = 2.0f * val->personal_space * pa->size + 1.0f; float vec[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_range_search(bbd->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); int ret = 0; if(neighbors > 1 && ptn[1].dist!=0.0f) { - VecSubf(vec, pa->prev_state.co, bbd->psys->particles[ptn[1].index].state.co); + VecSubf(vec, pa->prev_state.co, bbd->sim->psys->particles[ptn[1].index].state.co); VecMulf(vec, (2.0f * val->personal_space * pa->size - ptn[1].dist) / ptn[1].dist); VecAddf(bbd->wanted_co, bbd->wanted_co, vec); bbd->wanted_speed = val->max_speed; @@ -376,8 +352,8 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* check other boid systems */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { neighbors = BLI_kdtree_range_search(epsys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); @@ -400,14 +376,14 @@ static int rule_flock(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti { KDTreeNearest ptn[11]; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_find_n_nearest(bbd->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn); + int neighbors = BLI_kdtree_find_n_nearest(bbd->sim->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn); int n; int ret = 0; if(neighbors > 1) { for(n=1; n<neighbors; n++) { - VecAddf(loc, loc, bbd->psys->particles[ptn[n].index].prev_state.co); - VecAddf(vec, vec, bbd->psys->particles[ptn[n].index].prev_state.vel); + VecAddf(loc, loc, bbd->sim->psys->particles[ptn[n].index].prev_state.co); + VecAddf(vec, vec, bbd->sim->psys->particles[ptn[n].index].prev_state.vel); } VecMulf(loc, 1.0f/((float)neighbors - 1.0f)); @@ -429,8 +405,8 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float mul, len; - int n = (flbr->queue_size <= 1) ? bbd->psys->totpart : flbr->queue_size; - int i, ret = 0, p = pa - bbd->psys->particles; + int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size; + int i, ret = 0, p = pa - bbd->sim->psys->particles; if(flbr->ob) { float vec2[3], t; @@ -475,8 +451,8 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* not blocking so try to follow leader */ if(p && flbr->options & BRULE_LEADER_IN_LINE) { - VECCOPY(vec, bbd->psys->particles[p-1].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p-1].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p-1].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p-1].prev_state.co); } else { VECCOPY(loc, flbr->oloc); @@ -496,10 +472,10 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va float vec2[3], t, t_min = 3.0f; /* first check we're not blocking any leaders */ - for(i = 0; i< bbd->psys->totpart; i+=n){ - VECCOPY(vec, bbd->psys->particles[i].prev_state.vel); + for(i = 0; i< bbd->sim->psys->totpart; i+=n){ + VECCOPY(vec, bbd->sim->psys->particles[i].prev_state.vel); - VecSubf(loc, pa->prev_state.co, bbd->psys->particles[i].prev_state.co); + VecSubf(loc, pa->prev_state.co, bbd->sim->psys->particles[i].prev_state.co); mul = Inpf(vec, vec); @@ -539,12 +515,12 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* not blocking so try to follow leader */ if(flbr->options & BRULE_LEADER_IN_LINE) { - VECCOPY(vec, bbd->psys->particles[p-1].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p-1].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p-1].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p-1].prev_state.co); } else { - VECCOPY(vec, bbd->psys->particles[p - p%n].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p - p%n].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p - p%n].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p - p%n].prev_state.co); } /* fac is seconds behind leader */ @@ -584,7 +560,7 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* leveling */ if(asbr->level > 0.0f) { - Projf(vec, bbd->wanted_co, bbd->psys->part->acc); + Projf(vec, bbd->wanted_co, bbd->sim->psys->part->acc); VecMulf(vec, asbr->level); VecSubf(bbd->wanted_co, bbd->wanted_co, vec); } @@ -601,7 +577,7 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* leveling */ if(asbr->level > 0.0f) { - Projf(vec, bbd->wanted_co, bbd->psys->part->acc); + Projf(vec, bbd->wanted_co, bbd->sim->psys->part->acc); VecMulf(vec, asbr->level); VecSubf(bbd->wanted_co, bbd->wanted_co, vec); } @@ -627,9 +603,9 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti int n, ret = 0; /* calculate own group strength */ - int neighbors = BLI_kdtree_range_search(bbd->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); for(n=0; n<neighbors; n++) { - bpa = bbd->psys->particles[ptn[n].index].boid; + bpa = bbd->sim->psys->particles[ptn[n].index].boid; health += bpa->data.health; } @@ -638,8 +614,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* add other friendlies and calculate enemy strength and find closest enemy */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { epars = epsys->particles; @@ -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->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->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->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 */ @@ -941,7 +916,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) bbd->wanted_co[0]=bbd->wanted_co[1]=bbd->wanted_co[2]=bbd->wanted_speed=0.0f; /* create random seed for every particle & frame */ - BLI_srandom(bbd->psys->seed + p); + BLI_srandom(bbd->sim->psys->seed + p); rand = BLI_rand(); BLI_srandom((int)bbd->cfra + rand); @@ -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; @@ -1077,7 +1053,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f}; float force[3] = {0.0f, 0.0f, 0.0f}, tvel[3] = {0.0f, 0.0f, 1.0f}; float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep; - int p = pa - bbd->psys->particles; + int p = pa - bbd->sim->psys->particles; set_boid_values(&val, boids, pa); @@ -1208,7 +1184,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) } /* account for effectors */ - do_effectors(p, pa, &pa->state, bbd->scene, bbd->ob, bbd->psys, 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/brush.c b/source/blender/blenkernel/intern/brush.c index bce4e1120be..115d31b587c 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -44,6 +44,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_rand.h" #include "BKE_brush.h" #include "BKE_colortools.h" @@ -78,7 +79,7 @@ Brush *add_brush(const char *name) brush->smooth_stroke_radius= 75; brush->smooth_stroke_factor= 0.9; brush->rate= 0.1f; - brush->innerradius= 0.5f; + brush->jitter= 0.0f; brush->clone.alpha= 0.5; brush->sculpt_tool = SCULPT_TOOL_DRAW; @@ -379,36 +380,6 @@ void brush_check_exists(Brush **brush, const char *name) } /* Brush Sampling */ - -/*static float taylor_approx_cos(float f) -{ - f = f*f; - f = 1.0f - f/2.0f + f*f/24.0f; - return f; -}*/ - -float brush_sample_falloff(Brush *brush, float dist) -{ - float a, outer, inner; - - outer = brush->size >> 1; - inner = outer*brush->innerradius; - - if (dist <= inner) { - return brush->alpha; - } - else if ((dist < outer) && (inner < outer)) { - a = sqrt((dist - inner)/(outer - inner)); - return (1 - a)*brush->alpha; - - /* formula used by sculpt, with taylor approx - a = 0.5f*(taylor_approx_cos(3.0f*(dist - inner)/(outer - inner)) + 1.0f); - return a*brush->alpha; */ - } - else - return 0.0f; -} - void brush_sample_tex(Brush *brush, float *xy, float *rgba) { MTex *mtex= brush->mtex[brush->texact]; @@ -446,6 +417,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o ImBuf *ibuf; float xy[2], dist, rgba[4], *dstf; int x, y, rowbytes, xoff, yoff, imbflag; + int maxsize = brush->size >> 1; char *dst, crgb[3]; imbflag= (flt)? IB_rectfloat: IB_rect; @@ -470,7 +442,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); VECCOPY(dstf, brush->rgb); - dstf[3]= brush_sample_falloff(brush, dist); + dstf[3]= brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize); } else if (texfall == 1) { brush_sample_tex(brush, xy, dstf); @@ -483,7 +455,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dstf[0] = rgba[0]*brush->rgb[0]; dstf[1] = rgba[1]*brush->rgb[1]; dstf[2] = rgba[2]*brush->rgb[2]; - dstf[3] = rgba[3]*brush_sample_falloff(brush, dist); + dstf[3] = rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize); } } } @@ -506,7 +478,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dst[0]= crgb[0]; dst[1]= crgb[1]; dst[2]= crgb[2]; - dst[3]= FTOCHAR(brush_sample_falloff(brush, dist)); + dst[3]= FTOCHAR(brush->alpha*brush_curve_strength(brush, dist, maxsize)); } else if (texfall == 1) { brush_sample_tex(brush, xy, rgba); @@ -522,7 +494,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]); dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]); dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]); - dst[3] = FTOCHAR(rgba[3]*brush_sample_falloff(brush, dist)); + dst[3] = FTOCHAR(rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize)); } } } @@ -542,7 +514,7 @@ typedef struct BrushPainterCache { int lastsize; float lastalpha; - float lastinnerradius; + float lastjitter; ImBuf *ibuf; ImBuf *texibuf; @@ -567,7 +539,7 @@ struct BrushPainter { float startsize; float startalpha; - float startinnerradius; + float startjitter; float startspacing; BrushPainterCache cache; @@ -583,7 +555,7 @@ BrushPainter *brush_painter_new(Brush *brush) painter->startsize = brush->size; painter->startalpha = brush->alpha; - painter->startinnerradius = brush->innerradius; + painter->startjitter = brush->jitter; painter->startspacing = brush->spacing; return painter; @@ -617,7 +589,7 @@ void brush_painter_free(BrushPainter *painter) brush->size = painter->startsize; brush->alpha = painter->startalpha; - brush->innerradius = painter->startinnerradius; + brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); @@ -711,7 +683,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i } } -void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) +static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) { Brush *brush= painter->brush; BrushPainterCache *cache= &painter->cache; @@ -773,7 +745,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos) short flt; if ((brush->size != cache->lastsize) || (brush->alpha != cache->lastalpha) - || (brush->innerradius != cache->lastinnerradius)) { + || (brush->jitter != cache->lastjitter)) { if (cache->ibuf) { IMB_freeImBuf(cache->ibuf); cache->ibuf= NULL; @@ -798,7 +770,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos) cache->lastsize= brush->size; cache->lastalpha= brush->alpha; - cache->lastinnerradius= brush->innerradius; + cache->lastjitter= brush->jitter; } else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) { int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; @@ -820,20 +792,34 @@ static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pres brush->alpha = MAX2(0.0, painter->startalpha*pressure); if (brush->flag & BRUSH_SIZE_PRESSURE) brush->size = MAX2(1.0, painter->startsize*pressure); - if (brush->flag & BRUSH_RAD_PRESSURE) - brush->innerradius = MAX2(0.0, painter->startinnerradius*pressure); + if (brush->flag & BRUSH_JITTER_PRESSURE) + brush->jitter = MAX2(0.0, painter->startjitter*pressure); if (brush->flag & BRUSH_SPACING_PRESSURE) brush->spacing = MAX2(1.0, painter->startspacing*(1.5f-pressure)); } +static void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos) +{ + if(brush->jitter){ + jitterpos[0] = pos[0] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2); + jitterpos[1] = pos[1] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2); + } + else { + VECCOPY2D(jitterpos, pos); + } +} + int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user) { Brush *brush= painter->brush; int totpaintops= 0; - if (pressure == 0.0f) - pressure = 1.0f; /* zero pressure == not using tablet */ - + if (pressure == 0.0f) { + if(painter->lastpressure) // XXX - hack, operator misses + pressure= painter->lastpressure; + else + pressure = 1.0f; /* zero pressure == not using tablet */ + } if (painter->firsttouch) { /* paint exactly once on first touch */ painter->startpaintpos[0]= pos[0]; @@ -884,7 +870,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl } #endif else { - float startdistance, spacing, step, paintpos[2], dmousepos[2]; + float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2]; float t, len, press; /* compute brush spacing adapted to brush size, spacing may depend @@ -909,11 +895,13 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush_apply_pressure(painter, brush, press); spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f; + brush_jitter_pos(brush, paintpos, finalpos); + if (painter->cache.enabled) - brush_painter_refresh_cache(painter, paintpos); + brush_painter_refresh_cache(painter, finalpos); totpaintops += - func(user, painter->cache.ibuf, painter->lastpaintpos, paintpos); + func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos); painter->lastpaintpos[0]= paintpos[0]; painter->lastpaintpos[1]= paintpos[1]; @@ -936,10 +924,14 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl while (painter->accumtime >= brush->rate) { brush_apply_pressure(painter, brush, pressure); + + brush_jitter_pos(brush, pos, finalpos); + if (painter->cache.enabled) - brush_painter_refresh_cache(painter, paintpos); + brush_painter_refresh_cache(painter, finalpos); + totpaintops += - func(user, painter->cache.ibuf, painter->lastmousepos, pos); + func(user, painter->cache.ibuf, painter->lastmousepos, finalpos); painter->accumtime -= brush->rate; } @@ -953,17 +945,30 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush->alpha = painter->startalpha; brush->size = painter->startsize; - brush->innerradius = painter->startinnerradius; + brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; return totpaintops; } /* Uses the brush curve control to find a strength value between 0 and 1 */ +float brush_curve_strength_clamp(Brush *br, float p, const float len) +{ + if(p >= len) p= 1.0f; + else p= p/len; + + p= curvemapping_evaluateF(br->curve, 0, p); + if(p < 0.0) p= 0.0f; + else if(p > 1.0f) p= 1.0f; + return p; +} +/* same as above but can return negative values if the curve enables + * used for sculpt only */ float brush_curve_strength(Brush *br, float p, const float len) { - if(p > len) p= len; - return curvemapping_evaluateF(br->curve, 0, p/len); + if(p >= len) p= 1.0f; + else p= p/len; + return curvemapping_evaluateF(br->curve, 0, p); } /* TODO: should probably be unified with BrushPainter stuff? */ @@ -1030,7 +1035,7 @@ static struct ImBuf *brush_gen_radial_control_imbuf(Brush *br) for(i=0; i<side; ++i) { for(j=0; j<side; ++j) { float magn= sqrt(pow(i - half, 2) + pow(j - half, 2)); - im->rect_float[i*side + j]= brush_curve_strength(br, magn, half); + im->rect_float[i*side + j]= brush_curve_strength_clamp(br, magn, half); } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index d25c329f49f..74f88a77e63 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -95,7 +95,7 @@ static CM_SOLVER_DEF solvers [] = static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); +static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ); @@ -153,9 +153,12 @@ 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); } -BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) +static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; @@ -196,7 +199,7 @@ BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) return bvhtree; } -BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) +static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; @@ -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; @@ -998,7 +1005,7 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in return 0; } -void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) +static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) { unsigned int i = 0; @@ -1031,7 +1038,7 @@ void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgeli BLI_edgehash_free ( cloth->edgehash, NULL ); } -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) +static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) { Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; @@ -1160,25 +1167,66 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) BLI_linklist_prepend ( &cloth->springs, spring ); } - // bending springs - search2 = cloth->springs; - for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) - { - if ( !search2 ) - break; + if(numfaces) { + // bending springs + search2 = cloth->springs; + for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) + { + if ( !search2 ) + break; - tspring2 = search2->link; - search = edgelist[tspring2->kl]; - while ( search ) + tspring2 = search2->link; + search = edgelist[tspring2->kl]; + while ( search ) + { + tspring = search->link; + index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); + + // check for existing spring + // check also if startpoint is equal to endpoint + if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) ) + && ( index2!=tspring2->ij ) ) + { + spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + + if(!spring) + { + cloth_free_errorsprings(cloth, edgehash, edgelist); + return 0; + } + + spring->ij = MIN2(tspring2->ij, index2); + spring->kl = MAX2(tspring2->ij, index2); + VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_BENDING; + spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; + BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL ); + bend_springs++; + + BLI_linklist_prepend ( &cloth->springs, spring ); + } + search = search->next; + } + search2 = search2->next; + } + } + else if(struct_springs > 2) { + /* bending springs for hair strands */ + /* The current algorightm only goes through the edges in order of the mesh edges list */ + /* and makes springs between the outer vert of edges sharing a vertice. This works just */ + /* fine for hair, but not for user generated string meshes. This could/should be later */ + /* extended to work with non-ordered edges so that it can be used for general "rope */ + /* dynamics" without the need for the vertices or edges to be ordered through the length*/ + /* of the strands. -jahka */ + search = cloth->springs; + search2 = search->next; + while(search && search2) { tspring = search->link; - index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); - - // check for existing spring - // check also if startpoint is equal to endpoint - if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) ) - && ( index2!=tspring2->ij ) ) - { + tspring2 = search2->link; + + if(tspring->ij == tspring2->kl) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) @@ -1187,20 +1235,20 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) return 0; } - spring->ij = MIN2(tspring2->ij, index2); - spring->kl = MAX2(tspring2->ij, index2); + spring->ij = tspring2->ij; + spring->kl = tspring->kl; VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; - BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL ); bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } + search = search->next; + search2 = search2->next; } - search2 = search2->next; } /* insert other near springs in edgehash AFTER bending springs are calculated (for selfcolls) */ diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 37e9c93a108..8c664bc1a57 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -45,9 +45,9 @@ #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" - +#ifdef USE_BULLET #include "Bullet-C-Api.h" - +#endif #include "BLI_kdopbvh.h" #include "BKE_collision.h" @@ -313,7 +313,7 @@ gsl_poly_solve_quadratic (double a, double b, double c, * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" * page 4, left column */ -int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) +static int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) { int num_sols = 0; @@ -427,7 +427,7 @@ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3 // w3 is not perfect -void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) +static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -726,7 +726,7 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap return collpair; } -int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +static int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; Cloth *cloth1; @@ -891,7 +891,7 @@ static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, floa } // calculates the distance of 2 edges -float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) +static float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) { float line1[3], line2[3], cross[3]; float length; @@ -1065,7 +1065,7 @@ float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3 return 0; } -int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) +static int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; Cloth *cloth1=NULL; @@ -1275,7 +1275,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat return result; } -int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { Cloth *cloth1; cloth1 = clmd->clothObject; @@ -1296,15 +1296,15 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col // return all collision objects in scene // collision object will exclude self -CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *numcollobj) +Object **get_collisionobjects(Scene *scene, Object *self, int *numcollobj) { Base *base=NULL; - CollisionModifierData **objs = NULL; + Object **objs = NULL; Object *coll_ob = NULL; CollisionModifierData *collmd = NULL; int numobj = 0, maxobj = 100; - objs = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); + objs = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); // check all collision objects for ( base = scene->base.first; base; base = base->next ) { @@ -1330,16 +1330,16 @@ CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *nu { // realloc int oldmax = maxobj; - CollisionModifierData **tmp; + Object **tmp; maxobj *= 2; - tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); - memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); + tmp = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); + memcpy(tmp, objs, sizeof(Object *)*oldmax); MEM_freeN(objs); objs = tmp; } - objs[numobj] = collmd; + objs[numobj] = coll_ob; numobj++; } else @@ -1374,15 +1374,15 @@ CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *nu { // realloc int oldmax = maxobj; - CollisionModifierData **tmp; + Object **tmp; maxobj *= 2; - tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); - memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); + tmp = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); + memcpy(tmp, objs, sizeof(Object *)*oldmax); MEM_freeN(objs); objs = tmp; } - objs[numobj] = collmd; + objs[numobj] = coll_ob; numobj++; } } @@ -1392,7 +1392,98 @@ CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *nu return objs; } -void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) +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; @@ -1405,7 +1496,7 @@ void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModi } } -int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) +static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) { Cloth *cloth = clmd->clothObject; int i=0, j = 0, numfaces = 0, numverts = 0; @@ -1459,7 +1550,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; - CollisionModifierData **collobjs = NULL; + Object **collobjs = NULL; int numcollobj = 0; if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) ) @@ -1498,7 +1589,8 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl // check all collision objects for(i = 0; i < numcollobj; i++) { - CollisionModifierData *collmd = collobjs[i]; + Object *collob= collobjs[i]; + CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); BVHTreeOverlap *overlap = NULL; int result = 0; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e5c0b3947de..8846fe77809 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -685,9 +685,19 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain ct->flag= CONSTRAINT_TAR_TEMP; \ \ if (ct->tar) { \ - if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_BONE; \ - else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_VERT; \ - else ct->type = CONSTRAINT_OBTYPE_OBJECT; \ + if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) { \ + bPoseChannel *pchan= get_pose_channel(ct->tar->pose, ct->subtarget); \ + ct->type = CONSTRAINT_OBTYPE_BONE; \ + ct->rotOrder= (pchan) ? (pchan->rotmode) : EULER_ORDER_DEFAULT; \ + }\ + else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { \ + ct->type = CONSTRAINT_OBTYPE_VERT; \ + ct->rotOrder = EULER_ORDER_DEFAULT; \ + } \ + else {\ + ct->type = CONSTRAINT_OBTYPE_OBJECT; \ + ct->rotOrder= ct->tar->rotmode; \ + } \ } \ \ BLI_addtail(list, ct); \ @@ -1045,6 +1055,7 @@ static void kinematic_new_data (void *cdata) data->weight= (float)1.0; data->orientweight= (float)1.0; data->iterations = 500; + data->dist= (float)1.0; data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS; } @@ -1180,7 +1191,10 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr if (cu->path && cu->path->data) { if ((data->followflag & FOLLOWPATH_STATIC) == 0) { /* animated position along curve depending on time */ - curvetime= bsystem_time(cob->scene, ct->tar, ctime, 0.0) - data->offset; + if (cob->scene) + curvetime= bsystem_time(cob->scene, ct->tar, ctime, 0.0) - data->offset; + else + curvetime= ctime - data->offset; /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, * but this will only work if it actually is animated... @@ -1580,7 +1594,8 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta VECCOPY(loc, cob->matrix[3]); Mat4ToSize(cob->matrix, size); - Mat4ToEulO(ct->matrix, eul, ct->rotOrder); + /* to allow compatible rotations, must get both rotations in the order of the owner... */ + Mat4ToEulO(ct->matrix, eul, cob->rotOrder); Mat4ToEulO(cob->matrix, obeul, cob->rotOrder); if ((data->flag & ROTLIKE_X)==0) @@ -3631,7 +3646,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) /* these we can skip completely (invalid constraints...) */ if (cti == NULL) continue; - if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->flag & (CONSTRAINT_DISABLE|CONSTRAINT_OFF)) continue; /* these constraints can't be evaluated anyway */ if (cti->evaluate_constraint == NULL) continue; /* influence == 0 should be ignored */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index eec3cb73d8a..2ce877bd847 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -68,7 +68,7 @@ /* globals */ /* local */ -int cu_isectLL(float *v1, float *v2, float *v3, float *v4, +static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec); @@ -977,7 +977,7 @@ void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int i } } -void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float *p3, float *p, int it, int stride) +static void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float *p3, float *p, int it, int stride) { /* note that these are not purpendicular to the curve * they need to be rotated for this, @@ -1363,7 +1363,7 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp) } } -int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec) +static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec) { /* return: -1: colliniar @@ -1616,7 +1616,7 @@ static void bevel_list_flip_tangents(BevList *bl) nr= bl->nr; while(nr--) { - if(VecAngle2(bevp0->tan, bevp1->tan) > 90) + if(RAD2DEG(VecAngle2(bevp0->tan, bevp1->tan)) > 90) VecNegf(bevp1->tan); bevp0= bevp1; @@ -1882,7 +1882,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) } } -void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode) +static void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode) { switch(twist_mode) { case CU_TWIST_TANGENT: diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 6a14762e0ed..a8cec6070a0 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -78,6 +78,7 @@ #include "BKE_pointcache.h" #include "BKE_utildefines.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "MEM_guardedalloc.h" @@ -520,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); @@ -553,13 +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; ParticleSettings *part= psys->part; + ListBase *effectors = NULL; + EffectorCache *eff; dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); @@ -591,34 +593,17 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } - psys_end_effectors(psys); - psys_init_effectors(scene, ob, psys->part->eff_group, psys); + 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) { @@ -1606,6 +1591,21 @@ void graph_print_adj_list(void) /* ************************ API *********************** */ +/* mechanism to allow editors to be informed of depsgraph updates, + to do their own updates based on changes... */ +static void (*EditorsUpdateCb)(Main *bmain, ID *id)= NULL; + +void DAG_editors_update_cb(void (*func)(Main *bmain, ID *id)) +{ + EditorsUpdateCb= func; +} + +static void dag_editors_update(Main *bmain, ID *id) +{ + if(EditorsUpdateCb) + EditorsUpdateCb(bmain, id); +} + /* groups with objects in this scene need to be put in the right order as well */ static void scene_sort_groups(Scene *sce) { @@ -2142,30 +2142,58 @@ void DAG_scene_update_flags(Scene *scene, unsigned int lay) } -void DAG_id_flush_update(ID *id, short flag) +static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay) { - Main *bmain= G.main; wmWindowManager *wm; wmWindow *win; - Scene *sce; - Object *obt, *ob= NULL; - short idtype; /* only one scene supported currently, making more scenes work correctly requires changes beyond just the dependency graph */ + *sce= NULL; + *lay= 0; + if((wm= bmain->wm.first)) { - /* if we have a windowmanager, use sce from first window */ + /* if we have a windowmanager, look into windows */ for(win=wm->windows.first; win; win=win->next) { - sce= (win->screen)? win->screen->scene: NULL; - - if(sce) - break; + if(win->screen) { + if(!*sce) *sce= win->screen->scene; + *lay |= BKE_screen_visible_layers(win->screen); + } } } - else + else { /* if not, use the first sce */ - sce= bmain->scene.first; + *sce= bmain->scene.first; + if(*sce) *lay= (*sce)->lay; + + /* XXX for background mode, we should get the scen + from somewhere, for the -S option, but it's in + the context, how to get it here? */ + } +} + +void DAG_ids_flush_update(int time) +{ + Main *bmain= G.main; + Scene *sce; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); + + if(sce) + DAG_scene_flush_update(sce, lay, time); +} + +void DAG_id_flush_update(ID *id, short flag) +{ + Main *bmain= G.main; + Scene *sce; + Object *obt, *ob= NULL; + short idtype; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); if(!id || !sce || !sce->theDag) return; @@ -2173,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) { @@ -2210,13 +2238,27 @@ 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); } /* flush to other objects that depend on this one */ -// XXX if(G.curscreen) -// DAG_scene_flush_update(sce, dag_screen_view3d_layers(), 0); -// else - DAG_scene_flush_update(sce, sce->lay, 0); + DAG_scene_flush_update(sce, lay, 0); } /* recursively descends tree, each node only checked once */ @@ -2251,10 +2293,25 @@ static int parent_check_node(DagNode *node, int curtime) /* all nodes that influence this object get tagged, for calculating the exact position of this object at a given timeframe */ -void DAG_object_update_flags(Scene *sce, Object *ob, unsigned int lay) +void DAG_id_update_flags(ID *id) { + Main *bmain= G.main; + Scene *sce; DagNode *node; DagAdjList *itA; + Object *ob; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); + + if(!id || !sce || !sce->theDag) + return; + + /* objects only currently */ + if(GS(id->name) != ID_OB) + return; + + ob= (Object*)id; /* tag nodes unchecked */ for(node = sce->theDag->DagNode.first; node; node= node->next) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index d87dbc833c5..266a528dc57 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1131,7 +1131,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } -void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) +static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) { if(cu->flag & CU_3D) return; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e3c4f12184e..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,26 +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) { - CollisionModifierData **collobjs = NULL; - int numcollobj = 0, i; + ListBase *colls = colliders; + ColliderCache *col; float norm[3], len = 0.0; - float visibility = 1.0; - - collobjs = get_collisionobjects(scene, ob, &numcollobj); + float visibility = 1.0, absorption = 0.0; - 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) { - CollisionModifierData *collmd = collobjs[i]; + CollisionModifierData *collmd = col->collmd; + + if(col->ob == eff->ob) + continue; if(collmd->bvhtree) { @@ -285,18 +450,21 @@ 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= col->ob->pd->absorption; + // visibility is only between 0 and 1, calculated from 1-absorption - visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01))); + visibility *= CLAMPIS(1.0f-absorption, 0.0f, 1.0f); if(visibility <= 0.0f) break; } } } - - MEM_freeN(collobjs); + + if(!colliders) + free_collider_cache(&colls); return visibility; } @@ -344,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; } @@ -388,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() -------- @@ -525,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 @@ -540,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/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 31f6e2c6067..0ecd1fe912b 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -200,6 +200,85 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array return NULL; } +/* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */ +#define BEZT_BINARYSEARCH_THRESH 0.00001f + +/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_fcurve) + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace) +{ + int start=0, end=arraylen; + int loopbreaker= 0, maxloop= arraylen * 2; + + /* initialise replace-flag first */ + *replace= 0; + + /* sneaky optimisations (don't go through searching process if...): + * - keyframe to be added is to be added out of current bounds + * - keyframe to be added would replace one of the existing ones on bounds + */ + if ((arraylen <= 0) || (array == NULL)) { + printf("Warning: binarysearch_bezt_index() encountered invalid array \n"); + return 0; + } + else { + /* check whether to add before/after/on */ + float framenum; + + /* 'First' Keyframe (when only one keyframe, this case is used) */ + framenum= array[0].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) { + *replace = 1; + return 0; + } + else if (frame < framenum) + return 0; + + /* 'Last' Keyframe */ + framenum= array[(arraylen-1)].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) { + *replace= 1; + return (arraylen - 1); + } + else if (frame > framenum) + return arraylen; + } + + + /* most of the time, this loop is just to find where to put it + * 'loopbreaker' is just here to prevent infinite loops + */ + for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { + /* compute and get midpoint */ + int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */ + float midfra= array[mid].vec[1][0]; + + /* check if exactly equal to midpoint */ + if (IS_EQT(frame, midfra, BEZT_BINARYSEARCH_THRESH)) { + *replace = 1; + return mid; + } + + /* repeat in upper/lower half */ + if (frame > midfra) + start= mid + 1; + else if (frame < midfra) + end= mid - 1; + } + + /* print error if loop-limit exceeded */ + if (loopbreaker == (maxloop-1)) { + printf("Error: binarysearch_bezt_index() was taking too long \n"); + + // include debug info + printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); + } + + /* not found, so return where to place it */ + return start; +} + /* Calculate the extents of F-Curve's data */ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax) { @@ -916,7 +995,7 @@ void correct_bezpart (float *v1, float *v2, float *v3, float *v4) } /* find root ('zero') */ -int findzero (float x, float q0, float q1, float q2, float q3, float *o) +static int findzero (float x, float q0, float q1, float q2, float q3, float *o) { double c0, c1, c2, c3, a, b, c, p, q, d, t, phi; int nr= 0; @@ -1010,7 +1089,7 @@ int findzero (float x, float q0, float q1, float q2, float q3, float *o) } } -void berekeny (float f1, float f2, float f3, float f4, float *o, int b) +static void berekeny (float f1, float f2, float f3, float f4, float *o, int b) { float t, c0, c1, c2, c3; int a; @@ -1026,7 +1105,8 @@ void berekeny (float f1, float f2, float f3, float f4, float *o, int b) } } -void berekenx (float *f, float *o, int b) +#if 0 +static void berekenx (float *f, float *o, int b) { float t, c0, c1, c2, c3; int a; @@ -1041,6 +1121,7 @@ void berekenx (float *f, float *o, int b) o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3; } } +#endif /* -------------------------- */ diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index ad9e481ffd2..aa163b821c8 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -80,6 +80,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) if(!fss) return; + fss->fmd = fluidmd; fss->type = OB_FLUIDSIM_ENABLE; fss->show_advancedoptions = 0; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 411b2448dea..4e05bf45d3d 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -129,7 +129,7 @@ wcsleninu8(wchar_t *src) } int -utf8slen(char *src) +static utf8slen(char *src) { int size = 0, index = 0; unsigned char c; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index cdb175ed661..09d150341b2 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -277,7 +277,7 @@ static Image *image_alloc(const char *name, short source, short type) ima->xrep= ima->yrep= 1; ima->aspx= ima->aspy= 1.0; - ima->gen_x= 256; ima->gen_y= 256; + ima->gen_x= 1024; ima->gen_y= 1024; ima->gen_type= 1; /* no defines yet? */ ima->source= source; @@ -1472,9 +1472,11 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) iuser->ok= 1; break; case IMA_SIGNAL_SRC_CHANGE: - if(ima->type==IMA_TYPE_MULTILAYER) - image_free_buffers(ima); - else if(ima->source==IMA_SRC_GENERATED) { + if(ima->type == IMA_TYPE_UV_TEST) + if(ima->source != IMA_SRC_GENERATED) + ima->type= IMA_TYPE_IMAGE; + + if(ima->source==IMA_SRC_GENERATED) { if(ima->gen_x==0 || ima->gen_y==0) { ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); if(ibuf) { @@ -1483,6 +1485,9 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } } + + image_free_buffers(ima); + ima->ok= 1; if(iuser) iuser->ok= 1; @@ -1559,15 +1564,22 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) return rpass; } -RenderResult *BKE_image_get_renderresult(struct Scene *scene, Image *ima) +RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, Image *ima) { if(ima->rr) return ima->rr; - if(ima->type==IMA_TYPE_R_RESULT) - return RE_GetResult(RE_GetRender(scene->id.name)); + else if(ima->type==IMA_TYPE_R_RESULT) + return RE_AcquireResultRead(RE_GetRender(scene->id.name)); return NULL; } +void BKE_image_release_renderresult(struct Scene *scene, Image *ima) +{ + if(ima->rr); + else if(ima->type==IMA_TYPE_R_RESULT) + RE_ReleaseResult(RE_GetRender(scene->id.name)); +} + /* after imbuf load, openexr type can return with a exrhandle open */ /* in that case we have to build a render-result */ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) @@ -1868,16 +1880,25 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) /* showing RGBA result itself (from compo/sequence) or like exr, using layers etc */ /* always returns a single ibuf, also during render progress */ -static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) +static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_r) { Render *re= NULL; RenderResult *rr= NULL; + /* if we the caller is not going to release the lock, don't give the image */ + if(!lock_r) + return NULL; + if(iuser && iuser->scene) { re= RE_GetRender(iuser->scene->id.name); - rr= RE_GetResult(re); + rr= RE_AcquireResultRead(re); + + /* release is done in BKE_image_release_ibuf using lock_r */ + *lock_r= re; } - if(rr==NULL) return NULL; + + if(rr==NULL) + return NULL; if(RE_RenderInProgress(re)) { ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); @@ -1888,6 +1909,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, IB_rect, 0); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } + return ibuf; } else { @@ -1902,7 +1924,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) pass= (iuser)? iuser->pass: 0; /* this gives active layer, composite or seqence result */ - RE_GetResultImage(RE_GetRender(iuser->scene->id.name), &rres); + RE_AcquireResultImage(RE_GetRender(iuser->scene->id.name), &rres); rect= (unsigned int *)rres.rect32; rectf= rres.rectf; dither= iuser->scene->r.dither_intensity; @@ -1949,10 +1971,14 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf->zbuf_float= rres.rectz; ibuf->flags |= IB_zbuffloat; ibuf->dither= dither; - + + RE_ReleaseResultImage(re); + ima->ok= IMA_OK_LOADED; return ibuf; } + + RE_ReleaseResultImage(re); } return NULL; @@ -2006,8 +2032,9 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame } /* Checks optional ImageUser and verifies/creates ImBuf. */ -/* returns ibuf */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +/* use this one if you want to get a render result in progress, + * if not, use BKE_image_get_ibuf which doesn't require a release */ +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf= NULL; float color[] = {0, 0, 0, 1}; @@ -2023,6 +2050,9 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. * That means, the last two steps must be, 1) add the ibuf to the list and * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ + + if(lock_r) + *lock_r= NULL; /* quick reject tests */ if(ima==NULL) @@ -2090,16 +2120,17 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) else if(ima->source == IMA_SRC_GENERATED) { /* generated is: ibuf is allocated dynamically */ /* UV testgrid or black or solid etc */ - if(ima->gen_x==0) ima->gen_x= 256; - if(ima->gen_y==0) ima->gen_y= 256; + if(ima->gen_x==0) ima->gen_x= 1024; + if(ima->gen_y==0) ima->gen_y= 1024; ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 0, ima->gen_type, color); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok= IMA_OK_LOADED; } else if(ima->source == IMA_SRC_VIEWER) { if(ima->type==IMA_TYPE_R_RESULT) { - /* always verify entirely */ - ibuf= image_get_render_result(ima, iuser); + /* always verify entirely, and potentially + returns pointer to release later */ + ibuf= image_get_render_result(ima, iuser, lock_r); } else if(ima->type==IMA_TYPE_COMPOSITE) { /* Composite Viewer, all handled in compositor */ @@ -2121,6 +2152,17 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) return ibuf; } +void BKE_image_release_ibuf(Image *ima, void *lock) +{ + /* for getting image during threaded render, need to release */ + if(lock) + RE_ReleaseResult(lock); +} + +ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +{ + return BKE_image_acquire_ibuf(ima, iuser, NULL); +} void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) { @@ -2170,3 +2212,103 @@ void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) } } +/* + Produce image export path. + + Fails returning 0 if image filename is empty or if destination path + matches image path (i.e. both are the same file). + + Trailing slash in dest_dir is optional. + + Logic: + + - if an image is "below" current .blend file directory, rebuild the + same dir structure in dest_dir + + For example //textures/foo/bar.png becomes + [dest_dir]/textures/foo/bar.png. + + - if an image is not "below" current .blend file directory, + disregard it's path and copy it in the same directory where 3D file + goes. + + For example //../foo/bar.png becomes [dest_dir]/bar.png. + + This logic will help ensure that all image paths are relative and + that a user gets his images in one place. It'll also provide + consistent behaviour across exporters. + */ +int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size) +{ + char path[FILE_MAX]; + char dir[FILE_MAX]; + char base[FILE_MAX]; + char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */ + char dest_path[FILE_MAX]; + char rel_dir[FILE_MAX]; + int len; + + if (abs) + abs[0]= 0; + + if (rel) + rel[0]= 0; + + BLI_split_dirfile_basic(G.sce, blend_dir, NULL); + + if (!strlen(im->name)) { + if (G.f & G_DEBUG) printf("Invalid image type.\n"); + return 0; + } + + BLI_strncpy(path, im->name, sizeof(path)); + + /* expand "//" in filename and get absolute path */ + BLI_convertstringcode(path, G.sce); + + /* get the directory part */ + BLI_split_dirfile_basic(path, dir, base); + + len= strlen(blend_dir); + + rel_dir[0] = 0; + + /* if image is "below" current .blend file directory */ + if (!strncmp(path, blend_dir, len)) { + + /* if image is _in_ current .blend file directory */ + if (!strcmp(dir, blend_dir)) { + BLI_join_dirfile(dest_path, dest_dir, base); + } + /* "below" */ + else { + /* rel = image_path_dir - blend_dir */ + BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir)); + + BLI_join_dirfile(dest_path, dest_dir, rel_dir); + BLI_join_dirfile(dest_path, dest_path, base); + } + + } + /* image is out of current directory */ + else { + BLI_join_dirfile(dest_path, dest_dir, base); + } + + if (abs) + BLI_strncpy(abs, dest_path, abs_size); + + if (rel) { + strncat(rel, rel_dir, rel_size); + strncat(rel, base, rel_size); + } + + /* return 2 if src=dest */ + if (!strcmp(path, dest_path)) { + if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path); + return 2; + } + + return 1; +} + diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 0bce71b57eb..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" @@ -43,7 +44,7 @@ #include <windows.h> static LARGE_INTEGER _itstart, _itend; static LARGE_INTEGER ifreq; -void itstart(void) +static void itstart(void) { static int first = 1; if(first) { @@ -52,7 +53,7 @@ void itstart(void) } QueryPerformanceCounter(&_itstart); } -void itend(void) +static void itend(void) { QueryPerformanceCounter(&_itend); } @@ -74,7 +75,7 @@ double itval() { gettimeofday(&_itstart, &itz); } -void itend(void) +static void itend(void) { gettimeofday(&_itend,&itz); } @@ -155,7 +156,7 @@ DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vec /* printf vector[3] on console: for debug output */ -void print_fvector(float m3[3]) +static void print_fvector(float m3[3]) { printf("%f\n%f\n%f\n\n",m3[0],m3[1],m3[2]); } @@ -297,7 +298,7 @@ DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], f // 3x3 matrix /////////////////////////// /* printf 3x3 matrix on console: for debug output */ -void print_fmatrix(float m3[3][3]) +static void print_fmatrix(float m3[3][3]) { printf("%f\t%f\t%f\n",m3[0][0],m3[0][1],m3[0][2]); printf("%f\t%f\t%f\n",m3[1][0],m3[1][1],m3[1][2]); @@ -496,7 +497,8 @@ DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float fro // SPARSE SYMMETRIC big matrix with 3x3 matrix entries /////////////////////////// /* printf a big matrix on console: for debug output */ -void print_bfmatrix(fmatrix3x3 *m3) +#if 0 +static void print_bfmatrix(fmatrix3x3 *m3) { unsigned int i = 0; @@ -505,6 +507,8 @@ void print_bfmatrix(fmatrix3x3 *m3) print_fmatrix(m3[i].m); } } +#endif + /* create big matrix */ DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs) { @@ -887,7 +891,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) } } -int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) +static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) { // Solves for unknown X in equation AX=B unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100; @@ -970,7 +974,7 @@ DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv) } /* // version 1.3 -int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) +static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100; float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0; @@ -1038,7 +1042,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma } */ // version 1.4 -int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI) +static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI) { unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100; float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0, tol = 0; @@ -1391,7 +1395,7 @@ static void CalcFloat4( float *v1, float *v2, float *v3, float *v4, float *n) n[2]= n1[0]*n2[1]-n1[1]*n2[0]; } -float calculateVertexWindForce(float wind[3], float vertexnormal[3]) +static float calculateVertexWindForce(float wind[3], float vertexnormal[3]) { return (INPR(wind, vertexnormal)); } @@ -1417,7 +1421,6 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, int i = 0; int j = 0; int k = 0; - lfVector temp; INIT_MINMAX(gmin, gmax); @@ -1480,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); @@ -1523,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++) @@ -1595,7 +1601,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, // printf("\n"); } -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI) +static void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI) { unsigned int numverts = dFdV[0].vcount; @@ -1654,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); @@ -1739,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/ipo.c b/source/blender/blenkernel/intern/ipo.c index 2f0e0931588..6717f5560be 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -213,17 +213,17 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index) *array_index= 2; return "delta_location"; case OB_ROT_X: - *array_index= 0; return "rotation"; + *array_index= 0; return "rotation_euler"; case OB_ROT_Y: - *array_index= 1; return "rotation"; + *array_index= 1; return "rotation_euler"; case OB_ROT_Z: - *array_index= 2; return "rotation"; + *array_index= 2; return "rotation_euler"; case OB_DROT_X: - *array_index= 0; return "delta_rotation"; + *array_index= 0; return "delta_rotation_euler"; case OB_DROT_Y: - *array_index= 1; return "delta_rotation"; + *array_index= 1; return "delta_rotation_euler"; case OB_DROT_Z: - *array_index= 2; return "delta_rotation"; + *array_index= 2; return "delta_rotation_euler"; case OB_SIZE_X: *array_index= 0; return "scale"; @@ -281,23 +281,23 @@ static char *pchan_adrcodes_to_paths (int adrcode, int *array_index) /* result depends on adrcode */ switch (adrcode) { case AC_QUAT_W: - *array_index= 0; return "rotation"; + *array_index= 0; return "rotation_quaternion"; case AC_QUAT_X: - *array_index= 1; return "rotation"; + *array_index= 1; return "rotation_quaternion"; case AC_QUAT_Y: - *array_index= 2; return "rotation"; + *array_index= 2; return "rotation_quaternion"; case AC_QUAT_Z: - *array_index= 3; return "rotation"; + *array_index= 3; return "rotation_quaternion"; case AC_EUL_X: - *array_index= 0; return "euler_rotation"; + *array_index= 0; return "rotation_euler"; case AC_EUL_Y: - *array_index= 1; return "euler_rotation"; + *array_index= 1; return "rotation_euler"; case AC_EUL_Z: - *array_index= 2; return "euler_rotation"; + *array_index= 2; return "rotation_euler"; case -1: /* special case for euler-rotations used by old drivers */ - *array_index= 0; return "euler_rotation"; + *array_index= 0; return "rotation_euler"; case AC_LOC_X: *array_index= 0; return "location"; @@ -820,7 +820,7 @@ static char *particle_adrcodes_to_paths (int adrcode, int *array_index) * - array_index - index in property's array (if applicable) to use * - return - the allocated path... */ -char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) +static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) { DynStr *path= BLI_dynstr_new(); char *propname=NULL, *rpath=NULL; @@ -1047,10 +1047,6 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver) } } - - /* free old driver */ - MEM_freeN(idriver); - /* return the new one */ return cdriver; } @@ -1122,11 +1118,9 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha /* allocate memory for a new F-Curve */ fcu= MEM_callocN(sizeof(FCurve), "FCurve"); - /* convert driver - will free the old one... */ - if (icu->driver) { + /* convert driver */ + if (icu->driver) fcu->driver= idriver_to_cdriver(icu->driver); - icu->driver= NULL; - } /* copy flags */ if (icu->flag & IPO_VISIBLE) fcu->flag |= FCURVE_VISIBLE; @@ -1214,6 +1208,9 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha /* interpolation can only be constant... */ dst->ipo= BEZT_IPO_CONST; + /* 'hide' flag is now used for keytype - only 'keyframes' existed before */ + dst->hide= BEZT_KEYTYPE_KEYFRAME; + /* correct values, by checking if the flag of interest is set */ if ( ((int)(dst->vec[1][1])) & (abp->bit) ) dst->vec[0][1]= dst->vec[1][1]= dst->vec[2][1] = 1.0f; @@ -1230,10 +1227,6 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha /* add new F-Curve to list */ fcurve_add_to_list(groups, list, fcurve, actname); } - - /* free old data of curve now that it's no longer needed for converting any more curves */ - if (icu->bezt) MEM_freeN(icu->bezt); - if (icu->bp) MEM_freeN(icu->bezt); } else { /* get rna-path @@ -1264,6 +1257,9 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha if (icu->ipo != IPO_MIXED) dst->ipo= icu->ipo; + /* 'hide' flag is now used for keytype - only 'keyframes' existed before */ + dst->hide= BEZT_KEYTYPE_KEYFRAME; + /* correct values for euler rotation curves - they were degrees/10 */ // XXX for now, just make them into radians as RNA sets/reads directly in that form if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) || @@ -1296,9 +1292,6 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha } } } - - /* free this data now */ - MEM_freeN(icu->bezt); } else if (icu->bp) { /* TODO: need to convert from BPoint type to the more compact FPoint type... but not priority, since no data used this */ @@ -1319,7 +1312,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha */ static void ipo_to_animato (Ipo *ipo, char actname[], char constname[], ListBase *animgroups, ListBase *anim, ListBase *drivers) { - IpoCurve *icu, *icn; + IpoCurve *icu; /* sanity check */ if (ELEM3(NULL, ipo, anim, drivers)) @@ -1341,25 +1334,44 @@ static void ipo_to_animato (Ipo *ipo, char actname[], char constname[], ListBase } /* loop over IPO-Curves, freeing as we progress */ - for (icu= ipo->curve.first; icu; icu= icn) { - /* get link to next (for later) */ - icn= icu->next; - + for (icu= ipo->curve.first; icu; icu= icu->next) { /* Since an IPO-Curve may end up being made into many F-Curves (i.e. bitflag curves), * we figure out the best place to put the channel, then tell the curve-converter to just dump there */ if (icu->driver) { /* Blender 2.4x allowed empty drivers, but we don't now, since they cause more trouble than they're worth */ - if ((icu->driver->ob) || (icu->driver->type == IPO_DRIVER_TYPE_PYTHON)) + if ((icu->driver->ob) || (icu->driver->type == IPO_DRIVER_TYPE_PYTHON)) { icu_to_fcurves(NULL, drivers, icu, actname, constname); - else + } + else { MEM_freeN(icu->driver); + icu->driver= NULL; + } } else icu_to_fcurves(animgroups, anim, icu, actname, constname); + } + + /* if this IPO block doesn't have any users after this one, free... */ + ipo->id.us--; + if ( (ipo->id.us == 0) || ((ipo->id.us == 1) && (ipo->id.flag & LIB_FAKEUSER)) ) + { + IpoCurve *icn; - /* free this IpoCurve now that it's been converted */ - BLI_freelinkN(&ipo->curve, icu); + for (icu= ipo->curve.first; icu; icu= icn) { + icn= icu->next; + + /* free driver */ + if (icu->driver) + MEM_freeN(icu->driver); + + /* free old data of curve now that it's no longer needed for converting any more curves */ + if (icu->bezt) MEM_freeN(icu->bezt); + if (icu->bp) MEM_freeN(icu->bezt); + + /* free this IPO-Curve */ + BLI_freelinkN(&ipo->curve, icu); + } } } diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 730a12bea09..a957be4704c 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -524,30 +524,13 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp) { Curve *cu= par->data; - float fac, loc[4], dir[3], cent[3], radius; - short upflag, index; - - if(axis==MOD_CURVE_POSX || axis==MOD_CURVE_NEGX) { - upflag= OB_POSZ; - cent[0]= 0.0; - cent[1]= co[1]; - cent[2]= co[2]; - index= 0; - } - else if(axis==MOD_CURVE_POSY || axis==MOD_CURVE_NEGY) { - upflag= OB_POSZ; - cent[0]= co[0]; - cent[1]= 0.0; - cent[2]= co[2]; - index= 1; - } - else { - upflag= OB_POSY; - cent[0]= co[0]; - cent[1]= co[1]; - cent[2]= 0.0; - index= 2; - } + float fac, loc[4], dir[3], new_quat[4], radius; + short /*upflag, */ index; + + index= axis-1; + if(index>2) + index -= 3; /* negative */ + /* to be sure, mostly after file load */ if(cu->path==NULL) { makeDispListCurveTypes(scene, par, 0); @@ -555,7 +538,7 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C } /* options */ - if(ELEM3(axis, OB_NEGX, OB_NEGY, OB_NEGZ)) { + if(ELEM3(axis, OB_NEGX+1, OB_NEGY+1, OB_NEGZ+1)) { /* OB_NEG# 0-5, MOD_CURVE_POS# 1-6 */ if(cu->flag & CU_STRETCH) fac= (-co[index]-cd->dmax[index])/(cd->dmax[index] - cd->dmin[index]); else @@ -579,9 +562,10 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C } #endif // XXX old animation system - if( where_on_path_deform(par, fac, loc, dir, NULL, &radius)) { /* returns OK */ - float q[4], mat[3][3], quat[4]; - + if( where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */ + float quat[4], cent[3]; + +#if 0 // XXX - 2.4x Z-Up, Now use bevel tilt. if(cd->no_rot_axis) /* set by caller */ dir[cd->no_rot_axis-1]= 0.0f; @@ -597,22 +581,104 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C q[2]= -fac*dir[1]; q[3]= -fac*dir[2]; QuatMul(quat, q, quat); - } - QuatToMat3(quat, mat); - - if(cu->flag & CU_PATH_RADIUS) { - float tmat[3][3], rmat[3][3]; - Mat3Scale(tmat, radius); - Mat3MulMat3(rmat, mat, tmat); - Mat3CpyMat3(mat, rmat); } +#endif - /* local rotation */ - Mat3MulVecfl(mat, cent); + + static float q_x90d[4] = {0.70710676908493, 0.70710676908493, 0.0, 0.0}; // float rot_axis[3]= {1,0,0}; AxisAngleToQuat(q, rot_axis, 90 * (M_PI / 180)); + static float q_y90d[4] = {0.70710676908493, 0.0, 0.70710676908493, 0.0}; // float rot_axis[3]= {0,1,0}; AxisAngleToQuat(q, rot_axis, 90 * (M_PI / 180)); + static float q_z90d[4] = {0.70710676908493, 0.0, 0.0, 0.70710676908493}; // float rot_axis[3]= {0,0,2}; AxisAngleToQuat(q, rot_axis, 90 * (M_PI / 180)); + + static float q_nx90d[4] = {0.70710676908493, -0.70710676908493, 0.0, 0.0}; // float rot_axis[3]= {1,0,0}; AxisAngleToQuat(q, rot_axis, -90 * (M_PI / 180)); + static float q_ny90d[4] = {0.70710676908493, 0.0, -0.70710676908493, 0.0}; // float rot_axis[3]= {0,1,0}; AxisAngleToQuat(q, rot_axis, -90 * (M_PI / 180)); + static float q_nz90d[4] = {0.70710676908493, 0.0, 0.0, -0.70710676908493}; // float rot_axis[3]= {0,0,2}; AxisAngleToQuat(q, rot_axis, -90 * (M_PI / 180)); + + + if(cd->no_rot_axis) { /* set by caller */ + + /* this is not exactly the same as 2.4x, since the axis is having rotation removed rather then + * changing the axis before calculating the tilt but serves much the same purpose */ + float dir_flat[3]={0,0,0}, q[4]; + VECCOPY(dir_flat, dir); + dir_flat[cd->no_rot_axis-1]= 0.0f; + + Normalize(dir); + Normalize(dir_flat); + + RotationBetweenVectorsToQuat(q, dir, dir_flat); /* Could this be done faster? */ + + QuatMul(new_quat, q, new_quat); + } + + + /* Logic for 'cent' orientation * + * + * The way 'co' is copied to 'cent' may seem to have no meaning, but it does. + * + * Use a curve modifier to stretch a cube out, color each side RGB, positive side light, negative dark. + * view with X up (default), from the angle that you can see 3 faces RGB colors (light), anti-clockwise + * Notice X,Y,Z Up all have light colors and each ordered CCW. + * + * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell + * */ + + switch(axis) { + case MOD_CURVE_POSX: + QuatMul(quat, new_quat, q_y90d); + + cent[0]= 0.0; + cent[1]= co[2]; + cent[2]= co[1]; + break; + case MOD_CURVE_NEGX: + QuatMul(quat, new_quat, q_ny90d); + + cent[0]= 0.0; + cent[1]= -co[1]; + cent[2]= co[2]; + + break; + case MOD_CURVE_POSY: + QuatMul(quat, new_quat, q_x90d); + + cent[0]= co[2]; + cent[1]= 0.0; + cent[2]= -co[0]; + break; + case MOD_CURVE_NEGY: + QuatMul(quat, new_quat, q_nx90d); + + cent[0]= -co[0]; + cent[1]= 0.0; + cent[2]= -co[2]; + break; + case MOD_CURVE_POSZ: + QuatMul(quat, new_quat, q_z90d); + + cent[0]= co[1]; + cent[1]= -co[0]; + cent[2]= 0.0; + break; + case MOD_CURVE_NEGZ: + QuatMul(quat, new_quat, q_nz90d); + + cent[0]= co[0]; + cent[1]= -co[1]; + cent[2]= 0.0; + break; + } + + /* scale if enabled */ + if(cu->flag & CU_PATH_RADIUS) + VecMulf(cent, radius); + /* local rotation */ + NormalQuat(quat); + QuatMulVecf(quat, cent); + /* translation */ VECADD(co, cent, loc); - + if(quatp) QUATCOPY(quatp, quat); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 02d92a62b59..0f65be207d9 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -455,6 +455,15 @@ void flag_all_listbases_ids(short flag, short value) while(a--) flag_listbase_ids(lbarray[a], flag, value); } +void recalc_all_library_objects(Main *main) +{ + Object *ob; + + /* flag for full recalc */ + for(ob=main->object.first; ob; ob=ob->id.next) + if(ob->id.lib) + ob->recalc |= OB_RECALC; +} /* note: MAX_LIBARRAY define should match this code */ int set_listbasepointers(Main *main, ListBase **lb) @@ -631,42 +640,15 @@ void *alloc_libblock(ListBase *lb, short type, const char *name) } /* by spec, animdata is first item after ID */ -/* we still read ->adt itself, to ensure compiler warns when it doesnt exist */ +/* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */ static void id_copy_animdata(ID *id) { - switch(GS(id->name)) { - case ID_OB: - ((Object *)id)->adt= BKE_copy_animdata(((Object *)id)->adt); - break; - case ID_CU: - ((Curve *)id)->adt= BKE_copy_animdata(((Curve *)id)->adt); - break; - case ID_CA: - ((Camera *)id)->adt= BKE_copy_animdata(((Camera *)id)->adt); - break; - case ID_KE: - ((Key *)id)->adt= BKE_copy_animdata(((Key *)id)->adt); - break; - case ID_LA: - ((Lamp *)id)->adt= BKE_copy_animdata(((Lamp *)id)->adt); - break; - case ID_MA: - ((Material *)id)->adt= BKE_copy_animdata(((Material *)id)->adt); - break; - case ID_NT: - ((bNodeTree *)id)->adt= BKE_copy_animdata(((bNodeTree *)id)->adt); - break; - case ID_SCE: - ((Scene *)id)->adt= BKE_copy_animdata(((Scene *)id)->adt); - break; - case ID_TE: - ((Tex *)id)->adt= BKE_copy_animdata(((Tex *)id)->adt); - break; - case ID_WO: - ((World *)id)->adt= BKE_copy_animdata(((World *)id)->adt); - break; - } + AnimData *adt= BKE_animdata_from_id(id); + if (adt) { + IdAdtTemplate *iat = (IdAdtTemplate *)id; + iat->adt= BKE_copy_animdata(iat->adt); + } } /* used everywhere in blenkernel and text.c */ @@ -696,8 +678,9 @@ void *copy_libblock(void *rt) id->newid= idn; idn->flag |= LIB_NEW; if (id->properties) idn->properties = IDP_CopyProperty(id->properties); - - id_copy_animdata(id); + + /* the duplicate should get a copy of the animdata */ + id_copy_animdata(idn); return idn; } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index e6f9ac2f404..cbd306f6d87 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -159,9 +159,9 @@ void init_material(Material *ma) ma->sss_radius[0]= 1.0f; ma->sss_radius[1]= 1.0f; ma->sss_radius[2]= 1.0f; - ma->sss_col[0]= 0.8f; - ma->sss_col[1]= 0.8f; - ma->sss_col[2]= 0.8f; + ma->sss_col[0]= 1.0f; + ma->sss_col[1]= 1.0f; + ma->sss_col[2]= 1.0f; ma->sss_error= 0.05f; ma->sss_scale= 0.1f; ma->sss_ior= 1.3f; @@ -172,15 +172,15 @@ void init_material(Material *ma) ma->vol.density = 1.0f; ma->vol.emission = 0.0f; - ma->vol.absorption = 1.0f; ma->vol.scattering = 1.0f; + ma->vol.reflection = 1.0f; + ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f; + ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f; ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f; - ma->vol.absorption_col[0] = ma->vol.absorption_col[1] = ma->vol.absorption_col[2] = 0.0f; ma->vol.density_scale = 1.0f; ma->vol.depth_cutoff = 0.01f; ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; ma->vol.stepsize = 0.2f; - ma->vol.shade_stepsize = 0.2f; ma->vol.shade_type = MA_VOL_SHADE_SINGLE; ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; ma->vol.precache_resolution = 50; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index c92eda6d169..431543f8dbd 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -542,7 +542,8 @@ void set_mesh(Object *ob, Mesh *me) if(ob->type==OB_MESH) { old= ob->data; - old->id.us--; + if (old) + old->id.us--; ob->data= me; id_us_plus((ID *)me); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index f06173264ee..3b47c2f1830 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -214,7 +214,7 @@ static void curveModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->name, cmd->name, 32); } -CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md) { CurveModifierData *cmd = (CurveModifierData *)md; CustomDataMask dataMask = 0; @@ -290,7 +290,7 @@ static void latticeModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tlmd->name, lmd->name, 32); } -CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md) { LatticeModifierData *lmd = (LatticeModifierData *)md; CustomDataMask dataMask = 0; @@ -1104,7 +1104,7 @@ static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, Sc } } -float vertarray_size(MVert *mvert, int numVerts, int axis) +static float vertarray_size(MVert *mvert, int numVerts, int axis) { int i; float min_co, max_co; @@ -1771,7 +1771,7 @@ static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, S /* finds the best possible flipped name. For renaming; check for unique names afterwards */ /* if strip_number: removes number extensions */ -void vertgroup_flip_name (char *name, int strip_number) +static void vertgroup_flip_name (char *name, int strip_number) { int len; char prefix[128]={""}; /* The part before the facing */ @@ -3401,7 +3401,7 @@ static void bevelModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32); } -CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md) { BevelModifierData *bmd = (BevelModifierData *)md; CustomDataMask dataMask = 0; @@ -3481,7 +3481,7 @@ static void displaceModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32); } -CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; CustomDataMask dataMask = 0; @@ -3825,7 +3825,7 @@ static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target) tumd->aspecty = umd->aspecty; } -CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -4278,7 +4278,7 @@ static void smoothModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tsmd->defgrp_name, smd->defgrp_name, 32); } -int smoothModifier_isDisabled(ModifierData *md) +static int smoothModifier_isDisabled(ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData*) md; short flag; @@ -4291,7 +4291,7 @@ int smoothModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData *)md; CustomDataMask dataMask = 0; @@ -4508,7 +4508,7 @@ static void castModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32); } -int castModifier_isDisabled(ModifierData *md) +static int castModifier_isDisabled(ModifierData *md) { CastModifierData *cmd = (CastModifierData*) md; short flag; @@ -4520,7 +4520,7 @@ int castModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md) { CastModifierData *cmd = (CastModifierData *)md; CustomDataMask dataMask = 0; @@ -5151,7 +5151,7 @@ static void waveModifier_updateDepgraph( } } -CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md) { WaveModifierData *wmd = (WaveModifierData *)md; CustomDataMask dataMask = 0; @@ -5487,7 +5487,7 @@ static void armatureModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tamd->defgrp_name, amd->defgrp_name, 32); } -CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -5602,7 +5602,7 @@ static void hookModifier_copyData(ModifierData *md, ModifierData *target) strncpy(thmd->subtarget, hmd->subtarget, 32); } -CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md) { HookModifierData *hmd = (HookModifierData *)md; CustomDataMask dataMask = 0; @@ -5947,7 +5947,7 @@ static void clothModifier_updateDepgraph( } } -CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -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); @@ -6371,7 +6376,7 @@ static DerivedMesh *booleanModifier_applyModifier( return derivedData; } -CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE); @@ -6419,7 +6424,7 @@ static void particleSystemModifier_copyData(ModifierData *md, ModifierData *targ tpsmd->psys = psmd->psys; } -CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md) { ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; CustomDataMask dataMask = 0; @@ -6601,6 +6606,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( { DerivedMesh *dm = derivedData, *result; ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md; + ParticleSimulationData sim; ParticleSystem * psys=0; ParticleData *pa=0, *pars=0; MFace *mface, *orig_mface; @@ -6635,6 +6641,11 @@ static DerivedMesh * particleInstanceModifier_applyModifier( if(totpart==0) return derivedData; + sim.scene = md->scene; + sim.ob = pimd->ob; + sim.psys = psys; + sim.psmd = psys_get_modifier(pimd->ob, psys); + if(pimd->flag & eParticleInstanceFlag_UseSize) { int p; float *si; @@ -6662,7 +6673,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( maxvert=totvert*totpart; maxface=totface*totpart; - psys->lattice=psys_get_lattice(md->scene, ob, psys); + psys->lattice=psys_get_lattice(&sim); if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){ @@ -6712,7 +6723,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( mv->co[axis] = 0.0; } - psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1); + psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1); Normalize(state.vel); @@ -6734,7 +6745,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( } else{ state.time=-1.0; - psys_get_particle_state(md->scene, pimd->ob, psys, first_particle + i/totvert, &state,1); + psys_get_particle_state(&sim, first_particle + i/totvert, &state,1); } QuatMulVecf(state.rot,mv->co); @@ -6832,7 +6843,7 @@ static int explodeModifier_dependsOnTime(ModifierData *md) { return 1; } -CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md) { ExplodeModifierData *emd= (ExplodeModifierData*) md; CustomDataMask dataMask = 0; @@ -7416,6 +7427,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, DerivedMesh *explode, *dm=to_explode; MFace *mf=0; ParticleSettings *part=psmd->psys->part; + ParticleSimulationData sim = {scene, ob, psmd->psys, psmd}; ParticleData *pa=NULL, *pars=psmd->psys->particles; ParticleKey state; EdgeHash *vertpahash; @@ -7431,7 +7443,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, totvert= dm->getNumVerts(dm); totpart= psmd->psys->totpart; - timestep= psys_get_timestep(part); + timestep= psys_get_timestep(&sim); //if(part->flag & PART_GLOB_TIME) cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0); @@ -7474,7 +7486,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, /* getting back to object space */ Mat4Invert(imat,ob->obmat); - psmd->psys->lattice = psys_get_lattice(scene, ob, psmd->psys); + psmd->psys->lattice = psys_get_lattice(&sim); /* duplicate & displace vertices */ ehi= BLI_edgehashIterator_new(vertpahash); @@ -7502,7 +7514,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, Mat4MulVecfl(ob->obmat,loc0); state.time=cfra; - psys_get_particle_state(scene, ob, psmd->psys, i, &state,1); + psys_get_particle_state(&sim, i, &state, 1); vertco=CDDM_get_vert(explode,v)->co; @@ -7591,7 +7603,7 @@ static DerivedMesh * explodeModifier_applyModifier( { DerivedMesh *dm = derivedData; ExplodeModifierData *emd= (ExplodeModifierData*) md; - ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md);; + ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md); if(psmd){ ParticleSystem * psys=psmd->psys; @@ -7746,7 +7758,7 @@ static void meshdeformModifier_copyData(ModifierData *md, ModifierData *target) tmmd->object = mmd->object; } -CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; CustomDataMask dataMask = 0; @@ -8126,7 +8138,7 @@ static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target) tsmd->subsurfLevels = smd->subsurfLevels; } -CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; CustomDataMask dataMask = 0; @@ -8503,6 +8515,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->initData = smoothModifier_initData; mti->copyData = smoothModifier_copyData; mti->requiredDataMask = smoothModifier_requiredDataMask; + mti->isDisabled = smoothModifier_isDisabled; mti->deformVerts = smoothModifier_deformVerts; mti->deformVertsEM = smoothModifier_deformVertsEM; @@ -8513,6 +8526,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->initData = castModifier_initData; mti->copyData = castModifier_copyData; mti->requiredDataMask = castModifier_requiredDataMask; + mti->isDisabled = castModifier_isDisabled; mti->foreachObjectLink = castModifier_foreachObjectLink; mti->updateDepgraph = castModifier_updateDepgraph; mti->deformVerts = castModifier_deformVerts; @@ -9137,19 +9151,6 @@ int modifiers_indexInObject(Object *ob, ModifierData *md_seek) return i; } -int modifiers_usesPointCache(Object *ob) -{ - ModifierData *md = ob->modifiers.first; - - for (; md; md=md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (mti->flags & eModifierTypeFlag_UsesPointCache) { - return 1; - } - } - return 0; -} - void modifier_freeTemporaryData(ModifierData *md) { if(md->type == eModifierType_Armature) { diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 37e7e55050a..e7159b82d49 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -596,7 +596,7 @@ static void find_displacer_edges(MultiresDisplacer *d, DerivedMesh *dm, Displace } /* Returns in out the corners [0-3] that use v1 and v2 */ -void find_face_corners(MFace *f, int v1, int v2, int out[2]) +static void find_face_corners(MFace *f, int v1, int v2, int out[2]) { int i, end = f->v4 ? 4 : 3; @@ -1259,7 +1259,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i ***************************/ /* Does not actually free lvl itself */ -void multires_free_level(MultiresLevel *lvl) +static void multires_free_level(MultiresLevel *lvl) { if(lvl) { if(lvl->faces) MEM_freeN(lvl->faces); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 480c79fbc1a..3979586fb19 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -219,6 +219,9 @@ void copy_nladata (ListBase *dst, ListBase *src) if ELEM(NULL, dst, src) return; + /* clear out the destination list first for precautions... */ + dst->first= dst->last= NULL; + /* copy each NLA-track, one at a time */ for (nlt= src->first; nlt; nlt= nlt->next) { /* make a copy, and add the copy to the destination list */ @@ -1048,7 +1051,7 @@ short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) /* Is the given NLA-strip the first one to occur for the given AnimData block */ // TODO: make this an api method if necesary, but need to add prefix first -short nlastrip_is_first (AnimData *adt, NlaStrip *strip) +static short nlastrip_is_first (AnimData *adt, NlaStrip *strip) { NlaTrack *nlt; NlaStrip *ns; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 90ea53d4364..aa12894feb9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1953,6 +1953,7 @@ static void composit_end_exec(bNodeTree *ntree, int is_group) if(ns->data) { printf("freed leftover buffer from stack\n"); free_compbuf(ns->data); + ns->data= NULL; } } } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 8fe7beeb247..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" @@ -127,8 +128,8 @@ void clear_workob(Object *workob) { memset(workob, 0, sizeof(Object)); - workob->size[0]= workob->size[1]= workob->size[2]= 1.0; - + workob->size[0]= workob->size[1]= workob->size[2]= 1.0f; + workob->rotmode= ROT_MODE_EUL; } void copy_baseflags(struct Scene *scene) @@ -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); @@ -1038,6 +1036,11 @@ Object *add_object(struct Scene *scene, int type) ob->data= add_obdata_from_type(type); ob->lay= scene->lay; + + /* objects should default to having Euler XYZ rotations, + * but rotations default to quaternions + */ + ob->rotmode= ROT_MODE_EUL; base= scene_add_base(scene, ob); scene_select_base(scene, base); @@ -1064,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; } @@ -1124,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); @@ -1263,7 +1267,7 @@ Object *copy_object(Object *ob) /* increase user numbers */ id_us_plus((ID *)obn->data); id_us_plus((ID *)obn->dup_group); - // FIXME: add this for animdata too... + for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); @@ -1273,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); @@ -1406,7 +1412,7 @@ int object_data_is_libdata(Object *ob) /* *************** PROXY **************** */ /* when you make proxy, ensure the exposed layers are extern */ -void armature_set_id_extern(Object *ob) +static void armature_set_id_extern(Object *ob) { bArmature *arm= ob->data; bPoseChannel *pchan; @@ -1553,13 +1559,11 @@ float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs) cfra+= bluroffs+fieldoffs; /* global time */ - cfra*= scene->r.framelen; + if (scene) + cfra*= scene->r.framelen; #if 0 // XXX old animation system if (ob) { - if (no_speed_curve==0 && ob->ipo) - cfra= calc_ipo_time(ob->ipo, cfra); - /* ofset frames */ if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) cfra-= give_timeoffset(ob); @@ -1574,29 +1578,44 @@ float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs) void object_scale_to_mat3(Object *ob, float mat[][3]) { float vec[3]; - if(ob->ipo) { - vec[0]= ob->size[0]+ob->dsize[0]; - vec[1]= ob->size[1]+ob->dsize[1]; - vec[2]= ob->size[2]+ob->dsize[2]; - SizeToMat3(vec, mat); - } - else { - SizeToMat3(ob->size, mat); - } + + vec[0]= ob->size[0]+ob->dsize[0]; + vec[1]= ob->size[1]+ob->dsize[1]; + vec[2]= ob->size[2]+ob->dsize[2]; + SizeToMat3(vec, mat); } +// TODO: this should take rotation orders into account later... void object_rot_to_mat3(Object *ob, float mat[][3]) { - float vec[3]; - if(ob->ipo) { - vec[0]= ob->rot[0]+ob->drot[0]; - vec[1]= ob->rot[1]+ob->drot[1]; - vec[2]= ob->rot[2]+ob->drot[2]; - EulToMat3(vec, mat); + float rmat[3][3], dmat[3][3]; + + /* initialise the delta-rotation matrix, which will get (pre)multiplied + * with the rotation matrix to yield the appropriate rotation + */ + Mat3One(dmat); + + /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */ + if (ob->rotmode > 0) { + /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ + EulOToMat3(ob->rot, ob->rotmode, rmat); + EulOToMat3(ob->drot, ob->rotmode, dmat); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ + AxisAngleToMat3(&ob->quat[1], ob->quat[0], rmat); + AxisAngleToMat3(&ob->dquat[1], ob->dquat[0], dmat); } else { - EulToMat3(ob->rot, mat); + /* quats are normalised before use to eliminate scaling issues */ + NormalQuat(ob->quat); + QuatToMat3(ob->quat, rmat); + QuatToMat3(ob->dquat, dmat); } + + /* combine these rotations */ + // XXX is this correct? if errors, change the order of multiplication... + Mat3MulMat3(mat, dmat, rmat); } void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ @@ -1609,19 +1628,7 @@ void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ object_scale_to_mat3(ob, smat); /* rot */ - /* Quats arnt used yet */ - /*if(ob->transflag & OB_QUAT) { - if(ob->ipo) { - QuatMul(q1, ob->quat, ob->dquat); - QuatToMat3(q1, rmat); - } - else { - QuatToMat3(ob->quat, rmat); - } - } - else {*/ - object_rot_to_mat3(ob, rmat); - /*}*/ + object_rot_to_mat3(ob, rmat); Mat3MulMat3(mat, rmat, smat); } @@ -1633,12 +1640,9 @@ void object_to_mat4(Object *ob, float mat[][4]) Mat4CpyMat3(mat, tmat); - VECCOPY(mat[3], ob->loc); - if(ob->ipo) { - mat[3][0]+= ob->dloc[0]; - mat[3][1]+= ob->dloc[1]; - mat[3][2]+= ob->dloc[2]; - } + mat[3][0]= ob->loc[0] + ob->dloc[0]; + mat[3][1]= ob->loc[1] + ob->dloc[1]; + mat[3][2]= ob->loc[2] + ob->dloc[2]; } int enable_cu_speed= 1; @@ -1919,31 +1923,6 @@ void where_is_object_time(Scene *scene, Object *ob, float ctime) if(ob==NULL) return; -#if 0 // XXX old animation system - /* this is needed to be able to grab objects with ipos, otherwise it always freezes them */ - stime= bsystem_time(scene, ob, ctime, 0.0); - if(stime != ob->ctime) { - - ob->ctime= stime; - - if(ob->ipo) { - calc_ipo(ob->ipo, stime); - execute_ipo((ID *)ob, ob->ipo); - } - else - do_all_object_actions(scene, ob); - - /* do constraint ipos ..., note it needs stime (0 = all ipos) */ - do_constraint_channels(&ob->constraints, &ob->constraintChannels, stime, 0); - } - else { - /* but, the drivers have to be done */ - if(ob->ipo) do_ob_ipodrivers(ob, ob->ipo, stime); - /* do constraint ipos ..., note it needs stime (1 = only drivers ipos) */ - do_constraint_channels(&ob->constraints, &ob->constraintChannels, stime, 1); - } -#endif // XXX old animation system - /* execute drivers only, as animation has already been done */ BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_DRIVERS); @@ -2562,7 +2541,7 @@ int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3 static int pc_cmp(void *a, void *b) { LinkData *ad = a, *bd = b; - if((int)ad->data > (int)bd->data) + if(GET_INT_FROM_POINTER(ad->data) > GET_INT_FROM_POINTER(bd->data)) return 1; else return 0; } @@ -2576,14 +2555,14 @@ int object_insert_ptcache(Object *ob) for(link=ob->pc_ids.first, i = 0; link; link=link->next, i++) { - int index =(int)link->data; + int index = GET_INT_FROM_POINTER(link->data); if(i < index) break; } link = MEM_callocN(sizeof(LinkData), "PCLink"); - link->data = (void *)i; + link->data = SET_INT_IN_POINTER(i); BLI_addtail(&ob->pc_ids, link); return i; diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index bd0b1a5e36e..0de97b9c703 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -236,7 +236,7 @@ void packAll(Main *bmain, ReportList *reports) // attempt to create a function that generates an unique filename // this will work when all funtions in fileops.c understand relative filenames... -char *find_new_name(char *name) +static char *find_new_name(char *name) { char tempname[FILE_MAXDIR + FILE_MAXFILE]; char *newname; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 7c5b2b82b4b..f17d2fbdcac 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -46,19 +46,24 @@ const char PAINT_CURSOR_TEXTURE_PAINT[3] = {255, 255, 255}; Paint *paint_get_active(Scene *sce) { - if(sce && sce->basact && sce->basact->object) { + if(sce) { ToolSettings *ts = sce->toolsettings; - - switch(sce->basact->object->mode) { - case OB_MODE_SCULPT: - return &ts->sculpt->paint; - case OB_MODE_VERTEX_PAINT: - return &ts->vpaint->paint; - case OB_MODE_WEIGHT_PAINT: - return &ts->wpaint->paint; - case OB_MODE_TEXTURE_PAINT: - return &ts->imapaint.paint; + + if(sce->basact && sce->basact->object) { + switch(sce->basact->object->mode) { + case OB_MODE_SCULPT: + return &ts->sculpt->paint; + case OB_MODE_VERTEX_PAINT: + return &ts->vpaint->paint; + case OB_MODE_WEIGHT_PAINT: + return &ts->wpaint->paint; + case OB_MODE_TEXTURE_PAINT: + return &ts->imapaint.paint; + } } + + /* default to image paint */ + return &ts->imapaint.paint; } return NULL; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2d3e3210afc..f4f5a1364a3 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" @@ -69,7 +70,7 @@ #include "BKE_particle.h" #include "BKE_DerivedMesh.h" #include "BKE_object.h" -#include "BKE_softbody.h" +#include "BKE_cloth.h" #include "BKE_material.h" #include "BKE_key.h" #include "BKE_library.h" @@ -81,12 +82,11 @@ #include "RE_render_ext.h" -static void key_from_object(Object *ob, ParticleKey *key); static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float *fuv, float *orco, ParticleTexture *ptex, int event); static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); -static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, +static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t); @@ -96,11 +96,9 @@ int count_particles(ParticleSystem *psys){ PARTICLE_P; int tot=0; - LOOP_PARTICLES { - if(pa->alive == PARS_KILLED); - else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); + LOOP_SHOWN_PARTICLES { + if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)); else tot++; } return tot; @@ -110,55 +108,13 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){ PARTICLE_P; int tot=0; - LOOP_PARTICLES { - if(pa->alive == PARS_KILLED); - else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); + LOOP_SHOWN_PARTICLES { + if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)); else if(p%totgr==cur) tot++; } return tot; } -int psys_count_keys(ParticleSystem *psys) -{ - PARTICLE_P; - int totkey=0; - - LOOP_PARTICLES - totkey += pa->totkey; - - return totkey; -} -/* remember to free the pointer returned from this! */ -char *psys_menu_string(Object *ob, int for_sb) -{ - ParticleSystem *psys; - DynStr *ds; - char *str, num[6]; - int i; - - ds = BLI_dynstr_new(); - - if(for_sb) - BLI_dynstr_append(ds, "|Object%x-1"); - - for(i=0,psys=ob->particlesystem.first; psys; i++,psys=psys->next){ - - BLI_dynstr_append(ds, "|"); - sprintf(num,"%i. ",i+1); - BLI_dynstr_append(ds, num); - BLI_dynstr_append(ds, psys->part->id.name+2); - sprintf(num,"%%x%i",i+1); - BLI_dynstr_append(ds, num); - } - - str = BLI_dynstr_get_cstring(ds); - - BLI_dynstr_free(ds); - - return str; -} - /* we allocate path cache memory in chunks instead of a big continguous * chunk, windows' memory allocater fails to find big blocks of memory often */ @@ -258,30 +214,13 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys) return NULL; } -/* change object's active particle system */ -void psys_change_act(void *ob_v, void *act_v) -{ - Object *ob = ob_v; - ParticleSystem *npsys, *psys; - short act = *((short*)act_v)-1; - - if(act>=0){ - npsys=BLI_findlink(&ob->particlesystem,act); - psys=psys_get_current(ob); - - if(psys) - psys->flag &= ~PSYS_CURRENT; - if(npsys) - npsys->flag |= PSYS_CURRENT; - } -} -Object *psys_get_lattice(Scene *scene, Object *ob, ParticleSystem *psys) +Object *psys_get_lattice(ParticleSimulationData *sim) { Object *lattice=0; - if(psys_in_edit_mode(scene, psys)==0){ + if(psys_in_edit_mode(sim->scene, sim->psys)==0){ - ModifierData *md = (ModifierData*)psys_get_modifier(ob,psys); + ModifierData *md = (ModifierData*)psys_get_modifier(sim->ob, sim->psys); for(; md; md=md->next){ if(md->type==eModifierType_Lattice){ @@ -310,20 +249,20 @@ void psys_enable_all(Object *ob) for(; psys; psys=psys->next) psys->flag &= ~PSYS_DISABLED; } -int psys_ob_has_hair(Object *ob) -{ - ParticleSystem *psys = ob->particlesystem.first; - - for(; psys; psys=psys->next) - if(psys->part->type == PART_HAIR) - return 1; - - return 0; -} int psys_in_edit_mode(Scene *scene, ParticleSystem *psys) { return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit)); } +static void psys_create_frand(ParticleSystem *psys) +{ + int i; + float *rand = psys->frand = MEM_callocN(PSYS_FRAND_COUNT * sizeof(float), "particle randoms"); + + BLI_srandom(psys->seed); + + for(i=0; i<1024; i++, rand++) + *rand = BLI_frand(); +} int psys_check_enabled(Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd; @@ -345,6 +284,14 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) } else if(!(psmd->modifier.mode & eModifierMode_Realtime)) return 0; + + /* perhaps not the perfect place, but we have to be sure the rands are there before usage */ + if(!psys->frand) + psys_create_frand(psys); + else if(psys->recalc & PSYS_RECALC_RESET) { + MEM_freeN(psys->frand); + psys_create_frand(psys); + } return 1; } @@ -354,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); } @@ -424,7 +367,7 @@ void free_keyed_keys(ParticleSystem *psys) } } } -void free_child_path_cache(ParticleSystem *psys) +static void free_child_path_cache(ParticleSystem *psys) { psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs); psys->childcache = NULL; @@ -478,6 +421,26 @@ void psys_free_particles(ParticleSystem *psys) psys->totpart= 0; } } +void psys_free_pdd(ParticleSystem *psys) +{ + 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->ndata) + MEM_freeN(psys->pdd->ndata); + psys->pdd->ndata = NULL; + + if(psys->pdd->vedata) + MEM_freeN(psys->pdd->vedata); + psys->pdd->vedata = NULL; + } +} /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) { @@ -499,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){ @@ -527,10 +487,19 @@ 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); + + if(psys->pdd) { + psys_free_pdd(psys); + MEM_freeN(psys->pdd); + } + MEM_freeN(psys); } } @@ -722,12 +691,12 @@ void psys_render_restore(Object *ob, ParticleSystem *psys) int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) { DerivedMesh *dm= ctx->dm; - Mesh *me= (Mesh*)(ctx->ob->data); + Mesh *me= (Mesh*)(ctx->sim.ob->data); MFace *mf, *mface; MVert *mvert; ParticleRenderData *data; ParticleRenderElem *elems, *elem; - ParticleSettings *part= ctx->psys->part; + ParticleSettings *part= ctx->sim.psys->part; float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp; float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport; double vprate; @@ -736,10 +705,10 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) return tot; - if(!ctx->psys->renderdata) + if(!ctx->sim.psys->renderdata) return tot; - data= ctx->psys->renderdata; + data= ctx->sim.psys->renderdata; if(data->timeoffset) return 0; if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE)) @@ -816,7 +785,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) /* set simplification parameters per original face */ for(a=0, elem=elems; a<totorigface; a++, elem++) { - area = psys_render_projected_area(ctx->psys, facecenter[a], facearea[a], vprate, &viewport); + area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport); arearatio= fac*area/facearea[a]; if((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) { @@ -1438,7 +1407,7 @@ void psys_interpolate_mcol(MCol *mcol, int quad, float *w, MCol *mc) } } -float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values) +static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values) { if(values==0 || index==-1) return 0.0; @@ -1922,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; -int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase *lb) + 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; + + 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; - - effect[0]=effect[1]=effect[2]=0.0; + 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]; - 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; + if(effectors) for(eff = effectors->first; eff; eff=eff->next) { + pd = eff->pd; - 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; } @@ -2075,20 +2055,24 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float VECADDFAC(state->co,state->co,mat[0],rough[0]); VECADDFAC(state->co,state->co,mat[1],rough[1]); } -static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) +static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) { - float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}; + float force[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= psys->particles+i; - do_effectors(i, pa, &eff_key, scene, ob, psys, 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 * psys->part->eff_hair) / (float)steps); + VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps); VecAddf(force, force, vec); @@ -2155,12 +2139,12 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup) } return vg; } -void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys) +void psys_find_parents(ParticleSimulationData *sim) { - ParticleSettings *part=psys->part; + ParticleSettings *part=sim->psys->part; KDTree *tree; ChildParticle *cpa; - int p, totparent,totchild=psys->totchild; + int p, totparent,totchild=sim->psys->totchild; float co[3], orco[3]; int from=PART_FROM_FACE; totparent=(int)(totchild*part->parents*0.3); @@ -2170,15 +2154,15 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys tree=BLI_kdtree_new(totparent); - for(p=0,cpa=psys->child; p<totparent; p++,cpa++){ - psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + for(p=0,cpa=sim->psys->child; p<totparent; p++,cpa++){ + psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); BLI_kdtree_insert(tree, p, orco, NULL); } BLI_kdtree_balance(tree); for(; p<totchild; p++,cpa++){ - psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); cpa->parent=BLI_kdtree_find_nearest(tree, orco, NULL, NULL); } @@ -2216,11 +2200,11 @@ static void get_strand_normal(Material *ma, float *surfnor, float surfdist, floa VECCOPY(nor, vnor); } -int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) +static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) { ParticleThreadContext *ctx= threads[0].ctx; - Object *ob= ctx->ob; - ParticleSystem *psys= ctx->psys; +/* Object *ob= ctx->sim.ob; */ + ParticleSystem *psys= ctx->sim.psys; ParticleSettings *part = psys->part; ParticleEditSettings *pset = &scene->toolsettings->particle; int totparent=0, between=0; @@ -2253,10 +2237,10 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in if(totchild==0) return 0; /* init random number generator */ - if(ctx->psys->part->flag & PART_ANIM_BRANCHING) - seed= 31415926 + ctx->psys->seed + (int)cfra; + if(ctx->sim.psys->part->flag & PART_ANIM_BRANCHING) + seed= 31415926 + ctx->sim.psys->seed + (int)cfra; else - seed= 31415926 + ctx->psys->seed; + seed= 31415926 + ctx->sim.psys->seed; if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000) totthread= 1; @@ -2274,7 +2258,7 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in ctx->parent_pass= 0; ctx->cfra= cfra; - psys->lattice = psys_get_lattice(scene, ob, psys); + psys->lattice = psys_get_lattice(&ctx->sim); /* cache all relevant vertex groups if they exist */ if(part->from!=PART_FROM_PARTICLE){ @@ -2300,11 +2284,11 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in } /* note: this function must be thread safe, except for branching! */ -void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) +static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) { ParticleThreadContext *ctx= thread->ctx; - Object *ob= ctx->ob; - ParticleSystem *psys = ctx->psys; + Object *ob= ctx->sim.ob; + ParticleSystem *psys = ctx->sim.psys; ParticleSettings *part = psys->part; ParticleCacheKey **cache= psys->childcache; ParticleCacheKey **pcache= psys->pathcache; @@ -2373,7 +2357,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; - psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); + psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); if(part->path_start==0.0f) { /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ @@ -2383,7 +2367,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, pa = psys->particles + cpa->parent; - psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); pa=0; } @@ -2405,9 +2389,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_num=pa->num; cpa_fuv=pa->fuv; - psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); + psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); - psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); } keys->steps = ctx->steps; @@ -2424,7 +2408,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, /* get different child parameters from textures & vgroups */ get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex); - if(ptex.exist < cpa->rand[1]) { + if(ptex.exist < PSYS_FRAND(i + 24)) { keys->steps = -1; return; } @@ -2473,7 +2457,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, if(part->flag & PART_CHILD_EFFECT) { for(k=0,state=keys; k<=ctx->steps; k++,state++) { if(k) { - do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); + do_path_effectors(&ctx->sim, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); } else { VecSubf(eff_vec,(state+1)->co,state->co); @@ -2499,7 +2483,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, } /* apply different deformations to the child path */ - do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); + do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); /* TODO: better branching */ //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) @@ -2576,7 +2560,7 @@ static void *exec_child_path_cache(void *data) { ParticleThread *thread= (ParticleThread*)data; ParticleThreadContext *ctx= thread->ctx; - ParticleSystem *psys= ctx->psys; + ParticleSystem *psys= ctx->sim.psys; ParticleCacheKey **cache= psys->childcache; ChildParticle *cpa; int i, totchild= ctx->totchild, first= 0; @@ -2593,21 +2577,21 @@ static void *exec_child_path_cache(void *data) return 0; } -void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate) { - ParticleSettings *part = psys->part; + ParticleSettings *part = sim->psys->part; ParticleThread *pthreads; ParticleThreadContext *ctx; ParticleCacheKey **cache; ListBase threads; int i, totchild, totparent, totthread; - if(psys->flag & PSYS_GLOBAL_HAIR) + if(sim->psys->flag & PSYS_GLOBAL_HAIR) return; - pthreads= psys_threads_create(scene, ob, psys); + pthreads= psys_threads_create(sim); - if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) { + if(!psys_threads_init_path(pthreads, sim->scene, cfra, editupdate)) { psys_threads_free(pthreads); return; } @@ -2616,14 +2600,14 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa totchild= ctx->totchild; totparent= ctx->totparent; - if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) { - cache = psys->childcache; + if(editupdate && sim->psys->childcache && !(part->flag & PART_BRANCHING) && totchild == sim->psys->totchildcache) { + cache = sim->psys->childcache; } else { /* clear out old and create new empty path cache */ - free_child_path_cache(psys); - psys->childcache= psys_alloc_path_cache_buffers(&psys->childcachebufs, totchild, ctx->steps+1); - psys->totchildcache = totchild; + free_child_path_cache(sim->psys); + sim->psys->childcache= psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps+1); + sim->psys->totchildcache = totchild; } totthread= pthreads[0].tot; @@ -2661,27 +2645,29 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ /* -Cached path data is also used to determine cut position for the editmode tool. */ -void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra) +void psys_cache_paths(ParticleSimulationData *sim, float cfra) { - ParticleCacheKey *ca, **cache= psys->pathcache; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + PARTICLE_PSMD; + ParticleEditSettings *pset = &sim->scene->toolsettings->particle; + ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; - ParticleEditSettings *pset = &scene->toolsettings->particle; + ParticleCacheKey *ca, **cache= psys->pathcache; DerivedMesh *hair_dm = psys->hair_out_dm; - ParticleData *pa = psys->particles; ParticleKey result; Material *ma; ParticleInterpolationData pind; + + PARTICLE_P; float birthtime = 0.0, dietime = 0.0; - float t, time = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; + float t, time = 0.0, dfra = 1.0, frs_sec = sim->scene->r.frs_sec; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; float prev_tangent[3], hairmat[4][4]; float rotmat[3][3]; - int k,i; + int k; int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step)); int totpart = psys->totpart; float length, vec[3]; @@ -2693,7 +2679,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) return; - if(psys_in_edit_mode(scene, psys)) + if(psys_in_edit_mode(sim->scene, psys)) if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0) return; @@ -2706,8 +2692,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra psys_free_path_cache(psys, psys->edit); cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1); - psys->lattice = psys_get_lattice(scene, ob, psys); - ma= give_current_material(ob, psys->part->omat); + psys->lattice = psys_get_lattice(sim); + ma= give_current_material(sim->ob, psys->part->omat); if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) @@ -2720,12 +2706,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } /*---first main loop: create all actual particles' paths---*/ - for(i=0; i<totpart; i++, pa++){ - if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) - continue; - + LOOP_SHOWN_PARTICLES { if(!psys->totchild) { - BLI_srandom(psys->seed + i); + BLI_srandom(psys->seed + p); pa_length = 1.0f - part->randlength * BLI_frand(); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); @@ -2737,15 +2720,15 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE); pind.dm = hair_dm; - memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); + memset(cache[p], 0, sizeof(*cache[p])*(steps+1)); - cache[i]->steps = steps; + cache[p]->steps = steps; /*--get the first data points--*/ - init_particle_interpolation(ob, psys, pa, &pind); + init_particle_interpolation(sim->ob, sim->psys, pa, &pind); /* hairmat is needed for for non-hair particle too so we get proper rotations */ - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, psmd->dm, psys->part->from, pa, hairmat); VECCOPY(rotmat[0], hairmat[2]); VECCOPY(rotmat[1], hairmat[1]); VECCOPY(rotmat[2], hairmat[0]); @@ -2761,26 +2744,26 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } if(birthtime >= dietime) { - cache[i]->steps = -1; + cache[p]->steps = -1; continue; } dietime = birthtime + pa_length * (dietime - birthtime); /*--interpolate actual path from data points--*/ - for(k=0, ca=cache[i]; k<=steps; k++, ca++){ + for(k=0, ca=cache[p]; k<=steps; k++, ca++){ time = (float)k / (float)steps; t = birthtime + time * (dietime - birthtime); result.time = -t; - do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); + do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, &result); /* dynamic hair is in object space */ /* keyed and baked are allready in global space */ if(hair_dm) - Mat4MulVecfl(ob->obmat, result.co); + Mat4MulVecfl(sim->ob->obmat, result.co); else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) Mat4MulVecfl(hairmat, result.co); @@ -2790,23 +2773,23 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra /*--modify paths and calculate rotation & velocity--*/ - VecSubf(vec,(cache[i]+1)->co,cache[i]->co); + VecSubf(vec,(cache[p]+1)->co,cache[p]->co); length = VecLength(vec); effector= 1.0f; if(vg_effector) effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector); - for(k=0, ca=cache[i]; k<=steps; k++, ca++) { + for(k=0, ca=cache[p]; k<=steps; k++, ca++) { if(!(psys->flag & PSYS_GLOBAL_HAIR)) { /* apply effectors */ if(!(psys->part->flag & PART_CHILD_EFFECT) && k) - do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); + 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(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); + do_guides(sim->psys->effectors, (ParticleKey*)ca, p, (float)k/(float)steps); /* apply lattice */ if(psys->lattice) @@ -3022,23 +3005,7 @@ void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, flo if(time) *time=key->time; } /*-------changing particle keys from space to another-------*/ -void psys_key_to_object(Object *ob, ParticleKey *key, float imat[][4]){ - float q[4], imat2[4][4]; - - if(imat==0){ - Mat4Invert(imat2,ob->obmat); - imat=imat2; - } - - VECADD(key->vel,key->vel,key->co); - - Mat4MulVecfl(imat,key->co); - Mat4MulVecfl(imat,key->vel); - Mat4ToQuat(imat,q); - - VECSUB(key->vel,key->vel,key->co); - QuatMul(key->rot,q,key->rot); -} +#if 0 static void key_from_object(Object *ob, ParticleKey *key){ float q[4]; @@ -3051,6 +3018,7 @@ static void key_from_object(Object *ob, ParticleKey *key){ VECSUB(key->vel,key->vel,key->co); QuatMul(key->rot,q,key->rot); } +#endif static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[][4]) { @@ -3229,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; @@ -3241,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; @@ -3291,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 @@ -3303,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); } @@ -3390,59 +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); - } -} - -LinkNode *psys_using_settings(struct Scene *scene, ParticleSettings *part, int flush_update) -{ - Object *ob, *tob; - ParticleSystem *psys, *tpsys; - LinkNode *node= NULL; - int found; - - /* update all that have same particle settings */ - for(ob=G.main->object.first; ob; ob=ob->id.next) { - found= 0; - - for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->part == part) { - BLI_linklist_append(&node, psys); - found++; - } - else if(psys->part->type == PART_REACTOR){ - tob= (psys->target_ob)? psys->target_ob: ob; - tpsys= BLI_findlink(&tob->particlesystem, psys->target_psys-1); - - if(tpsys && tpsys->part==part) { - BLI_linklist_append(&node, tpsys); - found++; - } - } - } - - if(flush_update && found) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - - return node; -} - /************************************************/ /* Textures */ @@ -3498,9 +3410,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float mtex=ma->mtex[m]; if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){ float def=mtex->def_var; - float var=mtex->varfac; short blend=mtex->blendtype; - short neg=mtex->pmaptoneg; if((mtex->texco & TEXCO_UV) && fw) { if(!get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texco)) @@ -3515,18 +3425,18 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float ptex->time=0.0; setvars|=MAP_PA_TIME; } - ptex->time= texture_value_blend(mtex->def_var,ptex->time,value,var,blend,neg & MAP_PA_TIME); + ptex->time= texture_value_blend(mtex->def_var,ptex->time,value,mtex->timefac,blend); } if((event & mtex->pmapto) & MAP_PA_LENGTH) - ptex->length= texture_value_blend(def,ptex->length,value,var,blend,neg & MAP_PA_LENGTH); + ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend); if((event & mtex->pmapto) & MAP_PA_CLUMP) - ptex->clump= texture_value_blend(def,ptex->clump,value,var,blend,neg & MAP_PA_CLUMP); + ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend); if((event & mtex->pmapto) & MAP_PA_KINK) - ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_KINK); + ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend); if((event & mtex->pmapto) & MAP_PA_ROUGH) - ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,var,blend,neg & MAP_PA_ROUGH); + ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,mtex->roughfac,blend); if((event & mtex->pmapto) & MAP_PA_DENS) - ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS); + ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend); } } if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } @@ -3540,7 +3450,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float } if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } } -void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event) +void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *pa, ParticleTexture *ptex, int event) { MTex *mtex; int m; @@ -3550,19 +3460,17 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd if(ma) for(m=0; m<MAX_MTEX; m++){ mtex=ma->mtex[m]; if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){ - float var=mtex->varfac; float def=mtex->def_var; short blend=mtex->blendtype; - short neg=mtex->pmaptoneg; - if((mtex->texco & TEXCO_UV) && ELEM(psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { - if(!get_particle_uv(psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { + if((mtex->texco & TEXCO_UV) && ELEM(sim->psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { + if(!get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { /* failed to get uv's, let's try orco's */ - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } } else { - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); @@ -3570,29 +3478,31 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd if((event & mtex->pmapto) & MAP_PA_TIME){ /* the first time has to set the base value for time regardless of blend mode */ if((setvars&MAP_PA_TIME)==0){ - ptex->time *= 1.0f - var; - ptex->time += var * ((neg & MAP_PA_TIME)? 1.0f - value : value); + int flip= (mtex->timefac < 0.0f); + float timefac= fabsf(mtex->timefac); + ptex->time *= 1.0f - timefac; + ptex->time += timefac * ((flip)? 1.0f - value : value); setvars |= MAP_PA_TIME; } else - ptex->time= texture_value_blend(def,ptex->time,value,var,blend,neg & MAP_PA_TIME); + ptex->time= texture_value_blend(def,ptex->time,value,mtex->timefac,blend); } if((event & mtex->pmapto) & MAP_PA_LIFE) - ptex->life= texture_value_blend(def,ptex->life,value,var,blend,neg & MAP_PA_LIFE); + ptex->life= texture_value_blend(def,ptex->life,value,mtex->lifefac,blend); if((event & mtex->pmapto) & MAP_PA_DENS) - ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS); + ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend); if((event & mtex->pmapto) & MAP_PA_SIZE) - ptex->size= texture_value_blend(def,ptex->size,value,var,blend,neg & MAP_PA_SIZE); + ptex->size= texture_value_blend(def,ptex->size,value,mtex->sizefac,blend); if((event & mtex->pmapto) & MAP_PA_IVEL) - ptex->ivel= texture_value_blend(def,ptex->ivel,value,var,blend,neg & MAP_PA_IVEL); + ptex->ivel= texture_value_blend(def,ptex->ivel,value,mtex->ivelfac,blend); if((event & mtex->pmapto) & MAP_PA_PVEL) - texture_rgb_blend(ptex->pvel,rgba,ptex->pvel,value,var,blend); + texture_rgb_blend(ptex->pvel,rgba,ptex->pvel,value,mtex->pvelfac,blend); if((event & mtex->pmapto) & MAP_PA_LENGTH) - ptex->length= texture_value_blend(def,ptex->length,value,var,blend,neg & MAP_PA_LENGTH); + ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend); if((event & mtex->pmapto) & MAP_PA_CLUMP) - ptex->clump= texture_value_blend(def,ptex->clump,value,var,blend,neg & MAP_PA_CLUMP); + ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend); if((event & mtex->pmapto) & MAP_PA_KINK) - ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_CLUMP); + ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend); } } if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } @@ -3607,38 +3517,9 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd /************************************************/ /* Particle State */ /************************************************/ -float psys_get_timestep(ParticleSettings *part) +float psys_get_timestep(ParticleSimulationData *sim) { - return 0.04f*part->timetweak; -} -/* part->size should be updated with possible ipo effection before this is called */ -float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, IpoCurve *icu_size, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, float *vg_size) -{ - ParticleTexture ptex; - float size=1.0f; - - BLI_srandom(psys->seed + (pa - psys->particles) + 100); - - if(ma && part->from!=PART_FROM_PARTICLE){ - ptex.size=size; - psys_get_texture(ob,ma,psmd,psys,pa,&ptex,MAP_PA_SIZE); - size=ptex.size; - } - -#if 0 // XXX old animation system - if(icu_size){ - calc_icu(icu_size,pa->time); - size*=icu_size->curval; - } -#endif // XXX old animation system - - if(vg_size) - size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size); - - if(part->randsize!=0.0) - size*= 1.0f - part->randsize * BLI_frand(); - - return size*part->size; + return 0.04f * sim->psys->part->timetweak; } float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime) { @@ -3653,7 +3534,7 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, w++; } - life = part->lifetime*(1.0f-part->randlife*cpa->rand[1]); + life = part->lifetime * (1.0f - part->randlife * PSYS_FRAND(cpa - psys->child + 25)); } else{ ParticleData *pa = psys->particles + cpa->parent; @@ -3702,13 +3583,16 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, size*=part->childsize; if(part->childrandsize!=0.0) - size *= 1.0f - part->childrandsize*cpa->rand[2]; + size *= 1.0f - part->childrandsize * PSYS_FRAND(cpa - psys->child + 26); return size; } static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex) { - ptex->length= 1.0f - part->randlength*cpa->rand[0]; + ParticleSystem *psys = ctx->sim.psys; + int i = cpa - psys->child; + + ptex->length= 1.0f - part->randlength * PSYS_FRAND(i + 26); ptex->clump=1.0; ptex->kink=1.0; ptex->rough1= 1.0; @@ -3717,13 +3601,13 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread ptex->exist= 1.0; ptex->effector= 1.0; - ptex->length*= part->clength_thres < cpa->rand[1] ? part->clength : 1.0f; + ptex->length*= part->clength_thres < PSYS_FRAND(i + 27) ? part->clength : 1.0f; get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex, MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); - if(ptex->exist < cpa->rand[1]) + if(ptex->exist < PSYS_FRAND(i + 24)) return; if(ctx->vg_length) @@ -3741,18 +3625,20 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread if(ctx->vg_effector) ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector); } -static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t) +static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t) { + ParticleSettings *part = sim->psys->part; + int i = cpa - sim->psys->child; int guided = 0; if(part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ - guided = do_guide(scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors)); + guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t); if(guided==0){ if(part->kink) do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape, - part->kink_amp, part->kink, part->kink_axis, ob->obmat); + part->kink_amp, part->kink, part->kink_axis, sim->ob->obmat); do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump); } @@ -3761,17 +3647,18 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state); if(part->rough2 != 0.0 && ptex->rough2 != 0.0) - do_rough(cpa->rand, mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); + do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); if(part->rough_end != 0.0 && ptex->roughe != 0.0) - do_rough_end(cpa->rand, mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); + do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ -void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) +void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, int vel) { - ParticleSettings *part = psys->part; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - Material *ma = give_current_material(ob, part->omat); + PARTICLE_PSMD; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = sim->psys->part; + Material *ma = give_current_material(sim->ob, part->omat); ParticleData *pa; ChildParticle *cpa; ParticleTexture ptex; @@ -3779,7 +3666,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i ParticleThreadContext ctx; /* fake thread context for child modifiers */ ParticleInterpolationData pind; - float t, frs_sec = scene->r.frs_sec; + float t, frs_sec = sim->scene->r.frs_sec; float co[3], orco[3]; float hairmat[4][4]; int totparent = 0; @@ -3807,17 +3694,17 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i pind.cache = cached ? psys->pointcache : NULL; pind.epoint = NULL; pind.dm = psys->hair_out_dm; - init_particle_interpolation(ob, psys, pa, &pind); + init_particle_interpolation(sim->ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state); if(!keyed && !cached) { if((pa->flag & PARS_REKEY)==0) { - psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat); Mat4MulVecfl(hairmat, state->co); Mat4Mul3Vecfl(hairmat, state->vel); - if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { - do_guide(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 */ } @@ -3850,7 +3737,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i /* get parent states */ while(w<4 && cpa->pa[w]>=0){ keys[w].time = state->time; - psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1); + psys_get_particle_on_path(sim, cpa->pa[w], keys+w, 1); w++; } @@ -3870,14 +3757,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i pa = psys->particles + cpa->parent; - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); pa=0; } else{ /* get the parent state */ keys->time = state->time; - psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); + psys_get_particle_on_path(sim, cpa->parent, keys,1); /* get the original coordinates (orco) for texture usage */ pa=psys->particles+cpa->parent; @@ -3888,7 +3775,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0); - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); } /* correct child ipo timing */ @@ -3937,7 +3824,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i copy_particle_key(&tstate, state, 1); /* apply different deformations to the child path */ - do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, hairmat, state, t); + do_child_modifiers(sim, &ptex, par, par->rot, cpa, orco, hairmat, state, t); /* try to estimate correct velocity */ if(vel){ @@ -3946,13 +3833,13 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i if(t>=0.001f){ tstate.time=t-0.001f; - psys_get_particle_on_path(scene,ob,psys,p,&tstate,0); + psys_get_particle_on_path(sim,p,&tstate,0); VECSUB(state->vel,state->co,tstate.co); Normalize(state->vel); } else{ tstate.time=t+0.001f; - psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); + psys_get_particle_on_path(sim,p,&tstate,0); VECSUB(state->vel,tstate.co,state->co); Normalize(state->vel); } @@ -3962,39 +3849,50 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i } } /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ -int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){ - ParticleSettings *part=psys->part; - ParticleData *pa=0; +int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always){ + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + ParticleData *pa = NULL; + ChildParticle *cpa = NULL; float cfra; - int totpart=psys->totpart, between=0; + int totpart = psys->totpart; /* negative time means "use current time" */ - if(state->time>0) - cfra=state->time; - else - cfra= bsystem_time(scene, 0, (float)scene->r.cfra,0.0); + cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0); - if(psys->totchild && p>=totpart){ - if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ - between=1; - } - else - pa=psys->particles+(psys->child+p-totpart)->parent; - } - else - pa=psys->particles+p; - - if(between){ - state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL); + if(p>=totpart){ + if(!psys->totchild) + return 0; - if(always==0) - if((state->time<0.0 && (part->flag & PART_UNBORN)==0) - || (state->time>1.0 && (part->flag & PART_DIED)==0)) + if(part->from != PART_FROM_PARTICLE && part->childtype == PART_CHILD_FACES){ + if(!(psys->flag & PSYS_KEYED)) return 0; + + cpa = psys->child + p - totpart; + + state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL); + + if(!always) + if((state->time < 0.0 && !(part->flag & PART_UNBORN)) + || (state->time > 1.0 && !(part->flag & PART_DIED))) + return 0; + + state->time= (cfra - (part->sta + (part->end - part->sta) * PSYS_FRAND(p + 23))) / (part->lifetime * PSYS_FRAND(p + 24)); + + psys_get_particle_on_path(sim, p, state,1); + return 1; + } + else { + cpa = sim->psys->child + p - totpart; + pa = sim->psys->particles + cpa->parent; + } } - else{ - if(pa->alive==PARS_KILLED) return 0; - if(always==0) + else { + pa = sim->psys->particles + p; + } + + if(pa) { + if(!always) if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0) || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0)) return 0; @@ -4002,38 +3900,28 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy state->time = MIN2(state->time, pa->dietime); } - if(psys->flag & PSYS_KEYED){ - if(between){ - ChildParticle *cpa=psys->child+p-totpart; - state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]); - } - else - state->time= -cfra; - - psys_get_particle_on_path(scene, ob, psys, p, state,1); + if(sim->psys->flag & PSYS_KEYED){ + state->time= -cfra; + psys_get_particle_on_path(sim, p, state,1); return 1; } else{ - if(between) - return 0; /* currently not supported */ - else if(psys->totchild && p>=psys->totpart){ - ChildParticle *cpa=psys->child+p-psys->totpart; + if(cpa){ ParticleKey *key1; float t = (cfra - pa->time + pa->loop * pa->lifetime) / pa->lifetime; - pa = psys->particles + cpa->parent; key1=&pa->state; offset_child(cpa, key1, state, part->childflat, part->childrad); CLAMP(t,0.0,1.0); if(part->kink) /* TODO: part->kink_freq*pa_kink */ - do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,ob->obmat); + do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,sim->ob->obmat); /* TODO: pa_clump vgroup */ do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); if(psys->lattice) - calc_latt_deform(psys->lattice, state->co,1.0f); + calc_latt_deform(sim->psys->lattice, state->co,1.0f); } else{ if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) @@ -4044,7 +3932,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy /* let's interpolate to try to be as accurate as possible */ if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { ParticleKey keys[4]; - float dfra, keytime, frs_sec = scene->r.frs_sec; + float dfra, keytime, frs_sec = sim->scene->r.frs_sec; if(pa->prev_state.time >= pa->state.time) { /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ @@ -4079,8 +3967,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy } } - if(psys->lattice) - calc_latt_deform(psys->lattice, state->co,1.0f); + if(sim->psys->lattice) + calc_latt_deform(sim->psys->lattice, state->co,1.0f); } return 1; @@ -4136,8 +4024,11 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo } } -void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) +void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) { + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; + ParticleSystemModifierData *psmd = sim->psmd; float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4]; float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; @@ -4145,7 +4036,7 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys len= Normalize(vec); if(pa) - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); + psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); else psys_particle_on_emitter(psmd, (psys->part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index fb12cfe3147..d757372f17b 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" @@ -122,7 +122,6 @@ static int get_current_display_percentage(ParticleSystem *psys) void psys_reset(ParticleSystem *psys, int mode) { - ParticleSettings *part= psys->part; PARTICLE_P; if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { @@ -133,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; @@ -165,20 +161,22 @@ void psys_reset(ParticleSystem *psys, int mode) psys->pointcache->simframe= 0; } -static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) +static void realloc_particles(ParticleSimulationData *sim, int new_totpart) { + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; ParticleData *newpars = NULL; BoidParticle *newboids = NULL; PARTICLE_P; int totpart, totsaved = 0; if(new_totpart<0) { - if(psys->part->distr==PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) { - totpart= psys->part->grid_res; + if(part->distr==PART_DISTR_GRID && part->from != PART_FROM_VERT) { + totpart= part->grid_res; totpart*=totpart*totpart; } else - totpart=psys->part->totpart; + totpart=part->totpart; } else totpart=new_totpart; @@ -213,6 +211,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(pa->hair) MEM_freeN(pa->hair); MEM_freeN(psys->particles); + psys_free_pdd(psys); } psys->particles=newpars; @@ -606,13 +605,13 @@ static int binary_search_distribution(float *sum, int n, float value) /* note: this function must be thread safe, for from == PART_FROM_CHILD */ #define ONLY_WORKING_WITH_PA_VERTS 0 -void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) +static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) { ParticleThreadContext *ctx= thread->ctx; - Object *ob= ctx->ob; + Object *ob= ctx->sim.ob; DerivedMesh *dm= ctx->dm; ParticleData *tpa; - ParticleSettings *part= ctx->psys->part; +/* ParticleSettings *part= ctx->sim.psys->part; */ float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3]; float cur_d, min_d, randu, randv; int from= ctx->from; @@ -625,7 +624,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C pa->num= ctx->index[p]; pa->fuv[0] = 1.0f; pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; - //pa->verts[0] = pa->verts[1] = pa->verts[2] = 0; #if ONLY_WORKING_WITH_PA_VERTS if(ctx->tree){ @@ -653,7 +651,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel); psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); ctx->jitoff[i]++; - //ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); break; case PART_DISTR_RAND: randu= rng_getFloat(thread->rng); @@ -663,12 +660,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C } pa->foffset= 0.0f; - /* - pa->verts[0] = mface->v1; - pa->verts[1] = mface->v2; - pa->verts[2] = mface->v3; - */ - /* experimental */ if(from==PART_FROM_VOLUME){ MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); @@ -724,10 +715,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C } } else if(from == PART_FROM_PARTICLE) { - //pa->verts[0]=0; /* not applicable */ - //pa->verts[1]=0; - //pa->verts[2]=0; - tpa=ctx->tpars+ctx->index[p]; pa->num=ctx->index[p]; pa->fuv[0]=tpa->fuv[0]; @@ -743,42 +730,30 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C cpa->num=0; cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f; cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - cpa->rand[0]=cpa->rand[1]=cpa->rand[2]=0.0f; return; } mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE); - //switch(distr){ - // case PART_DISTR_JIT: - // i=index[p]; - // psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mf->v4, cpa->fuv); - // ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); - // break; - // case PART_DISTR_RAND: - randu= rng_getFloat(thread->rng); - randv= rng_getFloat(thread->rng); - psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); - // break; - //} + randu= rng_getFloat(thread->rng); + randv= rng_getFloat(thread->rng); + psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); - cpa->rand[0] = rng_getFloat(thread->rng); - cpa->rand[1] = rng_getFloat(thread->rng); - cpa->rand[2] = rng_getFloat(thread->rng); cpa->num = ctx->index[p]; if(ctx->tree){ KDTreeNearest ptn[10]; - int w,maxw, do_seams; + int w,maxw;//, do_seams; float maxd,mind,dd,totw=0.0; int parent[10]; float pweight[10]; - do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams); + /*do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams);*/ psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0,orco1,ornor1); transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); - maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); + //maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); + maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,ornor1,ptn); maxd=ptn[maxw-1].dist; mind=ptn[0].dist; @@ -788,70 +763,68 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C for(w=0; w<maxw; w++){ parent[w]=ptn[w].index; pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd)); - //pweight[w]= (1.0f - ptn[w].dist*ptn[w].dist/(maxd*maxd)); - //pweight[w] *= pweight[w]; } for(;w<10; w++){ parent[w]=-1; pweight[w]=0.0f; } - if(do_seams){ - ParticleSeam *seam=ctx->seams; - float temp[3],temp2[3],tan[3]; - float inp,cur_len,min_len=10000.0f; - int min_seam=0, near_vert=0; - /* find closest seam */ - for(i=0; i<ctx->totseam; i++, seam++){ - VecSubf(temp,co1,seam->v0); - inp=Inpf(temp,seam->dir)/seam->length2; - if(inp<0.0f){ - cur_len=VecLenf(co1,seam->v0); - } - else if(inp>1.0f){ - cur_len=VecLenf(co1,seam->v1); - } - else{ - VecCopyf(temp2,seam->dir); - VecMulf(temp2,inp); - cur_len=VecLenf(temp,temp2); - } - if(cur_len<min_len){ - min_len=cur_len; - min_seam=i; - if(inp<0.0f) near_vert=-1; - else if(inp>1.0f) near_vert=1; - else near_vert=0; - } - } - seam=ctx->seams+min_seam; - - VecCopyf(temp,seam->v0); - - if(near_vert){ - if(near_vert==-1) - VecSubf(tan,co1,seam->v0); - else{ - VecSubf(tan,co1,seam->v1); - VecCopyf(temp,seam->v1); - } - - Normalize(tan); - } - else{ - VecCopyf(tan,seam->tan); - VecSubf(temp2,co1,temp); - if(Inpf(tan,temp2)<0.0f) - VecNegf(tan); - } - for(w=0; w<maxw; w++){ - VecSubf(temp2,ptn[w].co,temp); - if(Inpf(tan,temp2)<0.0f){ - parent[w]=-1; - pweight[w]=0.0f; - } - } + //if(do_seams){ + // ParticleSeam *seam=ctx->seams; + // float temp[3],temp2[3],tan[3]; + // float inp,cur_len,min_len=10000.0f; + // int min_seam=0, near_vert=0; + // /* find closest seam */ + // for(i=0; i<ctx->totseam; i++, seam++){ + // VecSubf(temp,co1,seam->v0); + // inp=Inpf(temp,seam->dir)/seam->length2; + // if(inp<0.0f){ + // cur_len=VecLenf(co1,seam->v0); + // } + // else if(inp>1.0f){ + // cur_len=VecLenf(co1,seam->v1); + // } + // else{ + // VecCopyf(temp2,seam->dir); + // VecMulf(temp2,inp); + // cur_len=VecLenf(temp,temp2); + // } + // if(cur_len<min_len){ + // min_len=cur_len; + // min_seam=i; + // if(inp<0.0f) near_vert=-1; + // else if(inp>1.0f) near_vert=1; + // else near_vert=0; + // } + // } + // seam=ctx->seams+min_seam; + // + // VecCopyf(temp,seam->v0); + // + // if(near_vert){ + // if(near_vert==-1) + // VecSubf(tan,co1,seam->v0); + // else{ + // VecSubf(tan,co1,seam->v1); + // VecCopyf(temp,seam->v1); + // } + + // Normalize(tan); + // } + // else{ + // VecCopyf(tan,seam->tan); + // VecSubf(temp2,co1,temp); + // if(Inpf(tan,temp2)<0.0f) + // VecNegf(tan); + // } + // for(w=0; w<maxw; w++){ + // VecSubf(temp2,ptn[w].co,temp); + // if(Inpf(tan,temp2)<0.0f){ + // parent[w]=-1; + // pweight[w]=0.0f; + // } + // } - } + //} for(w=0,i=0; w<maxw && i<4; w++){ if(parent[w]>=0){ @@ -877,7 +850,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C static void *exec_distribution(void *data) { ParticleThread *thread= (ParticleThread*)data; - ParticleSystem *psys= thread->ctx->psys; + ParticleSystem *psys= thread->ctx->sim.psys; ParticleData *pa; ChildParticle *cpa; int p, totpart; @@ -944,11 +917,11 @@ static int compare_orig_index(const void *p1, const void *p2) /* 6. and we're done! */ /* This is to denote functionality that does not yet work with mesh - only derived mesh */ -int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) +static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) { ParticleThreadContext *ctx= threads[0].ctx; - Object *ob= ctx->ob; - ParticleSystem *psys= ctx->psys; + Object *ob= ctx->sim.ob; + ParticleSystem *psys= ctx->sim.psys; Object *tob; ParticleData *pa=0, *tpars= 0; ParticleSettings *part; @@ -1000,49 +973,49 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive totpart=get_psys_tot_child(scene, psys); cfrom=from=PART_FROM_FACE; - if(part->flag&PART_CHILD_SEAMS){ - MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE); - MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); - int totedge=dm->getNumEdges(dm); + //if(part->flag&PART_CHILD_SEAMS){ + // MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE); + // MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); + // int totedge=dm->getNumEdges(dm); - for(p=0, ed=medge; p<totedge; p++,ed++) - if(ed->flag&ME_SEAM) - totseam++; + // for(p=0, ed=medge; p<totedge; p++,ed++) + // if(ed->flag&ME_SEAM) + // totseam++; - if(totseam){ - ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams"); - float temp[3],temp2[3]; + // if(totseam){ + // ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams"); + // float temp[3],temp2[3]; - for(p=0, ed=medge; p<totedge; p++,ed++){ - if(ed->flag&ME_SEAM){ - VecCopyf(cur_seam->v0,(mvert+ed->v1)->co); - VecCopyf(cur_seam->v1,(mvert+ed->v2)->co); + // for(p=0, ed=medge; p<totedge; p++,ed++){ + // if(ed->flag&ME_SEAM){ + // VecCopyf(cur_seam->v0,(mvert+ed->v1)->co); + // VecCopyf(cur_seam->v1,(mvert+ed->v2)->co); - VecSubf(cur_seam->dir,cur_seam->v1,cur_seam->v0); + // VecSubf(cur_seam->dir,cur_seam->v1,cur_seam->v0); - cur_seam->length2=VecLength(cur_seam->dir); - cur_seam->length2*=cur_seam->length2; + // cur_seam->length2=VecLength(cur_seam->dir); + // cur_seam->length2*=cur_seam->length2; - temp[0]=(float)((mvert+ed->v1)->no[0]); - temp[1]=(float)((mvert+ed->v1)->no[1]); - temp[2]=(float)((mvert+ed->v1)->no[2]); - temp2[0]=(float)((mvert+ed->v2)->no[0]); - temp2[1]=(float)((mvert+ed->v2)->no[1]); - temp2[2]=(float)((mvert+ed->v2)->no[2]); + // temp[0]=(float)((mvert+ed->v1)->no[0]); + // temp[1]=(float)((mvert+ed->v1)->no[1]); + // temp[2]=(float)((mvert+ed->v1)->no[2]); + // temp2[0]=(float)((mvert+ed->v2)->no[0]); + // temp2[1]=(float)((mvert+ed->v2)->no[1]); + // temp2[2]=(float)((mvert+ed->v2)->no[2]); - VecAddf(cur_seam->nor,temp,temp2); - Normalize(cur_seam->nor); + // VecAddf(cur_seam->nor,temp,temp2); + // Normalize(cur_seam->nor); - Crossf(cur_seam->tan,cur_seam->dir,cur_seam->nor); + // Crossf(cur_seam->tan,cur_seam->dir,cur_seam->nor); - Normalize(cur_seam->tan); + // Normalize(cur_seam->tan); - cur_seam++; - } - } - } - - } + // cur_seam++; + // } + // } + // } + // + //} } else{ /* no need to figure out distribution */ @@ -1064,10 +1037,6 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive length=VecLength(cpa->fuv); } - cpa->rand[0]=BLI_frand(); - cpa->rand[1]=BLI_frand(); - cpa->rand[2]=BLI_frand(); - cpa->num=-1; } } @@ -1346,7 +1315,6 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive jitlevel= totpart/tot; if(part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */ if(jitlevel<3) jitlevel= 3; - //if(jitlevel>100) jitlevel= 100; } jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit"); @@ -1365,7 +1333,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive ctx->tree= tree; ctx->seams= seams; ctx->totseam= totseam; - ctx->psys= psys; + ctx->sim.psys= psys; ctx->index= index; ctx->jit= jit; ctx->jitlevel= jitlevel; @@ -1386,7 +1354,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive if(!children || psys->totchild < 10000) totthread= 1; - seed= 31415926 + ctx->psys->seed; + seed= 31415926 + ctx->sim.psys->seed; for(i=0; i<totthread; i++) { threads[i].rng= rng_new(seed); threads[i].tot= totthread; @@ -1395,16 +1363,17 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive return 1; } -static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Object *ob, ParticleSystem *psys, int from) +static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) { + DerivedMesh *finaldm = sim->psmd->dm; ListBase threads; ParticleThread *pthreads; ParticleThreadContext *ctx; int i, totthread; - pthreads= psys_threads_create(scene, ob, psys); + pthreads= psys_threads_create(sim); - if(!psys_threads_init_distribution(pthreads, scene, finaldm, from)) { + if(!psys_threads_init_distribution(pthreads, sim->scene, finaldm, from)) { psys_threads_free(pthreads); return; } @@ -1421,7 +1390,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Objec else exec_distribution(&pthreads[0]); - psys_calc_dmcache(ob, finaldm, psys); + psys_calc_dmcache(sim->ob, finaldm, sim->psys); ctx= pthreads[0].ctx; if(ctx->dm != finaldm) @@ -1431,8 +1400,9 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Objec } /* ready for future use, to emit particles without geometry */ -static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int from) +static void distribute_particles_on_shape(ParticleSimulationData *sim, int from) { + ParticleSystem *psys = sim->psys; PARTICLE_P; fprintf(stderr,"Shape emission not yet possible!\n"); @@ -1443,22 +1413,22 @@ static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int pa->num= -1; } } -static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, int from) +static void distribute_particles(ParticleSimulationData *sim, int from) { - ParticleSystemModifierData *psmd=0; + PARTICLE_PSMD; int distr_error=0; - psmd=psys_get_modifier(ob,psys); if(psmd){ if(psmd->dm) - distribute_particles_on_dm(psmd->dm, scene, ob, psys, from); + distribute_particles_on_dm(sim, from); else distr_error=1; } else - distribute_particles_on_shape(ob,psys,from); + distribute_particles_on_shape(sim, from); if(distr_error){ + ParticleSystem *psys = sim->psys; PARTICLE_P; fprintf(stderr,"Particle distribution error!\n"); @@ -1472,26 +1442,23 @@ static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, } /* threaded child particle distribution and path caching */ -ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys) +ParticleThread *psys_threads_create(ParticleSimulationData *sim) { ParticleThread *threads; ParticleThreadContext *ctx; int i, totthread; - if(scene->r.mode & R_FIXED_THREADS) - totthread= scene->r.threads; + if(sim->scene->r.mode & R_FIXED_THREADS) + totthread= sim->scene->r.threads; else totthread= BLI_system_thread_count(); threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread"); ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext"); - ctx->scene= scene; - ctx->ob= ob; - ctx->psys= psys; - ctx->psmd= psys_get_modifier(ob, psys); - ctx->dm= ctx->psmd->dm; - ctx->ma= give_current_material(ob, psys->part->omat); + ctx->sim = *sim; + ctx->dm= ctx->sim.psmd->dm; + ctx->ma= give_current_material(sim->ob, sim->psys->part->omat); memset(threads, 0, sizeof(ParticleThread)*totthread); @@ -1523,9 +1490,9 @@ void psys_threads_free(ParticleThread *threads) if(ctx->vg_roughe) MEM_freeN(ctx->vg_roughe); - if(ctx->psys->lattice){ - end_latt_deform(ctx->psys->lattice); - ctx->psys->lattice= NULL; + if(ctx->sim.psys->lattice){ + end_latt_deform(ctx->sim.psys->lattice); + ctx->sim.psys->lattice= NULL; } /* distribution */ @@ -1551,37 +1518,34 @@ void psys_threads_free(ParticleThread *threads) } /* set particle parameters that don't change during particle's life */ -void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) { - ParticleSettings *part; + ParticleSettings *part = sim->psys->part; ParticleTexture ptex; Material *ma=0; //IpoCurve *icu=0; // XXX old animation system int totpart; - float rand; - part=psys->part; - - totpart=psys->totpart; + totpart=sim->psys->totpart; ptex.life=ptex.size=ptex.exist=ptex.length=1.0; ptex.time=(float)p/(float)totpart; - BLI_srandom(psys->seed+p); + BLI_srandom(sim->psys->seed + p + 125); if(part->from!=PART_FROM_PARTICLE && part->type!=PART_FLUID){ - ma=give_current_material(ob,part->omat); + ma=give_current_material(sim->ob,part->omat); /* TODO: needs some work to make most blendtypes generally usefull */ - psys_get_texture(ob,ma,psmd,psys,pa,&ptex,MAP_PA_INIT); + psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT); } pa->lifetime= part->lifetime*ptex.life; if(part->type==PART_HAIR) pa->time= 0.0f; - else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) - pa->time= 300000.0f; /* max frame */ + //else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) + // pa->time= 300000.0f; /* max frame */ else{ //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME); //if(icu){ @@ -1605,10 +1569,8 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps } #endif // XXX old animation system - /* need to get every rand even if we don't use them so that randoms don't affect each other */ - rand= BLI_frand(); if(part->randlife!=0.0) - pa->lifetime*= 1.0f - part->randlife*rand; + pa->lifetime*= 1.0f - part->randlife * BLI_frand(); } pa->dietime= pa->time+pa->lifetime; @@ -1625,13 +1587,14 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps /* usage other than straight after distribute has to handle this index by itself - jahka*/ //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */ } -static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void initialize_all_particles(ParticleSimulationData *sim) { //IpoCurve *icu=0; // XXX old animation system + ParticleSystem *psys = sim->psys; PARTICLE_P; LOOP_PARTICLES - initialize_particle(pa,p,ob,psys,psmd); + initialize_particle(sim, pa, p); if(psys->part->type != PART_FLUID) { #if 0 // XXX old animation system @@ -1688,66 +1651,51 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS } } /* sets particle to the emitter surface with initial velocity & rotation */ -void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, ParticleSystemModifierData *psmd, Object *ob, - float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot) +void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra) { + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; ParticleSettings *part; ParticleTexture ptex; ParticleKey state; //IpoCurve *icu=0; // XXX old animation system - float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; + float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; - float q_phase[4], length, r_phase; + float q_phase[4], r_phase; + int p = pa - psys->particles; part=psys->part; ptex.ivel=1.0; - BLI_srandom(psys->seed + (pa - psys->particles)); - /* we need to get every random even if they're not used so that they don't effect eachother */ - /* while loops are to have a spherical distribution (avoid cubic distribution) */ - length=2.0f; - while(length>1.0){ - r_vel[0]=2.0f*(BLI_frand()-0.5f); - r_vel[1]=2.0f*(BLI_frand()-0.5f); - r_vel[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(r_vel); - } - - length=2.0f; - while(length>1.0){ - r_ave[0]=2.0f*(BLI_frand()-0.5f); - r_ave[1]=2.0f*(BLI_frand()-0.5f); - r_ave[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(r_ave); - } - - r_rot[0]=2.0f*(BLI_frand()-0.5f); - r_rot[1]=2.0f*(BLI_frand()-0.5f); - r_rot[2]=2.0f*(BLI_frand()-0.5f); - r_rot[3]=2.0f*(BLI_frand()-0.5f); - + r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); + r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); + r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); + + r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); + r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); + r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); + + r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); + r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); + r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); + r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); NormalQuat(r_rot); - r_phase = BLI_frand(); + r_phase = PSYS_FRAND(p + 20); if(part->from==PART_FROM_PARTICLE){ - Object *tob; - ParticleSystem *tpsys=0; + ParticleSimulationData tsim = {sim->scene, psys->target_ob ? psys->target_ob : ob, NULL, NULL}; float speed; - tob=psys->target_ob; - if(tob==0) - tob=ob; - - tpsys=BLI_findlink(&tob->particlesystem, psys->target_psys-1); + tsim.psys = BLI_findlink(&tsim.ob->particlesystem, sim->psys->target_psys-1); state.time = pa->time; if(pa->num == -1) memset(&state, 0, sizeof(state)); else - psys_get_particle_state(scene, tob,tpsys,pa->num,&state,1); + psys_get_particle_state(&tsim, pa->num, &state, 1); psys_get_from_key(&state, loc, nor, rot, 0); QuatMulVecf(rot, vtan); @@ -1764,23 +1712,20 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic } else{ /* get precise emitter matrix if particle is born */ - if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= psys->cfra) - where_is_object_time(scene, ob,pa->time); + if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) + where_is_object_time(sim->scene, sim->ob, pa->time); /* get birth location from object */ if(part->tanfac!=0.0) - psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); else - psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); - - /* save local coordinates for later */ - VECCOPY(tloc,loc); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); /* get possible textural influence */ - psys_get_texture(ob,give_current_material(ob,part->omat),psmd,psys,pa,&ptex,MAP_PA_IVEL); + psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL); - if(vg_vel && pa->num != -1) - ptex.ivel*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_vel); + //if(vg_vel && pa->num != -1) + // ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel); /* particles live in global space so */ /* let's convert: */ @@ -1788,21 +1733,18 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic Mat4MulVecfl(ob->obmat,loc); /* -normal */ - VECADD(nor,tloc,nor); - Mat4MulVecfl(ob->obmat,nor); - VECSUB(nor,nor,loc); + Mat4Mul3Vecfl(ob->obmat,nor); Normalize(nor); /* -tangent */ if(part->tanfac!=0.0){ - float phase=vg_rot?2.0f*(psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + float phase=0.0f; VecMulf(vtan,-(float)cos(M_PI*(part->tanphase+phase))); fac=-(float)sin(M_PI*(part->tanphase+phase)); VECADDFAC(vtan,vtan,utan,fac); - VECADD(vtan,tloc,vtan); - Mat4MulVecfl(ob->obmat,vtan); - VECSUB(vtan,vtan,loc); + Mat4Mul3Vecfl(ob->obmat,vtan); VECCOPY(utan,nor); VecMulf(utan,Inpf(vtan,nor)); @@ -1851,13 +1793,9 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic /* 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]; - - //pa->r_ve[0] = pa->r_ve[1] = 0.0f; - //pa->r_ve[2] = -1.0f; - //if(part->acc[2]!=0.0f) - // pa->r_ve[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); @@ -1897,8 +1835,9 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic VECADDFAC(vel,vel,nor,part->normfac); /* *emitter tangent */ - if(psmd && part->tanfac!=0.0) - VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_tan):1.0f)); + if(sim->psmd && part->tanfac!=0.0) + VECADDFAC(vel,vel,vtan,part->tanfac); + //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f)); /* *texture */ /* TODO */ @@ -1918,9 +1857,6 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic //} VecMulf(vel,ptex.ivel); - - //if(ELEM(part->phystype, PART_PHYS_GRADU_EX, PART_PHYS_GRADU_SIM)) - // VecAddf(vel,vel,part->acc); VECCOPY(pa->state.vel,vel); @@ -1998,26 +1934,28 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic 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; - -// pa->flag &= ~PARS_STICKY; } -static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from) +static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from) { ParticleData *pa; - int p, totpart=psys->totpart; - float *vg_vel=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); - float *vg_tan=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); - float *vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); + int p, totpart=sim->psys->totpart; + //float *vg_vel=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_VEL); + //float *vg_tan=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_TAN); + //float *vg_rot=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_ROT); - for(p=from, pa=psys->particles+from; p<totpart; p++, pa++) - reset_particle(scene, pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot); + for(p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++) + reset_particle(sim, pa, dtime, cfra); - if(vg_vel) - MEM_freeN(vg_vel); + //if(vg_vel) + // MEM_freeN(vg_vel); } /************************************************/ /* Particle targets */ @@ -2042,15 +1980,15 @@ ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt) /* Keyed particles */ /************************************************/ /* Counts valid keyed targets */ -void psys_count_keyed_targets(Object *ob, ParticleSystem *psys) +void psys_count_keyed_targets(ParticleSimulationData *sim) { - ParticleSystem *kpsys; + ParticleSystem *psys = sim->psys, *kpsys; ParticleTarget *pt = psys->targets.first; int keys_valid = 1; psys->totkeyed = 0; for(; pt; pt=pt->next) { - kpsys = psys_get_target_system(ob, pt); + kpsys = psys_get_target_system(sim->ob, pt); if(kpsys && kpsys->totpart) { psys->totkeyed += keys_valid; @@ -2065,9 +2003,10 @@ void psys_count_keyed_targets(Object *ob, ParticleSystem *psys) psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops; } -static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) +static void set_keyed_keys(ParticleSimulationData *sim) { - ParticleSystem *kpsys = psys; + ParticleSystem *psys = sim->psys; + ParticleSimulationData ksim = {sim->scene, NULL, NULL, NULL}; ParticleTarget *pt; PARTICLE_P; ParticleKey *key; @@ -2097,16 +2036,14 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) pt = psys->targets.first; for(k=0; k<totkeys; k++) { - if(pt->ob) - kpsys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1); - else - kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1); + ksim.ob = pt->ob ? pt->ob : sim->ob; + ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1); LOOP_PARTICLES { key = pa->keys + k; key->time = -1.0; /* use current time */ - psys_get_particle_state(scene, pt->ob, kpsys, p%kpsys->totpart, key, 1); + psys_get_particle_state(&ksim, p%ksim.psys->totpart, key, 1); if(psys->flag & PSYS_KEYED_TIMING){ key->time = pa->time + pt->time; @@ -2132,111 +2069,109 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) /************************************************/ /* Reactors */ /************************************************/ -static void push_reaction(Object* ob, ParticleSystem *psys, int pa_num, int event, ParticleKey *state) -{ - Object *rob; - ParticleSystem *rpsys; - ParticleSettings *rpart; - ParticleData *pa; - ListBase *lb=&psys->effectors; - ParticleEffectorCache *ec; - ParticleReactEvent *re; - - if(lb->first) for(ec = lb->first; ec; ec= ec->next){ - if(ec->type & PSYS_EC_REACTOR){ - /* all validity checks already done in add_to_effectors */ - rob=ec->ob; - rpsys=BLI_findlink(&rob->particlesystem,ec->psys_nbr); - rpart=rpsys->part; - if(rpsys->part->reactevent==event){ - pa=psys->particles+pa_num; - re= MEM_callocN(sizeof(ParticleReactEvent), "react event"); - re->event=event; - re->pa_num = pa_num; - re->ob = ob; - re->psys = psys; - re->size = pa->size; - copy_particle_key(&re->state,state,1); - - switch(event){ - case PART_EVENT_DEATH: - re->time=pa->dietime; - break; - case PART_EVENT_COLLIDE: - re->time=state->time; - break; - case PART_EVENT_NEAR: - re->time=state->time; - break; - } - - BLI_addtail(&rpsys->reactevents, re); - } - } - } -} -static void react_to_events(ParticleSystem *psys, int pa_num) -{ - ParticleSettings *part=psys->part; - ParticleData *pa=psys->particles+pa_num; - ParticleReactEvent *re=psys->reactevents.first; - int birth=0; - float dist=0.0f; - - for(re=psys->reactevents.first; re; re=re->next){ - birth=0; - if(part->from==PART_FROM_PARTICLE){ - if(pa->num==re->pa_num && pa->alive==PARS_UNBORN){ - if(re->event==PART_EVENT_NEAR){ - ParticleData *tpa = re->psys->particles+re->pa_num; - float pa_time=tpa->time + pa->foffset*tpa->lifetime; - if(re->time >= pa_time){ - pa->time=pa_time; - pa->dietime=pa->time+pa->lifetime; - } - } - else{ - pa->time=re->time; - pa->dietime=pa->time+pa->lifetime; - } - } - } - else{ - dist=VecLenf(pa->state.co, re->state.co); - if(dist <= re->size){ - if(pa->alive==PARS_UNBORN){ - pa->time=re->time; - pa->dietime=pa->time+pa->lifetime; - birth=1; - } - if(birth || part->flag&PART_REACT_MULTIPLE){ - float vec[3]; - VECSUB(vec,pa->state.co, re->state.co); - if(birth==0) - VecMulf(vec,(float)pow(1.0f-dist/re->size,part->reactshape)); - VECADDFAC(pa->state.vel,pa->state.vel,vec,part->reactfac); - VECADDFAC(pa->state.vel,pa->state.vel,re->state.vel,part->partfac); - } - if(birth) - VecMulf(pa->state.vel,(float)pow(1.0f-dist/re->size,part->reactshape)); - } - } - } -} -void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_ob, ParticleSystem **target_psys) -{ - Object *tob; - - tob=psys->target_ob; - if(tob==0) - tob=ob; - - *target_psys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); - if(*target_psys) - *target_ob=tob; - else - *target_ob=0; -} +//static void push_reaction(ParticleSimulationData *sim, int pa_num, int event, ParticleKey *state) +//{ +// Object *rob; +// ParticleSystem *rpsys; +// ParticleSettings *rpart; +// ParticleData *pa; +// ListBase *lb=&sim->psys->effectors; +// ParticleEffectorCache *ec; +// ParticleReactEvent *re; +// +// if(lb->first) for(ec = lb->first; ec; ec= ec->next){ +// if(ec->type & PSYS_EC_REACTOR){ +// /* all validity checks already done in add_to_effectors */ +// rob=ec->ob; +// rpsys=BLI_findlink(&rob->particlesystem,ec->psys_nbr); +// rpart=rpsys->part; +// if(rpsys->part->reactevent==event){ +// pa=sim->psys->particles+pa_num; +// re= MEM_callocN(sizeof(ParticleReactEvent), "react event"); +// re->event=event; +// re->pa_num = pa_num; +// re->ob = sim->ob; +// re->psys = sim->psys; +// re->size = pa->size; +// copy_particle_key(&re->state,state,1); +// +// switch(event){ +// case PART_EVENT_DEATH: +// re->time=pa->dietime; +// break; +// case PART_EVENT_COLLIDE: +// re->time=state->time; +// break; +// case PART_EVENT_NEAR: +// re->time=state->time; +// break; +// } +// +// BLI_addtail(&rpsys->reactevents, re); +// } +// } +// } +//} +//static void react_to_events(ParticleSystem *psys, int pa_num) +//{ +// ParticleSettings *part=psys->part; +// ParticleData *pa=psys->particles+pa_num; +// ParticleReactEvent *re=psys->reactevents.first; +// int birth=0; +// float dist=0.0f; +// +// for(re=psys->reactevents.first; re; re=re->next){ +// birth=0; +// if(part->from==PART_FROM_PARTICLE){ +// if(pa->num==re->pa_num && pa->alive==PARS_UNBORN){ +// if(re->event==PART_EVENT_NEAR){ +// ParticleData *tpa = re->psys->particles+re->pa_num; +// float pa_time=tpa->time + pa->foffset*tpa->lifetime; +// if(re->time >= pa_time){ +// pa->time=pa_time; +// pa->dietime=pa->time+pa->lifetime; +// } +// } +// else{ +// pa->time=re->time; +// pa->dietime=pa->time+pa->lifetime; +// } +// } +// } +// else{ +// dist=VecLenf(pa->state.co, re->state.co); +// if(dist <= re->size){ +// if(pa->alive==PARS_UNBORN){ +// pa->time=re->time; +// pa->dietime=pa->time+pa->lifetime; +// birth=1; +// } +// if(birth || part->flag&PART_REACT_MULTIPLE){ +// float vec[3]; +// VECSUB(vec,pa->state.co, re->state.co); +// if(birth==0) +// VecMulf(vec,(float)pow(1.0f-dist/re->size,part->reactshape)); +// VECADDFAC(pa->state.vel,pa->state.vel,vec,part->reactfac); +// VECADDFAC(pa->state.vel,pa->state.vel,re->state.vel,part->partfac); +// } +// if(birth) +// VecMulf(pa->state.vel,(float)pow(1.0f-dist/re->size,part->reactshape)); +// } +// } +// } +//} +//void psys_get_reactor_target(ParticleSimulationData *sim, Object **target_ob, ParticleSystem **target_psys) +//{ +// Object *tob; +// +// tob = sim->psys->target_ob ? sim->psys->target_ob : sim->ob; +// +// *target_psys = BLI_findlink(&tob->particlesystem, sim->psys->target_psys-1); +// if(*target_psys) +// *target_ob=tob; +// else +// *target_ob=0; +//} /************************************************/ /* Point Cache */ /************************************************/ @@ -2252,7 +2187,7 @@ void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) BKE_ptcache_disk_to_mem(&pid); } -void psys_clear_temp_pointcache(ParticleSystem *psys) +static void psys_clear_temp_pointcache(ParticleSystem *psys) { if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0) return; @@ -2270,555 +2205,52 @@ 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); psys->tree = BLI_kdtree_new(psys->totpart); - LOOP_PARTICLES { - if(pa->flag & (PARS_NO_DISP+PARS_UNEXIST) || pa->alive != PARS_ALIVE) - continue; - - BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); - } - BLI_kdtree_balance(psys->tree); - - psys->tree_frame = psys->cfra; - } - } -} -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;///(float)pow((double)distance,(double)power); - - 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(ListBase *lb, Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys) -{ - ParticleEffectorCache *ec; - PartDeflect *pd= ob->pd; - short type=0,i; - - if(pd && ob != obsrc){ - 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(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!=psys || (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)==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(Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys, ListBase *listb, int level) -{ - Group *group; - GroupObject *go; - unsigned int layer= obsrc->lay; - - if(level>MAX_DUPLI_RECUR) return; - - if(ob->lay & layer) { - if(ob->pd || ob->particlesystem.first) - add_to_effectors(listb, scene, ob, obsrc, psys); - - if(ob->dup_group) { - group= ob->dup_group; - for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, level+1); - } - } -} - -void psys_init_effectors(Scene *scene, Object *obsrc, Group *group, ParticleSystem *psys) -{ - ListBase *listb= &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(scene, go->ob, obsrc, psys, listb, 0); - } - else { - for(base = scene->base.first; base; base= base->next) - psys_init_effectors_recurs(scene, base->object, obsrc, psys, 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); -} - -static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) -{ - ListBase *lb=&psys->effectors; - ParticleEffectorCache *ec; - ParticleSettings *part=psys->part; - PARTICLE_P; - int totpart; - 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); - } + LOOP_SHOWN_PARTICLES { + if(pa->alive == PARS_ALIVE) { + if(pa->state.time == cfra) + BLI_kdtree_insert(psys->tree, p, pa->prev_state.co, NULL); else - psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); - - Mat4MulVecfl(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){ - Object *eob = ec->ob; - ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); - ParticleSettings *epart = epsys->part; - ParticleData *epa; - int p, totepart = epsys->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=epsys->particles; p<totepart; p++,epa++) - if(epa->alive==PARS_ALIVE && psys_get_particle_state(scene, eob,epsys,p,&state,0)) - BLI_kdtree_insert(tree, p, state.co, NULL); - - BLI_kdtree_balance(tree); + BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); } } + BLI_kdtree_balance(psys->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); + psys->tree_frame = psys->cfra; } } } -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(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, Object *ob, ParticleSystem *psys, float *rootco, float *force_field, float *vel,float framestep, float cfra) -{ - Object *eob; - ParticleSystem *epsys; - 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(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(psys->part)); - VecAddf(pco, state->co, velocity); - } - else - VECCOPY(pco, state->co); - - effector_find_co(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(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){ - int totepart, i; - epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr); - epart= epsys->part; - pd=epart->pd; - totepart= epsys->totpart; - - if(totepart <= 0) - continue; - - if(pd && pd->forcefield==PFIELD_HARMONIC){ - /* every particle is mapped to only one harmonic effector particle */ - p= pa_no%epsys->totpart; - totepart= p+1; - } - else{ - p=0; - } - - epsys->lattice= psys_get_lattice(scene, ob, psys); - - for(; p<totepart; p++){ - /* particle skips itself as effector */ - if(epsys==psys && p == pa_no) continue; - - epa = epsys->particles + p; - estate.time=cfra; - if(psys_get_particle_state(scene, eob,epsys,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(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(scene, eob,epsys,p,&estate,1); - VECADD(vel,vel,estate.vel); - /* TODO: add rotation handling here too */ - } - } - - if(epsys->lattice){ - end_latt_deform(epsys->lattice); - epsys->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); } /************************************************/ /* Newtonian physics */ /************************************************/ /* gathers all forces that effect particles and calculates a new state for the particle */ -static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra) +static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra, float cfra) { + ParticleSettings *part = sim->psys->part; + ParticleData *pa = sim->psys->particles + p; + EffectedPoint epoint; ParticleKey states[5], tkey; - float force[3],tvel[3],dx[4][3],dv[4][3]; - float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=psys->cfra; + float timestep = psys_get_timestep(sim); + 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; /* maintain angular velocity */ @@ -2843,10 +2275,11 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj 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(pa_no,pa,states+i,scene, ob, psys,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){ @@ -2865,10 +2298,17 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj 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: @@ -2879,7 +2319,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj if(i==0){ VECADDFAC(states[1].co,states->co,states->vel,dtime*0.5f); VECADDFAC(states[1].vel,states->vel,force,dtime*0.5f); - fra=psys->cfra+0.5f*dfra; + fra=sim->psys->cfra+0.5f*dfra; } else{ VECADDFAC(pa->state.co,states->co,states[1].vel,dtime); @@ -2896,7 +2336,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj VECADDFAC(states[1].co,states->co,dx[0],0.5f); VECADDFAC(states[1].vel,states->vel,dv[0],0.5f); - fra=psys->cfra+0.5f*dfra; + fra=sim->psys->cfra+0.5f*dfra; break; case 1: VECADDFAC(dx[1],states->vel,dv[0],0.5f); @@ -2941,6 +2381,8 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj 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); @@ -2950,7 +2392,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj tkey.time=pa->state.time; if(part->type != PART_HAIR) { - if(do_guide(scene, &tkey, pa_no, time, &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); @@ -3181,7 +2623,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; } } } @@ -3198,7 +2641,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; } } } @@ -3214,15 +2658,16 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 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(Scene *scene, Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){ - Object *ob = NULL, *skip_ob = NULL; - ListBase *lb=&psys->effectors; - ParticleEffectorCache *ec; - ParticleKey reaction_state; +static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){ + Object *ground_ob = NULL; + ParticleSettings *part = sim->psys->part; + 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; + float timestep = psys_get_timestep(sim); int deflections=0, max_deflections=10; VECCOPY(col.co1, pa->prev_state.co); @@ -3234,11 +2679,11 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa 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); @@ -3250,32 +2695,25 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa 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==pob && pa->time < cfra && pa->time >= 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(scene,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 */ @@ -3302,9 +2740,6 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /* 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]; @@ -3400,9 +2835,9 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa } /* store state for reactors */ - VECCOPY(reaction_state.co, co); - VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); - QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); + //VECCOPY(reaction_state.co, co); + //VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); + //QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); /* set coordinates for next iteration */ VECCOPY(col.co1, co); @@ -3424,8 +2859,8 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa } deflections++; - reaction_state.time = cfra - (1.0f - dt) * dfra; - push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); + //reaction_state.time = cfra - (1.0f - dt) * dfra; + //push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); } else return; @@ -3435,43 +2870,44 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /* Hair */ /************************************************/ /* check if path cache or children need updating and do it if needed */ -static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void psys_update_path_cache(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part=psys->part; - ParticleEditSettings *pset=&scene->toolsettings->particle; - int distr=0,alloc=0,skip=0; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + ParticleEditSettings *pset = &sim->scene->toolsettings->particle; + int distr=0, alloc=0, skip=0; - if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) + if((psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; - if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) + if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT))) distr=1; if(distr){ if(alloc) - realloc_particles(ob,psys,psys->totpart); + realloc_particles(sim, sim->psys->totpart); - if(get_psys_tot_child(scene, psys)) { + if(get_psys_tot_child(sim->scene, psys)) { /* don't generate children while computing the hair keys */ if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + distribute_particles(sim, PART_FROM_CHILD); if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) - psys_find_parents(ob,psmd,psys); + psys_find_parents(sim); } } } 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) skip = 1; /* draw visualization */ else if(psys->pointcache->flag & PTCACHE_BAKING) skip = 1; /* no need to cache paths while baking dynamics */ - else if(psys_in_edit_mode(scene, psys)) { + else if(psys_in_edit_mode(sim->scene, psys)) { if((pset->flag & PE_DRAW_PART)==0) skip = 1; else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) @@ -3480,7 +2916,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif } if(!skip) { - psys_cache_paths(scene, ob, psys, cfra); + psys_cache_paths(sim, cfra); /* for render, child particle paths are computed on the fly */ if(part->childtype) { @@ -3490,15 +2926,16 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif skip = 1; if(!skip) - psys_cache_child_paths(scene, ob, psys, cfra, 0); + psys_cache_child_paths(sim, cfra, 0); } } else if(psys->pathcache) psys_free_path_cache(psys, NULL); } -static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void do_hair_dynamics(ParticleSimulationData *sim) { + ParticleSystem *psys = sim->psys; DerivedMesh *dm = psys->hair_in_dm; MVert *mvert = NULL; MEdge *medge = NULL; @@ -3521,7 +2958,8 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par LOOP_PARTICLES totpoint += pa->totkey; - totedge = totpoint - psys->totpart; + totedge = totpoint; + totpoint += psys->totpart; if(dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) { dm->release(dm); @@ -3540,14 +2978,39 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par psys->clmd->sim_parms->vgroup_mass = 1; /* make vgroup for pin roots etc.. */ - psys->particles->hair_index = 0; + psys->particles->hair_index = 1; LOOP_PARTICLES { if(p) - pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey; + pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey + 1; - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); for(k=0, key=pa->hair; k<pa->totkey; k++,key++) { + + /* create fake root before actual root to resist bending */ + if(k==0) { + float temp[3]; + VECSUB(temp, key->co, (key+1)->co); + VECCOPY(mvert->co, key->co); + VECADD(mvert->co, mvert->co, temp); + Mat4MulVecfl(hairmat, mvert->co); + mvert++; + + medge->v1 = pa->hair_index - 1; + medge->v2 = pa->hair_index; + medge++; + + if(dvert) { + if(!dvert->totweight) { + dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->totweight = 1; + } + + dvert->dw->weight = 1.0f; + dvert++; + } + } + VECCOPY(mvert->co, key->co); Mat4MulVecfl(hairmat, mvert->co); mvert++; @@ -3576,19 +3039,23 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par 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, scene, ob, dm, 0, 0); + 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(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void hair_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part = psys->part; + ParticleSystem *psys = sim->psys; +/* ParticleSettings *part = psys->part; */ PARTICLE_P; float disp = (float)get_current_display_percentage(psys)/100.0f; BLI_srandom(psys->seed); LOOP_PARTICLES { - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -3596,36 +3063,33 @@ static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd if(psys->recalc & PSYS_RECALC_RESET) { /* need this for changing subsurf levels */ - psys_calc_dmcache(ob, psmd->dm, psys); + psys_calc_dmcache(sim->ob, sim->psmd->dm, psys); if(psys->clmd) - cloth_free_modifier(ob, psys->clmd); + cloth_free_modifier(sim->ob, psys->clmd); } - if(psys->effectors.first) - psys_end_effectors(psys); - /* dynamics with cloth simulation */ if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) - do_hair_dynamics(scene, ob, psys, psmd); + do_hair_dynamics(sim); - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); + psys_update_effectors(sim); - psys_update_path_cache(scene, ob,psmd,psys,cfra); + psys_update_path_cache(sim, cfra); psys->flag |= PSYS_HAIR_UPDATED; } -static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ +static void save_hair(ParticleSimulationData *sim, float cfra){ + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; HairKey *key, *root; PARTICLE_P; int totpart; - Mat4Invert(ob->imat,ob->obmat); + Mat4Invert(ob->imat, ob->obmat); - psys->lattice= psys_get_lattice(scene, ob, psys); + psys->lattice= psys_get_lattice(sim); if(psys->totpart==0) return; @@ -3648,7 +3112,7 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy if(pa->totkey) { VECSUB(key->co, key->co, root->co); - psys_vec_rot_to_face(psmd->dm, pa, key->co); + psys_vec_rot_to_face(sim->psmd->dm, pa, key->co); } key->time = pa->state.time; @@ -3666,13 +3130,13 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy /* System Core */ /************************************************/ /* unbaked particles are calculated dynamically */ -static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra, - float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size) +static void dynamics_step(ParticleSimulationData *sim, float cfra) { + ParticleSystem *psys = sim->psys; ParticleSettings *part=psys->part; KDTree *tree=0; - IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system - Material *ma=give_current_material(ob,part->omat); + //IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system +/* Material *ma=give_current_material(sim->ob, part->omat); */ BoidBrainData bbd; PARTICLE_P; float timestep; @@ -3688,7 +3152,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic totpart=psys->totpart; - timestep=psys_get_timestep(part); + timestep = psys_get_timestep(sim); dtime= dfra*timestep; ctime= cfra*timestep; ipotime= cfra; // XXX old animation system @@ -3702,12 +3166,10 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic if(dfra<0.0){ float *vg_size=0; - if(part->type==PART_REACTOR) - vg_size=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); - - LOOP_PARTICLES { - if(pa->flag & PARS_UNEXIST) continue; + //if(part->type==PART_REACTOR) + // vg_size=psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); + LOOP_EXISTING_PARTICLES { /* set correct ipo timing */ #if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ @@ -3716,25 +3178,18 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(sim, pa, dtime, cfra); - if(cfra>pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ - pa->loop=(short)((cfra-pa->time)/pa->lifetime); - pa->alive=PARS_UNBORN; + if(cfra > pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ + pa->loop = (short)((cfra-pa->time)/pa->lifetime); + pa->alive = PARS_UNBORN; } 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; } } @@ -3743,40 +3198,32 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } else{ BLI_srandom(31415926 + (int)cfra + psys->seed); - - /* update effectors */ - if(psys->effectors.first) - psys_end_effectors(psys); - psys_init_effectors(scene, ob, part->eff_group, psys); - - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); + 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; - bbd.scene = scene; - bbd.ob = ob; - bbd.psys = psys; + bbd.sim = sim; bbd.part = part; bbd.cfra = 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); } } /* main loop: calculate physics for all particles */ - LOOP_PARTICLES { - if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; - + LOOP_SHOWN_PARTICLES { copy_particle_key(&pa->prev_state,&pa->state,1); /* set correct ipo timing */ @@ -3787,23 +3234,19 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + //update_particle_settings(psys, part, &tpart, pa); + + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - /* reactions can change birth time so they need to be checked first */ - if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) - react_to_events(psys,p); + ///* reactions can change birth time so they need to be checked first */ + //if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) + // react_to_events(psys,p); birthtime = pa->time + pa->loop * pa->lifetime; dietime = birthtime + pa->lifetime; - /* allways reset particles to emitter before birth */ - if(pa->alive==PARS_UNBORN - || pa->alive==PARS_KILLED - || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) - || birthtime >= psys->cfra){ - reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); - } - pa_dfra = dfra; pa_dtime = dtime; @@ -3816,6 +3259,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } else if(birthtime <= cfra && birthtime >= psys->cfra){ /* particle is born some time between this and last step*/ + reset_particle(sim, pa, dtime, cfra); pa->alive = PARS_ALIVE; pa_dfra = cfra - birthtime; pa_dtime = pa_dfra*timestep; @@ -3824,18 +3268,22 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic /* nothing to be done when particle is dead */ } + /* only reset unborn particles if they're shown */ + if(pa->alive==PARS_UNBORN && part->flag & PART_UNBORN) + reset_particle(sim, pa, dtime, cfra); if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ - apply_particle_forces(scene, p, pa, ob, psys, part, timestep,pa_dfra,cfra); + apply_particle_forces(sim, p, pa_dfra, cfra); /* deflection */ - deflect_particle(scene, ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); + if(sim->colliders) + deflect_particle(sim, p, pa_dfra, cfra); /* rotations */ - rotate_particle(part,pa,pa_dfra,timestep); + rotate_particle(part, pa, pa_dfra, timestep); break; case PART_PHYS_BOIDS: { @@ -3845,18 +3293,19 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic boid_body(&bbd, pa); /* deflection */ - deflect_particle(scene,ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); + if(sim->colliders) + deflect_particle(sim, p, pa_dfra, cfra); } break; } } if(pa->alive == PARS_DYING){ - push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); + //push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); if(part->flag & PART_LOOP && part->type!=PART_HAIR){ pa->loop++; - reset_particle(scene, pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(sim, pa, 0.0, cfra); pa->alive=PARS_ALIVE; } else{ @@ -3867,40 +3316,33 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic else pa->state.time=cfra; - push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); + //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); } /* updates cached particles' alive & other flags etc..*/ -static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void cached_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part=psys->part; - ParticleKey state; - IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system - Material *ma=give_current_material(ob,part->omat); + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + //IpoCurve *icu_esize = NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system +/* Material *ma = give_current_material(sim->ob,part->omat); */ PARTICLE_P; float disp, birthtime, dietime, *vg_size= NULL; // XXX ipotime=cfra BLI_srandom(psys->seed); if(part->from!=PART_FROM_PARTICLE) - vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); + vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); - if(psys->effectors.first) - psys_end_effectors(psys); - - //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); - //} + psys_update_effectors(sim); disp= (float)get_current_display_percentage(psys)/100.0f; @@ -3912,9 +3354,13 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size= psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + //update_settings_with_particle(psys, part, pa); - psys->lattice= psys_get_lattice(scene, ob, psys); + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); + + psys->lattice= psys_get_lattice(sim); if(part->flag & PART_LOOP && part->type!=PART_HAIR) pa->loop = (short)((cfra - pa->time) / pa->lifetime); @@ -3925,25 +3371,16 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time); /* update alive status and push events */ - if(pa->time >= cfra) { - pa->alive = pa->time==cfra ? PARS_ALIVE : PARS_UNBORN; - if((psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) - reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL); + if(pa->time > cfra) { + pa->alive = PARS_UNBORN; + if(part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) + reset_particle(sim, pa, 0.0f, cfra); } else if(dietime <= cfra){ - if(dietime > psys->cfra){ - state.time = dietime; - psys_get_particle_state(scene, ob,psys,p,&state,1); - push_reaction(ob,psys,p,PART_EVENT_DEATH,&state); - } pa->alive = PARS_DEAD; } else{ pa->alive = PARS_ALIVE; - state.time = cfra; - psys_get_particle_state(scene, ob,psys,p,&state,1); - state.time = cfra; - push_reaction(ob,psys,p,PART_EVENT_NEAR,&state); } if(psys->lattice){ @@ -3951,43 +3388,41 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps psys->lattice= NULL; } - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; } /* make sure that children are up to date */ - if(psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) { - realloc_particles(ob, psys, psys->totpart); - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + if(psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) { + realloc_particles(sim, psys->totpart); + distribute_particles(sim, PART_FROM_CHILD); } - psys_update_path_cache(scene, ob,psmd,psys,cfra); + psys_update_path_cache(sim, cfra); if(vg_size) MEM_freeN(vg_size); } -static void psys_changed_type(Object *ob, ParticleSystem *psys) +static void psys_changed_type(ParticleSimulationData *sim) { - ParticleSettings *part; + ParticleSettings *part = sim->psys->part; PTCacheID pid; - part= psys->part; - - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); /* system type has changed so set sensible defaults and clear non applicable flags */ if(part->from == PART_FROM_PARTICLE) { - if(part->type != PART_REACTOR) - part->from = PART_FROM_FACE; + //if(part->type != PART_REACTOR) + part->from = PART_FROM_FACE; if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT) part->distr = PART_DISTR_JIT; } if(part->phystype != PART_PHYS_KEYED) - psys->flag &= ~PSYS_KEYED; + sim->psys->flag &= ~PSYS_KEYED; if(part->type == PART_HAIR) { if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) @@ -4002,13 +3437,13 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys) BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_hair(ob, psys, 1); + free_hair(sim->ob, sim->psys, 1); CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime)); CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime)); } - psys_reset(psys, PSYS_RESET_ALL); + psys_reset(sim->psys, PSYS_RESET_ALL); } void psys_check_boid_data(ParticleSystem *psys) { @@ -4034,24 +3469,24 @@ void psys_check_boid_data(ParticleSystem *psys) pa->boid = NULL; } } -static void psys_changed_physics(Object *ob, ParticleSystem *psys) +static void psys_changed_physics(ParticleSimulationData *sim) { - ParticleSettings *part = psys->part; + ParticleSettings *part = sim->psys->part; if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) { PTCacheID pid; - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_keyed_keys(psys); - psys->flag &= ~PSYS_KEYED; + free_keyed_keys(sim->psys); + sim->psys->flag &= ~PSYS_KEYED; } if(part->phystype == PART_PHYS_BOIDS && part->boids == NULL) { BoidState *state; - psys_check_boid_data(psys); + psys_check_boid_data(sim->psys); part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings"); boid_default_settings(part->boids); @@ -4066,8 +3501,9 @@ static void psys_changed_physics(Object *ob, ParticleSystem *psys) BLI_addtail(&part->boids->states, state); } } -static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, int cfra) +static void particles_fluid_step(ParticleSimulationData *sim, int cfra) { + ParticleSystem *psys = sim->psys; if(psys->particles){ MEM_freeN(psys->particles); psys->particles = 0; @@ -4077,7 +3513,7 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, /* fluid sim particle import handling, actual loading of particles from file */ #ifndef DISABLE_ELBEEM { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); + FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim); if( fluidmd && fluidmd->fss) { FluidsimSettings *fss= fluidmd->fss; @@ -4087,7 +3523,7 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, char *suffix2 = ".gz"; char filename[256]; char debugStrBuffer[256]; - int curFrame = scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading + int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading int p, j, numFileParts, totpart; int readMask, activeParts = 0, fileParts = 0; gzFile gzf; @@ -4115,11 +3551,11 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, part->totpart= totpart; part->sta=part->end = 1.0f; - part->lifetime = scene->r.efra + 1; + part->lifetime = sim->scene->r.efra + 1; /* initialize particles */ - realloc_particles(ob, psys, part->totpart); - initialize_all_particles(ob, psys, 0); + realloc_particles(sim, part->totpart); + initialize_all_particles(sim); // set up reading mask readMask = fss->typeFlags; @@ -4175,10 +3611,11 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, /* Calculates the next state for all particles of the system */ /* In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)*/ -static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +static void system_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part; - PointCache *cache; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + PointCache *cache = psys->pointcache; PTCacheID pid; PARTICLE_P; int totpart, oldtotpart, totchild, oldtotchild; @@ -4186,20 +3623,17 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; int framenr, framedelta, startframe, endframe; - part= psys->part; - cache= psys->pointcache; - - framenr= (int)scene->r.cfra; + framenr= (int)sim->scene->r.cfra; framedelta= framenr - cache->simframe; /* set suitable cache range automatically */ if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0 && !(psys->flag & PSYS_HAIR_DYNAMICS)) - psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe); + psys_get_pointcache_start_end(sim->scene, sim->psys, &cache->startframe, &cache->endframe); - BKE_ptcache_id_from_particles(&pid, ob, psys); - BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL); + BKE_ptcache_id_from_particles(&pid, sim->ob, psys); + BKE_ptcache_id_time(&pid, sim->scene, 0.0f, &startframe, &endframe, NULL); - psys_clear_temp_pointcache(psys); + psys_clear_temp_pointcache(sim->psys); /* update ipo's */ #if 0 // XXX old animation system @@ -4211,14 +3645,14 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* hair if it's already done is handled separate */ if(part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)) { - hair_step(scene, ob, psmd, psys, cfra); + hair_step(sim, cfra); psys->cfra = cfra; psys->recalc = 0; return; } /* fluid is also handled separate */ else if(part->type == PART_FLUID) { - particles_fluid_step(scene, ob, psys, framenr); + particles_fluid_step(sim, framenr); psys->cfra = cfra; psys->recalc = 0; return; @@ -4243,6 +3677,13 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle 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 */ @@ -4255,7 +3696,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle totpart = part->grid_res*part->grid_res*part->grid_res; else totpart = psys->part->totpart; - totchild = get_psys_tot_child(scene, psys); + totchild = get_psys_tot_child(sim->scene, psys); if(oldtotpart != totpart || oldtotchild != totchild) { only_children_changed = (oldtotpart == totpart); @@ -4272,45 +3713,45 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(init) { if(distr) { if(alloc) { - realloc_particles(ob, psys, totpart); + 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, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, psys); } } if(!only_children_changed) - distribute_particles(scene, ob, psys, part->from); + distribute_particles(sim, part->from); if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) /* don't generate children while growing hair - waste of time */ psys_free_children(psys); - else if(get_psys_tot_child(scene, psys)) - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + else if(get_psys_tot_child(sim->scene, psys)) + distribute_particles(sim, PART_FROM_CHILD); } if(!only_children_changed) { free_keyed_keys(psys); - initialize_all_particles(ob, psys, psmd); + initialize_all_particles(sim); if(alloc) { - reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart); + reset_all_particles(sim, 0.0, cfra, oldtotpart); } } /* flag for possible explode modifiers after this system */ - psmd->flag |= eParticleSystemFlag_Pars; + sim->psmd->flag |= eParticleSystemFlag_Pars; } /* try to read from the cache */ if(usecache) { - int result = BKE_ptcache_read_cache(&pid, cfra, scene->r.frs_sec); + int result = BKE_ptcache_read_cache(&pid, cfra, sim->scene->r.frs_sec); if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) { - cached_step(scene, ob, psmd, psys, cfra); + cached_step(sim, cfra); psys->cfra=cfra; psys->recalc = 0; @@ -4334,7 +3775,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle pa->alive = PARS_ALIVE; } } - else if(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; @@ -4352,14 +3793,14 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle BKE_ptcache_write_cache(&pid, startframe); if(part->phystype==PART_PHYS_KEYED) - psys_count_keyed_targets(ob,psys); + psys_count_keyed_targets(sim); /* initialize vertex groups */ if(part->from!=PART_FROM_PARTICLE) { - vg_vel= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); - vg_tan= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); - vg_rot= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); - vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); + vg_vel= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_VEL); + vg_tan= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_TAN); + vg_rot= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_ROT); + vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); } /* set particles to be not calculated TODO: can't work with pointcache */ @@ -4367,7 +3808,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle BLI_srandom(psys->seed); LOOP_PARTICLES { - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -4383,7 +3824,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle for(dframe=-totframesback; dframe<=0; dframe++) { /* ok now we're all set so let's go */ - dynamics_step(scene, ob, psys, psmd, cfra+dframe, vg_vel, vg_tan, vg_rot, vg_size); + dynamics_step(sim, cfra+dframe); psys->cfra = cfra+dframe; } } @@ -4400,8 +3841,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* for keyed particles the path is allways known so it can be drawn */ if(part->phystype==PART_PHYS_KEYED) { - set_keyed_keys(scene, ob, psys); - psys_update_path_cache(scene, ob, psmd, psys,(int)cfra); + set_keyed_keys(sim); + psys_update_path_cache(sim,(int)cfra); } else if(psys->pathcache) psys_free_path_cache(psys, NULL); @@ -4431,30 +3872,33 @@ 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) { - ParticleSystemModifierData *psmd; + ParticleSimulationData sim = {scene, ob, psys, NULL, NULL}; float cfra; + /* drawdata is outdated after ANY change */ + if(psys->pdd) psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED; + if(!psys_check_enabled(ob, psys)) return; cfra= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); - psmd= psys_get_modifier(ob, psys); + sim.psmd= psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ - if(psmd->flag & eParticleSystemFlag_psys_updated) { - psmd->flag &= ~eParticleSystemFlag_psys_updated; + if(sim.psmd->flag & eParticleSystemFlag_psys_updated) { + sim.psmd->flag &= ~eParticleSystemFlag_psys_updated; /* make sure it really was updated to cfra */ if(psys->cfra == cfra) return; } - if(!psmd->dm) + if(!sim.psmd->dm) return; if(psys->recalc & PSYS_RECALC_TYPE) - psys_changed_type(ob, psys); + psys_changed_type(&sim); else if(psys->recalc & PSYS_RECALC_PHYS) - psys_changed_physics(ob, psys); + psys_changed_physics(&sim); /* (re-)create hair */ if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) { @@ -4468,15 +3912,15 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) for(i=0; i<=psys->part->hair_step; i++){ hcfra=100.0f*(float)i/(float)psys->part->hair_step; - system_step(scene, ob, psys, psmd, hcfra); - save_hair(scene, ob, psys, psmd, hcfra); + system_step(&sim, hcfra); + save_hair(&sim, hcfra); } psys->flag |= PSYS_HAIR_DONE; } /* the main particle system step */ - system_step(scene, ob, psys, psmd, cfra); + system_step(&sim, cfra); /* save matrix for duplicators */ Mat4Invert(psys->imat, ob->obmat); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index f351f8a4335..bffe4566f74 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -56,15 +56,23 @@ #include "BKE_smoke.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BLI_blenlib.h" /* both in intern */ #include "smoke_API.h" + +#ifdef WITH_LZO #include "minilzo.h" +#else +/* used for non-lzo cases */ +#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) +#endif +#ifdef WITH_LZMA #include "LzmaLib.h" - +#endif /* needed for directory lookup */ /* untitled blend's need getpid for a unique name */ @@ -79,6 +87,20 @@ static void ptcache_data_to(void **data, int type, int index, void *to); static void ptcache_data_from(void **data, int type, void *from); +#define PTCACHE_DATA_FROM(data, type, from) if(data[type]) { memcpy(data[type], from, ptcache_data_size[type]); } +#define PTCACHE_DATA_TO(data, type, index, to) if(data[type]) { memcpy(to, (char*)data[type] + (index ? index * ptcache_data_size[type] : 0), ptcache_data_size[type]); } + +int ptcache_data_size[] = { + sizeof(int), // BPHYS_DATA_INDEX + 3 * sizeof(float), // BPHYS_DATA_LOCATION: + 3 * sizeof(float), // BPHYS_DATA_VELOCITY: + 4 * sizeof(float), // BPHYS_DATA_ROTATION: + 3 * sizeof(float), // BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ + sizeof(float), // BPHYS_DATA_SIZE: + 3 * sizeof(float), // BPHYS_DATA_TIMES: + sizeof(BoidData) // case BPHYS_DATA_BOIDS: +}; + /* Common functions */ static int ptcache_read_basic_header(PTCacheFile *pf) { @@ -110,8 +132,8 @@ static int ptcache_write_softbody(int index, void *soft_v, void **data) SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; - ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec); return 1; } @@ -125,8 +147,8 @@ static void ptcache_read_softbody(int index, void *soft_v, void **data, float fr memcpy(bp->vec, data + 3, 3 * sizeof(float)); } else { - ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); } } static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -181,25 +203,25 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) return 0; } - ptcache_data_from(data, BPHYS_DATA_INDEX, &index); - ptcache_data_from(data, BPHYS_DATA_LOCATION, pa->state.co); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, pa->state.vel); - ptcache_data_from(data, BPHYS_DATA_ROTATION, pa->state.rot); - ptcache_data_from(data, BPHYS_DATA_AVELOCITY, pa->state.ave); - ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size); - ptcache_data_from(data, BPHYS_DATA_TIMES, times); + PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); + PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); + PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); + PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); + PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); if(boid) - ptcache_data_from(data, BPHYS_DATA_BOIDS, &boid->data); + PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); return 1; } void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) { - ptcache_data_to(data, BPHYS_DATA_LOCATION, index, key->co); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, index, key->vel); - ptcache_data_to(data, BPHYS_DATA_ROTATION, index, key->rot); - ptcache_data_to(data, BPHYS_DATA_AVELOCITY, index, key->ave); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel); + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot); + PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave); key->time = time; } static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) @@ -220,18 +242,18 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); if(data[BPHYS_DATA_SIZE]) - ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size); + PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); if(data[BPHYS_DATA_TIMES]) { float times[3]; - ptcache_data_to(data, BPHYS_DATA_TIMES, 0, ×); + PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); pa->time = times[0]; pa->dietime = times[1]; pa->lifetime = times[2]; } if(boid) - ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &boid->data); + PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); /* determine velocity from previous location */ if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { @@ -270,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); @@ -307,6 +332,132 @@ static int ptcache_totwrite_particle(void *psys_v) return totwrite; } +//static int ptcache_write_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles; +// BoidParticle *boid = NULL; +// float times[3]; +// int i = 0; +// +// if(!pf && !pm) +// return 0; +// +// for(i=0; i<psys->totpart; i++, pa++) { +// +// if(data[BPHYS_DATA_INDEX]) { +// int step = psys->pointcache->step; +// /* No need to store unborn or died particles */ +// if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time) +// continue; +// } +// +// times[0] = pa->time; +// times[1] = pa->dietime; +// times[2] = pa->lifetime; +// +// PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); +// +// boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; +// if(boid) +// PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); +// +// if(pf && !ptcache_file_write_data(pf)) +// return 0; +// +// if(pm) +// BKE_ptcache_mem_incr_pointers(pm); +// } +// +// return 1; +//} +//static void ptcache_read_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles + index; +// BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; +// +// if(cfra > pa->state.time) +// memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey)); +// +// if(old_data){ +// /* old format cache */ +// memcpy(&pa->state, old_data, sizeof(ParticleKey)); +// return; +// } +// +// BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); +// +// if(data[BPHYS_DATA_SIZE]) +// PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); +// +// if(data[BPHYS_DATA_TIMES]) { +// float times[3]; +// PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); +// pa->time = times[0]; +// pa->dietime = times[1]; +// pa->lifetime = times[2]; +// } +// +// if(boid) +// PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); +// +// /* determine velocity from previous location */ +// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { +// if(cfra > pa->prev_state.time) { +// VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co); +// VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); +// } +// else { +// VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co); +// VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); +// } +// } +// +// /* determine rotation from velocity */ +// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { +// vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot); +// } +//} +//static void ptcache_interpolate_particle_stream(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles + index; +// ParticleKey keys[4]; +// float dfra; +// +// cfra = MIN2(cfra, pa->dietime); +// cfra1 = MIN2(cfra1, pa->dietime); +// cfra2 = MIN2(cfra2, pa->dietime); +// +// if(cfra1 == cfra2) +// return; +// +// memcpy(keys+1, &pa->state, sizeof(ParticleKey)); +// if(old_data) +// memcpy(keys+2, old_data, sizeof(ParticleKey)); +// else +// BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); +// +// dfra = cfra2 - cfra1; +// +// VecMulf(keys[1].vel, dfra / frs_sec); +// VecMulf(keys[2].vel, dfra / frs_sec); +// +// psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); +// QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); +// +// VecMulf(pa->state.vel, frs_sec / dfra); +// +// pa->state.time = cfra; +//} +// /* Cloth functions */ static int ptcache_write_cloth(int index, void *cloth_v, void **data) { @@ -314,9 +465,9 @@ static int ptcache_write_cloth(int index, void *cloth_v, void **data) Cloth *cloth= clmd->clothObject; ClothVertex *vert = cloth->verts + index; - ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v); - ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v); + PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst); return 1; } @@ -332,9 +483,9 @@ static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_ memcpy(vert->v, data + 6, 3 * sizeof(float)); } else { - ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v); - ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v); + PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); } } static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -484,20 +635,25 @@ static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) { int r = 0; - unsigned char compressed; - LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); - unsigned int out_len = LZO_OUT_LEN(in_len); + unsigned char compressed = 0; + unsigned int out_len= 0; unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); size_t sizeOfIt = 5; +#ifdef WITH_LZO + out_len= LZO_OUT_LEN(in_len); if(mode == 1) { + LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); + r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); if (!(r == LZO_E_OK) || (out_len >= in_len)) compressed = 0; else compressed = 1; } - else if(mode == 2) { +#endif +#ifdef WITH_LZMA + if(mode == 2) { r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1.... props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); @@ -507,7 +663,8 @@ static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned i else compressed = 2; } - +#endif + ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); if(compressed) { ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int)); @@ -570,9 +727,9 @@ static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) SmokeDomainSettings *sds = smd->domain; if(sds->wt) { - unsigned int res_big_array[3]; - unsigned int res_big; - unsigned int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big_array[3]; + int res_big; + int res = sds->res[0]*sds->res[1]*sds->res[2]; float *dens, *densold, *tcu, *tcv, *tcw; unsigned int in_len = sizeof(float)*(unsigned int)res; unsigned int in_len_big; @@ -621,16 +778,19 @@ static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigne in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); +#ifdef WITH_LZO if(compressed == 1) r = lzo1x_decompress(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); - else if(compressed == 2) +#endif +#ifdef WITH_LZMA + if(compressed == 2) { size_t leni = in_len, leno = out_len; ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int)); ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); } - +#endif MEM_freeN(in); } else { @@ -678,8 +838,8 @@ static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v) SmokeDomainSettings *sds = smd->domain; if(sds->fluid) { - unsigned int res = sds->res[0]*sds->res[1]*sds->res[2]; - unsigned int res_big, res_big_array[3]; + int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big, res_big_array[3]; float *dens, *densold, *tcu, *tcv, *tcw; unsigned int out_len = sizeof(float)*(unsigned int)res; unsigned int out_len_big; @@ -987,7 +1147,7 @@ static int ptcache_file_read_data(PTCacheFile *pf) int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i))) + if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } @@ -998,7 +1158,7 @@ static int ptcache_file_write_data(PTCacheFile *pf) int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i))) + if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } @@ -1045,38 +1205,7 @@ static int ptcache_file_write_header_begin(PTCacheFile *pf) /* Data pointer handling */ int BKE_ptcache_data_size(int data_type) { - switch(data_type) { - case BPHYS_DATA_INDEX: - return sizeof(int); - case BPHYS_DATA_LOCATION: - case BPHYS_DATA_VELOCITY: - case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ - case BPHYS_DATA_TIMES: - return 3 * sizeof(float); - case BPHYS_DATA_ROTATION: - return 4 * sizeof(float); - case BPHYS_DATA_SIZE: - return sizeof(float); - case BPHYS_DATA_BOIDS: - return sizeof(BoidData); - default: - return 0; - } -} -static void ptcache_data_to(void **data, int type, int index, void *to) -{ - if(data[type]) { - if(index) - memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type)); - else - memcpy(to, data[type], BKE_ptcache_data_size(type)); - } -} - -static void ptcache_data_from(void **data, int type, void *from) -{ - if(data[type]) - memcpy(data[type], from, BKE_ptcache_data_size(type)); + return ptcache_data_size[data_type]; } static void ptcache_file_init_pointers(PTCacheFile *pf) @@ -1108,7 +1237,7 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) for(i=0; i<BPHYS_TOT_DATA; i++) { if(pm->cur[i]) - pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i); + pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; } } static void ptcache_alloc_data(PTCacheMem *pm) @@ -1119,7 +1248,7 @@ static void ptcache_alloc_data(PTCacheMem *pm) for(i=0; i<BPHYS_TOT_DATA; i++) { if(data_types & (1<<i)) - pm->data[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data"); + pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data"); } } static void ptcache_free_data(void *data[]) @@ -1136,7 +1265,7 @@ static void ptcache_copy_data(void *from[], void *to[]) int i; for(i=0; i<BPHYS_TOT_DATA; i++) { if(from[i]) - memcpy(to[i], from[i], BKE_ptcache_data_size(i)); + memcpy(to[i], from[i], ptcache_data_size[i]); } } @@ -1898,6 +2027,9 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } } + if (ob->type == OB_ARMATURE) + BIK_clear_cache(ob->pose); + return reset; } @@ -2119,6 +2251,26 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if((cache->flag & PTCACHE_BAKED)==0) { if(pid->type==PTCACHE_TYPE_PARTICLES) psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); + else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) { + /* get all pids from the object and search for smoke low res */ + ListBase pidlist2; + PTCacheID *pid2; + BKE_ptcache_ids_from_object(&pidlist2, pid->ob); + for(pid2=pidlist2.first; pid2; pid2=pid2->next) { + if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) + { + if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) { + if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) + BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0); + if(bake) { + pid2->cache->flag |= PTCACHE_BAKING; + pid2->cache->flag &= ~PTCACHE_BAKED; + } + } + } + } + BLI_freelistN(&pidlist2); + } if(bake || cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 391adfb762a..e524359d2bc 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -230,7 +230,7 @@ char *BKE_reports_string(ReportList *reports, ReportType level) DynStr *ds; char *cstring; - if(!reports) + if(!reports || !reports->list.first) return NULL; ds= BLI_dynstr_new(); diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index de2118af202..5cd554725ff 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -128,6 +128,9 @@ void init_sensor(bSensor *sens) case SENS_PROPERTY: sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens"); break; + case SENS_ARMATURE: + sens->data= MEM_callocN(sizeof(bArmatureSensor), "armsens"); + break; case SENS_ACTUATOR: sens->data= MEM_callocN(sizeof(bActuatorSensor), "actsens"); break; @@ -455,6 +458,9 @@ void init_actuator(bActuator *act) case ACT_STATE: act->data = MEM_callocN(sizeof( bStateActuator ), "state act"); break; + case ACT_ARMATURE: + act->data = MEM_callocN(sizeof( bArmatureActuator ), "armature act"); + break; default: ; /* this is very severe... I cannot make any memory for this */ /* logic brick... */ @@ -596,6 +602,8 @@ void sca_remove_ob_poin(Object *obt, Object *ob) bEditObjectActuator *eoa; bPropertyActuator *pa; bMessageActuator *ma; + bParentActuator *para; + bArmatureActuator *aa; sens= obt->sensors.first; while(sens) { @@ -634,7 +642,15 @@ void sca_remove_ob_poin(Object *obt, Object *ob) ma= act->data; if(ma->toObject==ob) ma->toObject= NULL; break; - + case ACT_PARENT: + para = act->data; + if (para->ob==ob) para->ob = NULL; + break; + case ACT_ARMATURE: + aa = act->data; + if (aa->target == ob) aa->target = NULL; + if (aa->subtarget == ob) aa->subtarget = NULL; + break; } act= act->next; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6f9ed3e0978..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; @@ -419,7 +423,11 @@ Scene *add_scene(char *name) pset->brush[PE_BRUSH_CUT].strength= 100; sce->jumpframe = 10; - sce->r.audio.mixrate = 44100; + sce->r.ffcodecdata.audio_mixrate = 44100; + + sce->audio.distance_model = 2.0; + sce->audio.doppler_factor = 1.0; + sce->audio.speed_of_sound = 343.3; strcpy(sce->r.backbuf, "//backbuf"); strcpy(sce->r.pic, U.renderdir); @@ -774,11 +782,11 @@ static void scene_update(Scene *sce, unsigned int lay) DAG_scene_update_flags(sce, lay); // only stuff that moves or needs display still /* All 'standard' (i.e. without any dependencies) animation is handled here, - * with an 'local' to 'macro' order of evaluation. This should ensure that - * settings stored nestled within a hierarchy (i.e. settings in a Texture block - * can be overridden by settings from Scene, which owns the Texture through a hierarchy - * such as Scene->World->MTex/Texture) can still get correctly overridden. - */ + * with an 'local' to 'macro' order of evaluation. This should ensure that + * settings stored nestled within a hierarchy (i.e. settings in a Texture block + * can be overridden by settings from Scene, which owns the Texture through a hierarchy + * such as Scene->World->MTex/Texture) can still get correctly overridden. + */ BKE_animsys_evaluate_all_animation(G.main, ctime); for(base= sce->base.first; base; base= base->next) { diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index cc740d7fb3d..661d0da1550 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -33,8 +33,10 @@ #include "MEM_guardedalloc.h" +#include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "DNA_view3d_types.h" #include "BLI_blenlib.h" @@ -321,4 +323,23 @@ void free_screen(bScreen *sc) BLI_freelistN(&sc->areabase); } +/* for depsgraph */ +unsigned int BKE_screen_visible_layers(bScreen *screen) +{ + ScrArea *sa; + unsigned int layer= 0; + + if(!screen) + return layer; + + /* get all used view3d layers */ + for(sa= screen->areabase.first; sa; sa= sa->next) + if(sa->spacetype==SPACE_VIEW3D) + layer |= ((View3D *)sa->spacedata.first)->lay; + + if(!layer) + return screen->scene->lay; + + return layer; +} diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index c6b714c3125..b80df60e726 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -127,7 +127,7 @@ void new_tstripdata(Sequence *seq) /* free */ -void free_proxy_seq(Sequence *seq) +static void free_proxy_seq(Sequence *seq) { if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { IMB_free_anim(seq->strip->proxy->anim); @@ -682,7 +682,7 @@ void clear_scene_in_allseqs(Scene *sce) } } -char *give_seqname_by_type(int type) +static char *give_seqname_by_type(int type) { switch(type) { case SEQ_META: return "Meta"; @@ -949,7 +949,7 @@ static TStripElem* alloc_tstripdata(int len, const char * name) return se; } -TStripElem *give_tstripelem(Sequence *seq, int cfra) +static TStripElem *give_tstripelem(Sequence *seq, int cfra) { TStripElem *se; int nr; @@ -1297,7 +1297,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re se->ibuf = 0; } -void seq_proxy_rebuild(Scene *scene, Sequence * seq) +static void seq_proxy_rebuild(Scene *scene, Sequence * seq) { int cfra; float rsize = seq->strip->proxy->size; @@ -2067,7 +2067,7 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int if(rendering) BLI_strncpy(sce->id.name+2, scenename, 64); - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); if(rres.rectf) { se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); @@ -2080,6 +2080,8 @@ static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); } + + RE_ReleaseResultImage(re); BIF_end_render_callbacks(); @@ -2623,7 +2625,7 @@ ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown } /* check used when we need to change seq->blend_mode but not to effect or audio strips */ -int seq_can_blend(Sequence *seq) +static int seq_can_blend(Sequence *seq) { if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { return 1; @@ -2749,7 +2751,7 @@ static void *seq_prefetch_thread(void * This_) return 0; } -void seq_start_threads(Scene *scene) +static void seq_start_threads(Scene *scene) { int i; @@ -2782,7 +2784,7 @@ void seq_start_threads(Scene *scene) BLI_init_threads(0, 0, 0); } -void seq_stop_threads() +static void seq_stop_threads() { PrefetchThread *tslot; PrefetchQueueElem *e; @@ -2850,7 +2852,7 @@ void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, pthread_mutex_unlock(&wakeup_lock); } -void seq_wait_for_prefetch_ready() +static void seq_wait_for_prefetch_ready() { PrefetchThread *tslot; @@ -2984,7 +2986,7 @@ static void free_anim_seq(Sequence *seq) } } -void free_imbuf_seq_except(Scene *scene, int cfra) +static void free_imbuf_seq_except(Scene *scene, int cfra) { Editing *ed= seq_give_editing(scene, FALSE); Sequence *seq; @@ -3178,7 +3180,7 @@ void free_imbuf_seq() } #endif -void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) +static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) { /* force update of all sequences with this ipo, on ipo changes */ Editing *ed= seq_give_editing(scene, FALSE); diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index af79fd74ae8..4f7a8cda81b 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -167,6 +167,8 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive // calc other res with max_res provided VECSUB(size, max, min); + // printf("size: %f, %f, %f\n", size[0], size[1], size[2]); + // prevent crash when initializing a plane as domain if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON)) return 0; @@ -210,6 +212,8 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive } } + // printf("smd->domain->dx: %f\n", smd->domain->dx); + // TODO: put in failsafe if res<=0 - dg // printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]); @@ -224,8 +228,8 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive smd->domain->res_wt[1] = smd->domain->res[1] * (smd->domain->amplify + 1); smd->domain->res_wt[2] = smd->domain->res[2] * (smd->domain->amplify + 1); smd->domain->dx_wt = smd->domain->dx / (smd->domain->amplify + 1); - printf("smd->domain->amplify: %d\n", smd->domain->amplify); - printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n"); + // printf("smd->domain->amplify: %d\n", smd->domain->amplify); + // printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n"); } if(!smd->domain->shadow) @@ -236,7 +240,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive if(smd->domain->wt) { smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength)); - printf("smoke_initWaveletBlenderRNA\n"); + // printf("smoke_initWaveletBlenderRNA\n"); } return 1; } @@ -522,7 +526,7 @@ void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int } } -void smokeModifier_freeDomain(SmokeModifierData *smd) +static void smokeModifier_freeDomain(SmokeModifierData *smd) { if(smd->domain) { @@ -546,7 +550,7 @@ void smokeModifier_freeDomain(SmokeModifierData *smd) } } -void smokeModifier_freeFlow(SmokeModifierData *smd) +static void smokeModifier_freeFlow(SmokeModifierData *smd) { if(smd->flow) { @@ -563,7 +567,7 @@ void smokeModifier_freeFlow(SmokeModifierData *smd) } } -void smokeModifier_freeCollision(SmokeModifierData *smd) +static void smokeModifier_freeCollision(SmokeModifierData *smd) { if(smd->coll) { @@ -595,11 +599,6 @@ void smokeModifier_reset_turbulence(struct SmokeModifierData *smd) smoke_turbulence_free(smd->domain->wt); smd->domain->wt = NULL; } - - smd->domain->point_cache[1]->flag &= ~PTCACHE_SIMULATION_VALID; - smd->domain->point_cache[1]->flag |= PTCACHE_OUTDATED; - smd->domain->point_cache[1]->simframe= 0; - smd->domain->point_cache[1]->last_exact= 0; } void smokeModifier_reset(struct SmokeModifierData *smd) @@ -617,11 +616,9 @@ void smokeModifier_reset(struct SmokeModifierData *smd) smoke_free(smd->domain->fluid); smd->domain->fluid = NULL; } - - smd->domain->point_cache[0]->flag &= ~PTCACHE_SIMULATION_VALID; + smd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED; - smd->domain->point_cache[0]->simframe= 0; - smd->domain->point_cache[0]->last_exact= 0; + smd->domain->point_cache[1]->flag |= PTCACHE_OUTDATED; smokeModifier_reset_turbulence(smd); @@ -744,7 +741,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd) } // forward decleration -void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct); +static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct); static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct); static int get_lamp(Scene *scene, float *light) { @@ -835,13 +832,12 @@ 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); // Mat4MulVecfl (ob->imat, pos); - // 1. get corresponding cell + // 1. get corresponding cell get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, pa->state.co, cell, 0); // check if cell is valid (in the domain boundary) for(i = 0; i < 3; i++) @@ -1102,75 +1098,52 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } else if(smd->type & MOD_SMOKE_TYPE_DOMAIN) { + SmokeDomainSettings *sds = smd->domain; + float light[3]; PointCache *cache = NULL; PTCacheID pid; PointCache *cache_wt = NULL; PTCacheID pid_wt; + int startframe, endframe, framenr; float timescale; int cache_result = 0, cache_result_wt = 0; - int startframe, endframe, framenr, badloading = 0; - SmokeDomainSettings *sds = smd->domain; - float light[3]; framenr = scene->r.cfra; - cache = sds->point_cache[0]; + // printf("time: %d\n", scene->r.cfra); + + if(framenr == smd->time) + return; + cache = sds->point_cache[0]; BKE_ptcache_id_from_smoke(&pid, ob, smd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); cache_wt = sds->point_cache[1]; BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd); - /* handle continuous simulation with the play button */ - if(BKE_ptcache_get_continue_physics()) + if(!smd->domain->fluid) { - // TODO - return; + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); } if(framenr < startframe) - { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - - cache_wt->flag &= ~PTCACHE_SIMULATION_VALID; - cache_wt->simframe= 0; - cache_wt->last_exact= 0; - - // we got back in time, reset smoke in this case (TODO: use cache later) - // smd->time = scene->r.cfra; - // smokeModifier_reset(smd); - return; - } - else if(framenr > endframe) - { - framenr = endframe; - - // we load last valid frame here - // and don't update the smd->time variable later - badloading = 1; - } - if(!(cache->flag & PTCACHE_SIMULATION_VALID)) - { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - } - if(sds->wt && !(cache_wt->flag & PTCACHE_SIMULATION_VALID)) - { - BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); - } + if(framenr > endframe) + return; - if(smd->time == -1 && framenr!= startframe) + if(!smd->domain->fluid && (framenr != startframe)) return; + // printf("startframe: %d, framenr: %d\n", startframe, framenr); + if(!smokeModifier_init(smd, ob, scene, dm)) + { + printf("bad smokeModifier_init\n"); return; - - if(!smd->domain->fluid) - return; + } /* try to read from cache */ cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); @@ -1178,138 +1151,58 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM if(cache_result == PTCACHE_READ_EXACT) { - SmokeDomainSettings *sds = smd->domain; - cache->flag |= PTCACHE_SIMULATION_VALID; cache->simframe= framenr; - sds->v3dnum = framenr; - - if(!badloading) - smd->time = scene->r.cfra; - // check for wt cache if(sds->wt) { cache_result_wt = BKE_ptcache_read_cache(&pid_wt, (float)framenr, scene->r.frs_sec); - // printf("cache_result_wt: %d\n", cache_result_wt); - - // error handling + if(cache_result_wt == PTCACHE_READ_EXACT) { cache_wt->flag |= PTCACHE_SIMULATION_VALID; cache_wt->simframe= framenr; } - else if(cache_result_wt==PTCACHE_READ_OLD) - { - BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_FREE); - cache_wt->flag |= PTCACHE_SIMULATION_VALID; - } - else if(ob->id.lib || (cache_wt->flag & PTCACHE_BAKED)) - { - // if baked and nothing in cache, do nothing - cache_wt->flag &= ~PTCACHE_SIMULATION_VALID; - cache_wt->simframe= 0; - cache_wt->last_exact= 0; - } } - - // printf("PTCACHE_READ_EXACT\n"); return; } - else if(cache_result==PTCACHE_READ_OLD) - { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE); - cache->flag |= PTCACHE_SIMULATION_VALID; - - BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_FREE); - cache_wt->flag |= PTCACHE_SIMULATION_VALID; - } - else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) - { - // if baked and nothing in cache, do nothing - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - - cache_wt->flag &= ~PTCACHE_SIMULATION_VALID; - cache_wt->simframe= 0; - cache_wt->last_exact= 0; - - // printf("PTCACHE_BAKED\n"); - return; - } - /* - else if((cache_result==0) && ((startframe!=framenr) && !(cache->flag & PTCACHE_SIMULATION_VALID || (framenr == smd->time)))) - { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - - return; - }*/ - - // printf("framenr: %d, time: %f\n", framenr, smd->time); - /* do simulation */ - - // low res - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= framenr; - - if(sds->wt) - { - cache_wt->flag |= PTCACHE_SIMULATION_VALID; - cache_wt->simframe= framenr; - } - - tstart(); - - if(sds->flags & MOD_SMOKE_DISSOLVE) - { - smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); - } + tstart(); smoke_calc_domain(scene, ob, smd); // set new time smd->time = scene->r.cfra; - // frame 1 is start, don't simulate anything - if(smd->time == 1) - { - // set new time - smd->time = scene->r.cfra; - - BKE_ptcache_write_cache(&pid, framenr); - if(sds->wt) - BKE_ptcache_write_cache(&pid_wt, framenr); - - if(get_lamp(scene, light)) - smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); + /* do simulation */ - // printf("smd->time: %f\n", smd->time); - return; - } + // low res + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; // simulate the actual smoke (c++ code in intern/smoke) - smoke_step(sds->fluid, smd->time); + // DG: interesting commenting this line + deactivating loading of noise files + if(framenr!=startframe) + smoke_step(sds->fluid, smd->time); + + // create shadows before writing cache so we get nice shadows for sstartframe, too + if(get_lamp(scene, light)) + smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); + BKE_ptcache_write_cache(&pid, framenr); if(sds->wt) { + if(framenr!=startframe) + smoke_turbulence_step(sds->wt, sds->fluid); - if(sds->flags & MOD_SMOKE_DISSOLVE) - smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); - - smoke_turbulence_step(sds->wt, sds->fluid); + cache_wt->flag |= PTCACHE_SIMULATION_VALID; + cache_wt->simframe= framenr; BKE_ptcache_write_cache(&pid_wt, framenr); } - if(get_lamp(scene, light)) - smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); - tend(); - // printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); + printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); } } @@ -1449,7 +1342,7 @@ static void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int } } -void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct) +static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct) { int x, y, z; float bv[6]; 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/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 2d5d8dad7a8..6ac9b020f21 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -340,7 +340,7 @@ void sound_update_playing(struct bContext *C) for(handle = scene->sound_handles.first; handle; handle = handle->next) { - if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute) + if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute || (scene->audio.flag & AUDIO_MUTE)) { if(handle->state == AUD_STATUS_PLAYING) { @@ -421,7 +421,7 @@ void sound_scrub(struct bContext *C) int cfra = CFRA; float fps = FPS; - if(scene->r.audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) + if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) { AUD_lock(); @@ -443,7 +443,7 @@ void sound_scrub(struct bContext *C) } } -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end) +AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume) { AUD_Device* mixdown = AUD_openReadDevice(specs); SoundHandle *handle; @@ -453,6 +453,8 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int e end++; + AUD_setDeviceVolume(mixdown, volume); + for(handle = scene->sound_handles.first; handle; handle = handle->next) { if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->handle) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index dac426de4eb..8bf0f6b8bdf 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -130,8 +130,10 @@ undo position static void txt_pop_first(Text *text); static void txt_pop_last(Text *text); static void txt_undo_add_op(Text *text, int op); -static void txt_undo_add_block(Text *text, int op, char *buf); +static void txt_undo_add_block(Text *text, int op, const char *buf); static void txt_delete_line(Text *text, TextLine *line); +static void txt_delete_sel (Text *text); +static void txt_make_dirty (Text *text); /***/ @@ -537,6 +539,30 @@ void unlink_text(Main *bmain, Text *text) text->id.us= 0; } +void clear_text(Text *text) /* called directly from rna */ +{ + int oldstate; + + oldstate = txt_get_undostate( ); + txt_set_undostate( 1 ); + txt_sel_all( text ); + txt_delete_sel(text); + txt_set_undostate( oldstate ); + + txt_make_dirty(text); +} + +void write_text(Text *text, char *str) /* called directly from rna */ +{ + int oldstate; + + oldstate = txt_get_undostate( ); + txt_insert_buf( text, str ); + txt_move_eof( text, 0 ); + txt_set_undostate( oldstate ); + + txt_make_dirty(text); +} /*****************************/ /* Editing utility functions */ @@ -570,17 +596,15 @@ static TextLine *txt_new_line(char *str) return tmp; } -static TextLine *txt_new_linen(char *str, int n) +static TextLine *txt_new_linen(const char *str, int n) { TextLine *tmp; - if(!str) str= ""; - tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(n+1, "textline_string"); tmp->format= NULL; - BLI_strncpy(tmp->line, str, n+1); + BLI_strncpy(tmp->line, (str)? str: "", n+1); tmp->len= strlen(tmp->line); tmp->next= tmp->prev= NULL; @@ -1315,7 +1339,7 @@ char *txt_sel_to_buf (Text *text) return buf; } -void txt_insert_buf(Text *text, char *in_buffer) +void txt_insert_buf(Text *text, const char *in_buffer) { int i=0, l=0, j, u, len; TextLine *add; @@ -1544,7 +1568,7 @@ static void txt_undo_add_op(Text *text, int op) text->undo_buf[text->undo_pos+1]= 0; } -static void txt_undo_add_block(Text *text, int op, char *buf) +static void txt_undo_add_block(Text *text, int op, const char *buf) { int length; @@ -2808,3 +2832,60 @@ TextMarker *txt_next_marker(Text *text, TextMarker *marker) { } return NULL; /* Only if marker==NULL */ } + + +/*******************************/ +/* Character utility functions */ +/*******************************/ + +int text_check_bracket(char ch) +{ + int a; + char opens[] = "([{"; + char close[] = ")]}"; + + for(a=0; a<(sizeof(opens)-1); a++) { + if(ch==opens[a]) + return a+1; + else if(ch==close[a]) + return -(a+1); + } + return 0; +} + +int text_check_delim(char ch) +{ + int a; + char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,"; + + for(a=0; a<(sizeof(delims)-1); a++) { + if(ch==delims[a]) + return 1; + } + return 0; +} + +int text_check_digit(char ch) +{ + if(ch < '0') return 0; + if(ch <= '9') return 1; + return 0; +} + +int text_check_identifier(char ch) +{ + if(ch < '0') return 0; + if(ch <= '9') return 1; + if(ch < 'A') return 0; + if(ch <= 'Z' || ch == '_') return 1; + if(ch < 'a') return 0; + if(ch <= 'z') return 1; + return 0; +} + +int text_check_whitespace(char ch) +{ + if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') + return 1; + return 0; +} diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index d7616ec8a9a..3b8ae9a6c7f 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -559,6 +559,36 @@ void default_mtex(MTex *mtex) mtex->norfac= 1.0; mtex->varfac= 1.0; mtex->dispfac=0.2; + mtex->colspecfac= 1.0f; + mtex->mirrfac= 1.0f; + mtex->alphafac= 1.0f; + mtex->difffac= 1.0f; + mtex->specfac= 1.0f; + mtex->emitfac= 1.0f; + mtex->hardfac= 1.0f; + mtex->raymirrfac= 1.0f; + mtex->translfac= 1.0f; + mtex->ambfac= 1.0f; + mtex->colemitfac= 1.0f; + mtex->colreflfac= 1.0f; + mtex->coltransfac= 1.0f; + mtex->densfac= 1.0f; + mtex->scatterfac= 1.0f; + mtex->reflfac= 1.0f; + mtex->shadowfac= 1.0f; + mtex->zenupfac= 1.0f; + mtex->zendownfac= 1.0f; + mtex->blendfac= 1.0f; + mtex->timefac= 1.0f; + mtex->lengthfac= 1.0f; + mtex->clumpfac= 1.0f; + mtex->kinkfac= 1.0f; + mtex->roughfac= 1.0f; + mtex->padensfac= 1.0f; + mtex->lifefac= 1.0f; + mtex->sizefac= 1.0f; + mtex->ivelfac= 1.0f; + mtex->pvelfac= 1.0f; mtex->normapspace= MTEX_NSPACE_TANGENT; } @@ -984,6 +1014,7 @@ struct VoxelData *BKE_add_voxeldata(void) vd->interp_type= TEX_VD_LINEAR; vd->file_format= TEX_VD_SMOKE; vd->int_multiplier = 1.0; + vd->extend = TEX_CLIP; vd->object = NULL; return vd; diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index f8e3b3c5ad2..1f72c894cc8 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -75,7 +75,7 @@ static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDum /* Lengths */ static struct bUnitDef buMetricLenDef[] = { {"kilometer", "kilometers", "km", NULL, "Kilometers", 1000.0, 0.0, B_UNIT_DEF_NONE}, - {"hectometer", "hectometers", "hm", NULL, "10 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS}, + {"hectometer", "hectometers", "hm", NULL, "100 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS}, {"dekameter", "dekameters", "dkm",NULL, "10 Meters", 10.0, 0.0, B_UNIT_DEF_SUPPRESS}, {"meter", "meters", "m", NULL, "Meters", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", 0.1, 0.0, B_UNIT_DEF_SUPPRESS}, @@ -485,7 +485,7 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre if(unit==NULL) unit= unit_default(usys); - /* add the unit prefic and re-run, use brackets incase there was an expression given */ + /* add the unit prefix and re-run, use brackets incase there was an expression given */ if(snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) { strncpy(str, str_tmp, len_max); return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type); diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index e7164dc4794..1953058fddf 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -148,7 +148,7 @@ static int write_audio_frame(void) #else pkt.pts = c->coded_frame->pts; #endif - fprintf(stderr, "Audio Frame PTS: %lld\n", pkt.pts); + fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts); pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; @@ -265,7 +265,7 @@ static void write_video_frame(RenderData *rd, AVFrame* frame) #else packet.pts = c->coded_frame->pts; #endif - fprintf(stderr, "Video Frame PTS: %lld\n", packet.pts); + fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); } else { fprintf(stderr, "Video Frame PTS: not set\n"); } @@ -559,7 +559,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->codec_id = codec_id; c->codec_type = CODEC_TYPE_AUDIO; - c->sample_rate = rd->audio.mixrate; + c->sample_rate = rd->ffcodecdata.audio_mixrate; c->bit_rate = ffmpeg_audio_bitrate*1000; c->channels = 2; codec = avcodec_find_encoder(c->codec_id); @@ -613,7 +613,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } /* essential functions -- start, append, end */ -void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) +static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) { /* Handle to the output file */ AVFormatContext* of; @@ -734,7 +734,7 @@ void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) if (ffmpeg_type == FFMPEG_DV) { fmt->audio_codec = CODEC_ID_PCM_S16LE; - if (ffmpeg_multiplex_audio && rd->audio.mixrate != 48000) { + if (ffmpeg_multiplex_audio && rd->ffcodecdata.audio_mixrate != 48000) { G.afbreek = 1; //XXX error("FFMPEG only supports 48khz / stereo " // "audio for DV!"); @@ -831,7 +831,6 @@ static void makeffmpegstring(RenderData* rd, char* string) { } } - void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) { ffmpeg_autosplit_count = 0; @@ -844,8 +843,8 @@ void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) AUD_Specs specs; specs.channels = c->channels; specs.format = AUD_FORMAT_S16; - specs.rate = rd->audio.mixrate; - audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra); + specs.rate = rd->ffcodecdata.audio_mixrate; + audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra, rd->ffcodecdata.audio_volume); } } |