Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Steiblys <imbusy@imbusy.org>2009-10-02 02:29:15 +0400
committerLukas Steiblys <imbusy@imbusy.org>2009-10-02 02:29:15 +0400
commit0677398a649b6b8c293df3ce3c6668f0a3be3bc8 (patch)
tree9d510a5bd23559bf4fae670ed04d7e5d6c12578c /source/blender/blenkernel
parent59248e9f62006ba05e3098e4d213f3dcb23fe711 (diff)
parentbc942eceacb638735dc4f4f68252c4c207147a70 (diff)
merge from 23153 to 23595soc-2009-imbusy
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_action.h53
-rw-r--r--source/blender/blenkernel/BKE_anim.h9
-rw-r--r--source/blender/blenkernel/BKE_armature.h7
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_boids.h4
-rw-r--r--source/blender/blenkernel/BKE_brush.h4
-rw-r--r--source/blender/blenkernel/BKE_collision.h11
-rw-r--r--source/blender/blenkernel/BKE_constraint.h6
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h16
-rw-r--r--source/blender/blenkernel/BKE_effect.h109
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h7
-rw-r--r--source/blender/blenkernel/BKE_image.h11
-rw-r--r--source/blender/blenkernel/BKE_library.h1
-rw-r--r--source/blender/blenkernel/BKE_node.h7
-rw-r--r--source/blender/blenkernel/BKE_particle.h173
-rw-r--r--source/blender/blenkernel/BKE_screen.h6
-rw-r--r--source/blender/blenkernel/BKE_sound.h2
-rw-r--r--source/blender/blenkernel/BKE_text.h12
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h49
-rw-r--r--source/blender/blenkernel/CMakeLists.txt14
-rw-r--r--source/blender/blenkernel/SConscript14
-rw-r--r--source/blender/blenkernel/intern/Makefile19
-rw-r--r--source/blender/blenkernel/intern/action.c413
-rw-r--r--source/blender/blenkernel/intern/anim.c31
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c145
-rw-r--r--source/blender/blenkernel/intern/armature.c547
-rw-r--r--source/blender/blenkernel/intern/boids.c249
-rw-r--r--source/blender/blenkernel/intern/brush.c117
-rw-r--r--source/blender/blenkernel/intern/cloth.c98
-rw-r--r--source/blender/blenkernel/intern/collision.c138
-rw-r--r--source/blender/blenkernel/intern/constraint.c27
-rw-r--r--source/blender/blenkernel/intern/curve.c10
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c147
-rw-r--r--source/blender/blenkernel/intern/displist.c2
-rw-r--r--source/blender/blenkernel/intern/effect.c858
-rw-r--r--source/blender/blenkernel/intern/fcurve.c87
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c1
-rw-r--r--source/blender/blenkernel/intern/font.c2
-rw-r--r--source/blender/blenkernel/intern/image.c178
-rw-r--r--source/blender/blenkernel/intern/implicit.c48
-rw-r--r--source/blender/blenkernel/intern/ipo.c90
-rw-r--r--source/blender/blenkernel/intern/lattice.c144
-rw-r--r--source/blender/blenkernel/intern/library.c53
-rw-r--r--source/blender/blenkernel/intern/material.c12
-rw-r--r--source/blender/blenkernel/intern/mesh.c3
-rw-r--r--source/blender/blenkernel/intern/modifier.c83
-rw-r--r--source/blender/blenkernel/intern/multires.c4
-rw-r--r--source/blender/blenkernel/intern/nla.c5
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/object.c135
-rw-r--r--source/blender/blenkernel/intern/packedFile.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c27
-rw-r--r--source/blender/blenkernel/intern/particle.c835
-rw-r--r--source/blender/blenkernel/intern/particle_system.c1730
-rw-r--r--source/blender/blenkernel/intern/pointcache.c302
-rw-r--r--source/blender/blenkernel/intern/report.c2
-rw-r--r--source/blender/blenkernel/intern/sca.c18
-rw-r--r--source/blender/blenkernel/intern/scene.c20
-rw-r--r--source/blender/blenkernel/intern/screen.c21
-rw-r--r--source/blender/blenkernel/intern/sequence.c24
-rw-r--r--source/blender/blenkernel/intern/smoke.c215
-rw-r--r--source/blender/blenkernel/intern/softbody.c67
-rw-r--r--source/blender/blenkernel/intern/sound.c8
-rw-r--r--source/blender/blenkernel/intern/text.c95
-rw-r--r--source/blender/blenkernel/intern/texture.c31
-rw-r--r--source/blender/blenkernel/intern/unit.c4
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c15
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, &times);
+ PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, &times);
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, &times);
+// 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, &timescale);
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);
}
}