Unified effector functionality for particles, cloth and softbody
authorJanne Karhu <jhkarh@gmail.com>
Wed, 30 Sep 2009 22:10:14 +0000 (22:10 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Wed, 30 Sep 2009 22:10:14 +0000 (22:10 +0000)
* Unified scene wide gravity (currently in scene buttons)
  instead of each simulation having it's own gravity.
* Weight parameters for all effectors and an effector group
  setting.
* Every effector can use noise.
* Most effectors have "shapes" point, plane, surface, every point.
- "Point" is most like the old effectors and uses the
  effector location as the effector point.
- "Plane" uses the closest point on effectors local xy-plane
  as the effector point.
- "Surface" uses the closest point on an effector object's
  surface as the effector point.
- "Every Point" uses every point in a mesh effector object
  as an effector point.
- The falloff is calculated from this point, so for example
  with "surface" shape and "use only negative z axis" it's
  possible to apply force only "inside" the effector object.
* Spherical effector is now renamed as "force" as it's no longer
  just spherical.
* New effector parameter "flow", which makes the effector act as
  surrounding air velocity, so the resulting force is
  proportional to the velocity difference of the point and "air
  velocity". For example a wind field with flow=1.0 results in
  proper non-accelerating wind.
* New effector fields "turbulence", which creates nice random
  flow paths, and "drag", which slows the points down.
* Much improved vortex field.
* Effectors can now effect particle rotation as well as location.
* Use full, or only positive/negative z-axis to apply force
  (note. the z-axis is the surface normal in the case of
  effector shape "surface")
* New "force field" submenu in add menu, which adds an empty
  with the chosen effector (curve object for corve guides).
* Other dynamics should be quite easy to add to the effector
  system too if wanted.
* "Unified" doesn't mean that force fields give the exact same results for
  particles, softbody & cloth, since their final effect depends on many external
  factors, like for example the surface area of the effected faces.

Code changes
* Subversion bump for correct handling of global gravity.
* Separate ui py file for common dynamics stuff.
* Particle settings updating is flushed with it's id through
  DAG_id_flush_update(..).

Known issues
* Curve guides don't yet have all ui buttons in place, but they
  should work none the less.
* Hair dynamics don't yet respect force fields.

Other changes
* Particle emission defaults now to frames 1-200 with life of 50
  frames to fill the whole default timeline.
* Many particles drawing related crashes fixed.
* Sometimes particles didn't update on first frame properly.
* Hair with object/group visualization didn't work properly.
* Memory leaks with PointCacheID lists (Genscher, remember to
  free pidlists after use :).

43 files changed:
release/scripts/ui/buttons_particle.py
release/scripts/ui/buttons_physics_cloth.py
release/scripts/ui/buttons_physics_common.py [new file with mode: 0644]
release/scripts/ui/buttons_physics_field.py
release/scripts/ui/buttons_physics_softbody.py
release/scripts/ui/buttons_scene.py
source/blender/blenkernel/BKE_collision.h
source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/boids.c
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/implicit.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/smoke.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/physics/particle_boids.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesdna/DNA_cloth_types.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_boid.c
source/blender/makesrna/intern/rna_cloth.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_particle.c
source/blender/makesrna/intern/rna_scene.c

index 5274ddbcfbe9e8b81c5940318e93e3f08177a5b5..1a800fc4dfd2b441020a6e1a73f7fc2f1cff3e02 100644 (file)
@@ -1,6 +1,11 @@
 
 import bpy
 
+from buttons_physics_common import point_cache_ui
+from buttons_physics_common import effector_weights_ui
+from buttons_physics_common import basic_force_field_settings_ui
+from buttons_physics_common import basic_force_field_falloff_ui
+
 def particle_panel_enabled(psys):
        return psys.point_cache.baked==False and psys.edited==False
        
@@ -10,72 +15,6 @@ def particle_panel_poll(context):
        if psys.settings==None:  return False
        return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR')
        
-def point_cache_ui(self, cache, enabled, particles, smoke):
-       layout = self.layout
-       layout.set_context_pointer("PointCache", cache)
-       
-       row = layout.row()
-       row.template_list(cache, "point_cache_list", cache, "active_point_cache_index", rows=2 )
-       col = row.column(align=True)
-       col.itemO("ptcache.add_new", icon='ICON_ZOOMIN', text="")
-       col.itemO("ptcache.remove", icon='ICON_ZOOMOUT', text="")
-       
-       row = layout.row()
-       row.itemL(text="File Name:")
-       if particles:
-               row.itemR(cache, "external")
-       
-       if cache.external:
-               split = layout.split(percentage=0.80)
-               split.itemR(cache, "name", text="")
-               split.itemR(cache, "index", text="")
-               
-               layout.itemL(text="File Path:")
-               layout.itemR(cache, "filepath", text="")
-               
-               layout.itemL(text=cache.info)
-       else:
-               layout.itemR(cache, "name", text="")
-               
-               if not particles:
-                       row = layout.row()
-                       row.enabled = enabled
-                       row.itemR(cache, "start_frame")
-                       row.itemR(cache, "end_frame")
-               
-               row = layout.row()
-       
-               if cache.baked == True:
-                       row.itemO("ptcache.free_bake", text="Free Bake")
-               else:
-                       row.item_booleanO("ptcache.bake", "bake", True, text="Bake")
-       
-               sub = row.row()
-               sub.enabled = (cache.frames_skipped or cache.outdated) and enabled
-               sub.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame")
-               
-               row = layout.row()
-               row.enabled = enabled
-               row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake")
-               if not smoke:
-                       row.itemR(cache, "step");
-       
-               if not smoke:
-                       row = layout.row()
-                       sub = row.row()
-                       sub.enabled = enabled
-                       sub.itemR(cache, "quick_cache")
-                       row.itemR(cache, "disk_cache")
-       
-               layout.itemL(text=cache.info)
-               
-               layout.itemS()
-               
-               row = layout.row()
-               row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
-               row.itemO("ptcache.free_bake_all", text="Free All Bakes")
-               layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame")
-       
 
 class ParticleButtonsPanel(bpy.types.Panel):
        __space_type__ = 'PROPERTIES'
@@ -244,24 +183,23 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel):
                
                split = layout.split()
                        
-               col = split.column()
-               col.itemL(text="Quality:")
-               col.itemR(cloth, "quality", text="Steps",slider=True)
-               col.itemL(text="Gravity:")
-               col.itemR(cloth, "gravity", text="")
-               
                col = split.column()
                col.itemL(text="Material:")
                sub = col.column(align=True)
                sub.itemR(cloth, "pin_stiffness", text="Stiffness")
                sub.itemR(cloth, "mass")
                sub.itemR(cloth, "bending_stiffness", text="Bending")
+               sub.itemR(cloth, "internal_friction", slider="True")
+               
+               col = split.column()
+
                col.itemL(text="Damping:")
                sub = col.column(align=True)
                sub.itemR(cloth, "spring_damping", text="Spring")
                sub.itemR(cloth, "air_damping", text="Air")
                
-               layout.itemR(cloth, "internal_friction", slider="True")
+               col.itemL(text="Quality:")
+               col.itemR(cloth, "quality", text="Steps",slider=True)
                                
 class PARTICLE_PT_cache(ParticleButtonsPanel):
        __label__ = "Cache"
@@ -385,9 +323,11 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
                        sub.itemR(part, "brownian_factor")
                        sub.itemR(part, "drag_factor", slider=True)
                        sub.itemR(part, "damp_factor", slider=True)
-                       sub.itemR(part, "integrator")
                        sub = split.column()
-                       sub.itemR(part, "acceleration")
+                       sub.itemR(part, "size_deflect")
+                       sub.itemR(part, "die_on_collision")
+                       sub.itemR(part, "integrator")
+                       sub.itemR(part, "time_tweak")
                        
                elif part.physics_type == 'KEYED':
                        split = layout.split()
@@ -445,14 +385,10 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
                        
                        col = row.column()
                        col.itemL(text="Misc:")
-                       col.itemR(part, "gravity")
                        col.itemR(boids, "banking", slider=True)
                        col.itemR(boids, "height", slider=True)
                        
-               if part.physics_type=='NEWTON':
-                       sub.itemR(part, "size_deflect")
-                       sub.itemR(part, "die_on_collision")
-               elif part.physics_type=='KEYED' or part.physics_type=='BOIDS':
+               if part.physics_type=='KEYED' or part.physics_type=='BOIDS':
                        if part.physics_type=='BOIDS':
                                layout.itemL(text="Relations:")
                        
@@ -502,11 +438,10 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
                return psys.settings.physics_type=='BOIDS'
        
        def draw(self, context):
-               psys = context.particle_system
-               boids = psys.settings.boids
+               boids = context.particle_system.settings.boids
                layout = self.layout
                
-               layout.enabled = particle_panel_enabled(psys)
+               layout.enabled = particle_panel_enabled(context.particle_system)
                
                # Currently boids can only use the first state so these are commented out for now.
                #row = layout.row()
@@ -858,30 +793,41 @@ class PARTICLE_PT_children(ParticleButtonsPanel):
                sub = split.column()
                sub.itemR(part, "kink_shape", slider=True)
 
-class PARTICLE_PT_effectors(ParticleButtonsPanel):
-       __label__ = "Effectors"
+class PARTICLE_PT_field_weights(ParticleButtonsPanel):
+       __label__ = "Field Weights"
+       __default_closed__ = True
+       
+       def draw(self, context):
+               part = context.particle_system.settings
+               effector_weights_ui(self, part.effector_weights)
+               
+               if part.type == 'HAIR':
+                       self.layout.itemR(part.effector_weights, "do_growing_hair")
+               
+class PARTICLE_PT_force_fields(ParticleButtonsPanel):
+       __label__ = "Force Field Settings"
        __default_closed__ = True
        
        def draw(self, context):
                layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
+               part = context.particle_system.settings
                
-               layout.itemR(part, "effector_group")
+               layout.itemR(part, "self_effect")
                
-               layout.itemR(part, "eweight_all", slider=True)
+               split = layout.split(percentage=0.2)
+               split.itemL(text="Type 1:")
+               split.itemR(part.force_field_1, "type",text="")
+               basic_force_field_settings_ui(self, part.force_field_1)
+               basic_force_field_falloff_ui(self, part.force_field_1)
                
-               layout.itemS()
-               layout.itemR(part, "eweight_spherical", slider=True)
-               layout.itemR(part, "eweight_vortex", slider=True)
-               layout.itemR(part, "eweight_magnetic", slider=True)
-               layout.itemR(part, "eweight_wind", slider=True)
-               layout.itemR(part, "eweight_curveguide", slider=True)
-               layout.itemR(part, "eweight_texture", slider=True)
-               layout.itemR(part, "eweight_harmonic", slider=True)
-               layout.itemR(part, "eweight_charge", slider=True)
-               layout.itemR(part, "eweight_lennardjones", slider=True)
+               if part.force_field_1.type != 'NONE':
+                       layout.itemL(text="")
+                       
+               split = layout.split(percentage=0.2)
+               split.itemL(text="Type 2:")
+               split.itemR(part.force_field_2, "type",text="")
+               basic_force_field_settings_ui(self, part.force_field_2)
+               basic_force_field_falloff_ui(self, part.force_field_2)
                
 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
        __label__ = "Vertexgroups"
@@ -958,5 +904,6 @@ bpy.types.register(PARTICLE_PT_boidbrain)
 bpy.types.register(PARTICLE_PT_render)
 bpy.types.register(PARTICLE_PT_draw)
 bpy.types.register(PARTICLE_PT_children)
-bpy.types.register(PARTICLE_PT_effectors)
+bpy.types.register(PARTICLE_PT_field_weights)
+bpy.types.register(PARTICLE_PT_force_fields)
 bpy.types.register(PARTICLE_PT_vertexgroups)
index f6493951a34e8668f285636162e00ccfc1c0d007..e25497b371396fb6e73665a28bf70ac42f8125a5 100644 (file)
@@ -1,7 +1,8 @@
 
 import bpy
 
-from buttons_particle import point_cache_ui
+from buttons_physics_common import point_cache_ui
+from buttons_physics_common import effector_weights_ui
 
 def cloth_panel_enabled(md):
        return md.point_cache.baked==False
@@ -49,10 +50,11 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel):
                        split = layout.split()
                        
                        col = split.column()
-                       col.itemL(text="Quality:")
-                       col.itemR(cloth, "quality", text="Steps",slider=True)
-                       col.itemL(text="Gravity:")
-                       col.itemR(cloth, "gravity", text="")
+                       col.itemL(text="Material:")
+                       sub = col.column(align=True)
+                       sub.itemR(cloth, "mass")
+                       sub.itemR(cloth, "structural_stiffness", text="Structural")
+                       sub.itemR(cloth, "bending_stiffness", text="Bending")
 
                        col.itemR(cloth, "pin_cloth", text="Pin")
                        sub = col.column(align=True)
@@ -61,18 +63,18 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel):
                        sub.item_pointerR(cloth, "mass_vertex_group", ob, "vertex_groups", text="")
                        
                        col = split.column()
-                       col.itemL(text="Presets...")
-                       col.itemL(text="TODO!")
-                       col.itemL(text="Material:")
-                       sub = col.column(align=True)
-                       sub.itemR(cloth, "mass")
-                       sub.itemR(cloth, "structural_stiffness", text="Structural")
-                       sub.itemR(cloth, "bending_stiffness", text="Bending")
+
                        col.itemL(text="Damping:")
                        sub = col.column(align=True)
                        sub.itemR(cloth, "spring_damping", text="Spring")
                        sub.itemR(cloth, "air_damping", text="Air")
                        
+                       col.itemL(text="Presets...")
+                       col.itemL(text="TODO!")
+                       
+                       col.itemL(text="Quality:")
+                       col.itemR(cloth, "quality", text="Steps",slider=True)
+                       
                        # Disabled for now
                        """
                        if cloth.mass_vertex_group:
@@ -165,8 +167,20 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel):
                sub = col.column(align=True)
                sub.itemR(cloth, "bending_stiffness_max", text="Max")
                sub.item_pointerR(cloth, "bending_vertex_group", ob, "vertex_groups", text="")
+
+class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel):
+       __label__ = "Cloth Field Weights"
+       __default_closed__ = True
+       
+       def poll(self, context):
+               return (context.cloth)
+       
+       def draw(self, context):
+               cloth = context.cloth.settings
+               effector_weights_ui(self, cloth.effector_weights)
                
 bpy.types.register(PHYSICS_PT_cloth)
 bpy.types.register(PHYSICS_PT_cloth_cache)
 bpy.types.register(PHYSICS_PT_cloth_collision)
 bpy.types.register(PHYSICS_PT_cloth_stiffness)
+bpy.types.register(PHYSICS_PT_cloth_field_weights)
diff --git a/release/scripts/ui/buttons_physics_common.py b/release/scripts/ui/buttons_physics_common.py
new file mode 100644 (file)
index 0000000..b65d092
--- /dev/null
@@ -0,0 +1,153 @@
+import bpy
+
+def point_cache_ui(self, cache, enabled, particles, smoke):
+       layout = self.layout
+       layout.set_context_pointer("PointCache", cache)
+       
+       row = layout.row()
+       row.template_list(cache, "point_cache_list", cache, "active_point_cache_index", rows=2 )
+       col = row.column(align=True)
+       col.itemO("ptcache.add_new", icon='ICON_ZOOMIN', text="")
+       col.itemO("ptcache.remove", icon='ICON_ZOOMOUT', text="")
+       
+       row = layout.row()
+       row.itemL(text="File Name:")
+       if particles:
+               row.itemR(cache, "external")
+       
+       if cache.external:
+               split = layout.split(percentage=0.80)
+               split.itemR(cache, "name", text="")
+               split.itemR(cache, "index", text="")
+               
+               layout.itemL(text="File Path:")
+               layout.itemR(cache, "filepath", text="")
+               
+               layout.itemL(text=cache.info)
+       else:
+               layout.itemR(cache, "name", text="")
+               
+               if not particles:
+                       row = layout.row()
+                       row.enabled = enabled
+                       row.itemR(cache, "start_frame")
+                       row.itemR(cache, "end_frame")
+               
+               row = layout.row()
+       
+               if cache.baked == True:
+                       row.itemO("ptcache.free_bake", text="Free Bake")
+               else:
+                       row.item_booleanO("ptcache.bake", "bake", True, text="Bake")
+       
+               sub = row.row()
+               sub.enabled = (cache.frames_skipped or cache.outdated) and enabled
+               sub.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame")
+               
+               row = layout.row()
+               row.enabled = enabled
+               row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake")
+               if not smoke:
+                       row.itemR(cache, "step");
+       
+               if not smoke:
+                       row = layout.row()
+                       sub = row.row()
+                       sub.enabled = enabled
+                       sub.itemR(cache, "quick_cache")
+                       row.itemR(cache, "disk_cache")
+       
+               layout.itemL(text=cache.info)
+               
+               layout.itemS()
+               
+               row = layout.row()
+               row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
+               row.itemO("ptcache.free_bake_all", text="Free All Bakes")
+               layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame")
+               
+def effector_weights_ui(self, weights):
+               layout = self.layout
+               
+               layout.itemR(weights, "group")
+               
+               split = layout.split()
+               split.itemR(weights, "gravity", slider=True)
+               split.itemR(weights, "all", slider=True)
+               
+               layout.itemS()
+               
+               flow = layout.column_flow()
+               flow.itemR(weights, "spherical", slider=True)
+               flow.itemR(weights, "vortex", slider=True)
+               flow.itemR(weights, "magnetic", slider=True)
+               flow.itemR(weights, "wind", slider=True)
+               flow.itemR(weights, "curveguide", slider=True)
+               flow.itemR(weights, "texture", slider=True)
+               flow.itemR(weights, "harmonic", slider=True)
+               flow.itemR(weights, "charge", slider=True)
+               flow.itemR(weights, "lennardjones", slider=True)
+               flow.itemR(weights, "turbulence", slider=True)
+               flow.itemR(weights, "drag", slider=True)
+               flow.itemR(weights, "boid", slider=True)
+               
+def basic_force_field_settings_ui(self, field):
+       layout = self.layout
+       split = layout.split()
+       
+       if not field or field.type == 'NONE':
+               return
+       
+       col = split.column()
+       
+       if field.type == 'DRAG':
+               col.itemR(field, "linear_drag", text="Linear")
+       else:
+               col.itemR(field, "strength")
+               
+       if field.type == 'TURBULENCE':
+               col.itemR(field, "size")
+               col.itemR(field, "flow")
+       elif field.type == 'HARMONIC':
+               col.itemR(field, "harmonic_damping", text="Damping")
+       elif field.type == 'VORTEX' and field.shape == 'PLANE':
+               col.itemR(field, "inflow")
+       elif field.type == 'DRAG':
+               col.itemR(field, "quadratic_drag", text="Quadratic")
+       else:
+               col.itemR(field, "flow")
+       
+       col = split.column()
+       col.itemR(field, "noise")
+       col.itemR(field, "seed")
+       if field.type == 'TURBULENCE':
+               col.itemR(field, "global_coordinates", text="Global")
+       
+       row = layout.row()
+       row.itemL(text="Effect point:")
+       row.itemR(field, "do_location")
+       row.itemR(field, "do_rotation")
+               
+               
+def basic_force_field_falloff_ui(self, field):
+       layout = self.layout
+       split = layout.split(percentage=0.35)
+       
+       if not field or field.type == 'NONE':
+               return
+               
+       col = split.column()
+       col.itemR(field, "z_direction", text="")
+       col.itemR(field, "use_min_distance", text="Use Minimum")
+       col.itemR(field, "use_max_distance", text="Use Maximum")
+
+       col = split.column()
+       col.itemR(field, "falloff_power", text="Power")
+       
+       sub = col.column()
+       sub.active = field.use_min_distance
+       sub.itemR(field, "minimum_distance", text="Distance")
+       
+       sub = col.column()
+       sub.active = field.use_max_distance
+       sub.itemR(field, "maximum_distance", text="Distance")
\ No newline at end of file
index 7d14690856a363d5710d2b41cd976bf5eb1f00ff..24740acc68f58bb5dfcf043a92030bef77bf9405 100644 (file)
@@ -1,6 +1,9 @@
 
 import bpy
 
+from buttons_physics_common import basic_force_field_settings_ui
+from buttons_physics_common import basic_force_field_falloff_ui
+
 class PhysicButtonsPanel(bpy.types.Panel):
        __space_type__ = 'PROPERTIES'
        __region_type__ = 'WINDOW'
@@ -12,7 +15,6 @@ class PhysicButtonsPanel(bpy.types.Panel):
                
 class PHYSICS_PT_field(PhysicButtonsPanel):
        __label__ = "Force Fields"
-       __default_closed__ = True
 
        def draw(self, context):
                layout = self.layout
@@ -23,50 +25,21 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
                #layout.active = field.enabled
                
                split = layout.split(percentage=0.2)
-               
                split.itemL(text="Type:")
                split.itemR(field, "type",text="")
+               
+               if field.type not in ('NONE', 'GUIDE', 'TEXTURE'):
+                       split = layout.split(percentage=0.2)
+                       #split = layout.row()
+                       split.itemL(text="Shape:")
+                       split.itemR(field, "shape", text="")
                        
                split = layout.split()
                
-               if field.type == 'GUIDE':
+               if field.type == 'NONE':
+                       return # nothing to draw
+               elif field.type == 'GUIDE':
                        layout.itemR(field, "guide_path_add")
-                       
-               elif field.type == 'WIND':
-                       split.itemR(field, "strength")
-                       
-                       col = split.column()
-                       col.itemR(field, "noise")
-                       col.itemR(field, "seed")
-
-               elif field.type == 'VORTEX':
-                       split.itemR(field, "strength")
-                       split.itemL()
-                       
-               elif field.type in ('SPHERICAL', 'CHARGE', 'LENNARDJ'):
-                       split.itemR(field, "strength")
-                       
-                       col = split.column()
-                       col.itemR(field, "planar")
-                       col.itemR(field, "surface")
-                       
-               elif field.type == 'BOID':
-                       split.itemR(field, "strength")
-                       split.itemR(field, "surface")
-                       
-               elif field.type == 'MAGNET':
-                       split.itemR(field, "strength")
-                       split.itemR(field, "planar")
-                       
-               elif field.type == 'HARMONIC':
-                       col = split.column()
-                       col.itemR(field, "strength")
-                       col.itemR(field, "harmonic_damping", text="Damping")
-                       
-                       col = split.column()
-                       col.itemR(field, "planar")
-                       col.itemR(field, "surface")
-                       
                elif field.type == 'TEXTURE':
                        col = split.column()
                        col.itemR(field, "strength")
@@ -78,29 +51,15 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
                        col.itemR(field, "use_coordinates")
                        col.itemR(field, "root_coordinates")
                        col.itemR(field, "force_2d")
+               else :
+                       basic_force_field_settings_ui(self, field)
                        
-               if field.type in ('HARMONIC', 'SPHERICAL', 'CHARGE', 'WIND', 'VORTEX', 'TEXTURE', 'MAGNET', 'BOID'):
+               if field.type not in ('NONE', 'GUIDE'):
                        
                        layout.itemL(text="Falloff:")
                        layout.itemR(field, "falloff_type", expand=True)
 
-                       split = layout.split(percentage=0.35)
-                       
-                       col = split.column()
-                       col.itemR(field, "positive_z", text="Positive Z")
-                       col.itemR(field, "use_min_distance", text="Use Minimum")
-                       col.itemR(field, "use_max_distance", text="Use Maximum")
-
-                       col = split.column()
-                       col.itemR(field, "falloff_power", text="Power")
-                       
-                       sub = col.column()
-                       sub.active = field.use_min_distance
-                       sub.itemR(field, "minimum_distance", text="Distance")
-                       
-                       sub = col.column()
-                       sub.active = field.use_max_distance
-                       sub.itemR(field, "maximum_distance", text="Distance")
+                       basic_force_field_falloff_ui(self, field)
                        
                        if field.falloff_type == 'CONE':
                                layout.itemS()
@@ -157,7 +116,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
 
 class PHYSICS_PT_collision(PhysicButtonsPanel):
        __label__ = "Collision"
-       __default_closed__ = True
+       #__default_closed__ = True
        
        def poll(self, context):
                ob = context.object
@@ -182,16 +141,18 @@ class PHYSICS_PT_collision(PhysicButtonsPanel):
                        #row.itemR(md, "render", text="")
                        #row.itemR(md, "realtime", text="")
                        
-                       settings = md.settings
+                       coll = md.settings
                        
                else:
                        # add modifier
                        split.item_enumO("object.modifier_add", "type", 'COLLISION', text="Add")
                        split.itemL()
                        
-                       settings = None
+                       coll = None
                
-               if settings:
+               if coll:
+                       settings = context.object.collision
+
                        layout.active = settings.enabled
                
                        split = layout.split()
index 3bdbb1b8b900c08b51c6b5114ff7f404419ef748..cd66df00044bf1e4e9463ca63fc54dacbd56db1c 100644 (file)
@@ -1,7 +1,8 @@
 
 import bpy
 
-from buttons_particle import point_cache_ui
+from buttons_physics_common import point_cache_ui
+from buttons_physics_common import effector_weights_ui
 
 def softbody_panel_enabled(md):
        return md.point_cache.baked==False
@@ -55,7 +56,6 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel):
 
                        col = split.column()
                        col.itemL(text="Simulation:")
-                       col.itemR(softbody, "gravity")
                        col.itemR(softbody, "speed")
                        
 class PHYSICS_PT_softbody_cache(PhysicButtonsPanel):
@@ -222,6 +222,18 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
                        
                layout.itemL(text="Diagnostics:")
                layout.itemR(softbody, "diagnose")
+
+class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel):
+       __label__ = "Soft Body Field Weights"
+       __default_closed__ = True
+       
+       def poll(self, context):
+               return (context.soft_body)
+       
+       def draw(self, context):
+               md = context.soft_body
+               softbody = md.settings
+               effector_weights_ui(self, softbody.effector_weights)
        
 bpy.types.register(PHYSICS_PT_softbody)
 bpy.types.register(PHYSICS_PT_softbody_cache)
@@ -229,3 +241,4 @@ bpy.types.register(PHYSICS_PT_softbody_goal)
 bpy.types.register(PHYSICS_PT_softbody_edge)
 bpy.types.register(PHYSICS_PT_softbody_collision)
 bpy.types.register(PHYSICS_PT_softbody_solver)
+bpy.types.register(PHYSICS_PT_softbody_field_weights)
index 88947aac86c824372d1494037ba162847c2647c6..2fbd176e36a3d31586bdcde32be47955131964a9 100644 (file)
@@ -451,6 +451,23 @@ class SCENE_PT_unit(RenderButtonsPanel):
                row.itemR(unit, "scale_length", text="Scale")
                row.itemR(unit, "use_separate")
 
+class SCENE_PT_physics(RenderButtonsPanel):
+       __label__ = "Gravity"
+       COMPAT_ENGINES = set(['BLENDER_RENDER'])
+
+       def draw_header(self, context):
+               self.layout.itemR(context.scene, "use_gravity", text="")
+
+       def draw(self, context):
+               layout = self.layout
+               
+               scene = context.scene
+
+               layout.active = scene.use_gravity
+
+               layout.itemR(scene, "gravity", text="")
+
+               
 bpy.types.register(SCENE_PT_render)
 bpy.types.register(SCENE_PT_layers)
 bpy.types.register(SCENE_PT_dimensions)
@@ -462,3 +479,4 @@ bpy.types.register(SCENE_PT_performance)
 bpy.types.register(SCENE_PT_post_processing)
 bpy.types.register(SCENE_PT_stamp)
 bpy.types.register(SCENE_PT_unit)
+bpy.types.register(SCENE_PT_physics)
index e0df75f41b9421edaf129dc33fef5a74f2d843f5..5ca8ad892ac4f27ead3958e1ed3af1d23f85b2e6 100644 (file)
@@ -141,6 +141,15 @@ void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3],
 /////////////////////////////////////////////////
 Object **get_collisionobjects(struct Scene *scene, Object *self, int *numcollobj);
 
+typedef struct ColliderCache {
+       struct ColliderCache *next, *prev;
+       struct Object *ob;
+       struct CollisionModifierData *collmd;
+} ColliderCache;
+
+struct ListBase *get_collider_cache(struct Scene *scene, Object *self);
+void free_collider_cache(struct ListBase **colliders);
+
 /////////////////////////////////////////////////
 
 
index e21e83bf5cf3aa63311d0b9964019a48f479b954..83ec7c13946fd740df456b9655ff4296485b8b18 100644 (file)
@@ -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
index 5850ddaca08f38ca0f7ce29f27712b7376fd7b2d..e0259ff10dd3437c45e5284fb884e1116d021fc8 100644 (file)
@@ -76,39 +76,18 @@ typedef struct ParticleSimulationData {
        struct Object *ob;
        struct ParticleSystem *psys;
        struct ParticleSystemModifierData *psmd;
-       float timestep;
+       struct ListBase *colliders;
 } ParticleSimulationData;
 
-typedef struct ParticleEffectorCache {
-       struct ParticleEffectorCache *next, *prev;
-       struct Object *ob;
-       
-       /* precalculated variables for guides */
-       float firstloc[4], firstdir[3];
-       float *distances;
-       float *locations;
-       /* precalculated variables for deflection */
-       float ob_minmax[6];
-       float *face_minmax;
-       float *vert_cos;
-       /* precalculated variables for boids */
-       struct KDTree *tree;
-
-       short type, psys_nbr;
-       
-       struct Object obcopy;   /* for restoring transformation data */
-       struct RNG *rng; /* random noise generator for e.g. wind */
-} ParticleEffectorCache;
-
-typedef struct ParticleReactEvent {
-       struct ParticleReactEvent *next, *prev;
-       int event, pa_num;
-       Object *ob;
-       struct ParticleSystem *psys;
-       struct ParticleKey state;
-
-       float time, size;
-}ParticleReactEvent;
+//typedef struct ParticleReactEvent {
+//     struct ParticleReactEvent *next, *prev;
+//     int event, pa_num;
+//     Object *ob;
+//     struct ParticleSystem *psys;
+//     struct ParticleKey state;
+//
+//     float time, size;
+//}ParticleReactEvent;
 
 typedef struct ParticleTexture{
        float ivel;                                                     /* used in reset */
@@ -185,8 +164,8 @@ typedef struct ParticleBillboardData
 /* container for moving data between deflet_particle and particle_intersect_face */
 typedef struct ParticleCollision
 {
-       struct Object *ob, *ob_t; // collided and current objects
-       struct CollisionModifierData *md; // collision modifier for ob_t;
+       struct Object *ob, *hit_ob; // collided and current objects
+       struct CollisionModifierData *md, *hit_md; // collision modifiers for current and hit object;
        float nor[3]; // normal at collision point
        float vel[3]; // velocity of collision point
        float co1[3], co2[3]; // ray start and end points
@@ -244,7 +223,6 @@ void object_add_particle_system(struct Scene *scene, struct Object *ob);
 void object_remove_particle_system(struct Scene *scene, struct Object *ob);
 struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
 struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
-void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc);
 void make_local_particlesettings(struct ParticleSettings *part);
 
 void psys_reset(struct ParticleSystem *psys, int mode);
@@ -254,7 +232,8 @@ void psys_find_parents(struct ParticleSimulationData *sim);
 void psys_cache_paths(struct ParticleSimulationData *sim, float cfra);
 void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra);
 void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, int editupdate);
-int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb);
+int do_guides(struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
+void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors);
 float psys_get_timestep(struct ParticleSimulationData *sim);
 float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
 float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time);
@@ -273,9 +252,7 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
 /* particle_system.c */
 struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
 void psys_count_keyed_targets(struct ParticleSimulationData *sim);
-//void psys_get_reactor_target(struct ParticleSimulationData *sim, struct Object **target_ob, struct ParticleSystem **target_psys);
-
-int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc);
+void psys_update_particle_tree(struct ParticleSystem *psys, float cfra);
 
 void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
 void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra);
@@ -316,29 +293,17 @@ void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_
 
 /* particle_system.c */
 void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, int p);
-
-int effector_find_co(struct Scene *scene, float *pco, struct SurfaceModifierData *sur, struct Object *ob, struct PartDeflect *pd, float *co, float *nor, float *vel, int *index);
-void do_effectors(struct ParticleSimulationData *sim, int pa_no, struct ParticleData *pa, struct ParticleKey *state, float *texco, float *force_field, float *vel,float framestep, float cfra);
-void psys_end_effectors(struct ParticleSystem *psys);
-
 void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);
 int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node);
 
 void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra);
 
-
 /* psys_reset */
 #define PSYS_RESET_ALL                 1
 #define PSYS_RESET_DEPSGRAPH   2
 #define PSYS_RESET_CHILDREN    3
 #define PSYS_RESET_CACHE_MISS  4
 
-/* ParticleEffectorCache->type */
-#define PSYS_EC_EFFECTOR       1
-#define PSYS_EC_DEFLECT                2
-#define PSYS_EC_PARTICLE       4
-#define PSYS_EC_REACTOR                8
-
 /* index_dmcache */
 #define DMCACHE_NOTFOUND       -1
 #define DMCACHE_ISCHILD                -2
index 7c3f3a7876f1c0222b85bb4c78bfa7976a333a21..76824d3a34a5bfd78c376d146687d1e8d41690e3 100644 (file)
@@ -47,6 +47,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_kdtree.h"
 #include "BLI_kdopbvh.h"
+#include "BKE_collision.h"
 #include "BKE_effect.h"
 #include "BKE_boids.h"
 #include "BKE_particle.h"
@@ -72,112 +73,91 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
 {
        BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule;
        BoidSettings *boids = bbd->part->boids;
-       ParticleEffectorCache *ec;
        Object *priority_ob = NULL;
        BoidParticle *bpa = pa->boid;
+       EffectedPoint epoint;
+       ListBase *effectors = bbd->sim->psys->effectors;
+       EffectorCache *cur, *eff = NULL;
+       EffectorData efd, cur_efd;
        float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
        float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
        float priority = 0.0f, len = 0.0f;
        int ret = 0;
 
-       /* first find out goal/predator with highest priority */
-       /* if rule->ob specified use it */
-       if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) {
-               PartDeflect *pd = gabr->ob->pd;
-               float vec_to_part[3];
-
-               if(pd && pd->forcefield == PFIELD_BOID) {
-                       effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, gabr->ob, pd, loc, vec, NULL, NULL);
-                       
-                       VecSubf(vec_to_part, pa->prev_state.co, loc);
+       pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
 
-                       priority = mul * pd->f_strength * effector_falloff(pd, vec, vec_to_part);
-               }
-               else
-                       priority = 1.0;
-
-               priority = 1.0;
-               priority_ob = gabr->ob;
-       }
-       else for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) {
-               if(ec->type & PSYS_EC_EFFECTOR) {
-                       Object *eob = ec->ob;
-                       PartDeflect *pd = eob->pd;
-
-                       /* skip current object */
-                       if(rule->type == eBoidRuleType_Goal && eob == bpa->ground)
-                               continue;
-
-                       if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f) {
-                               float vec_to_part[3], temp;
-
-                               effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, vec, NULL, NULL);
-                               
-                               VecSubf(vec_to_part, pa->prev_state.co, loc);
-
-                               temp = mul * pd->f_strength * effector_falloff(pd, vec, vec_to_part);
-
-                               if(temp == 0.0f)
-                                       ; /* do nothing */
-                               else if(temp > priority) {
-                                       priority = temp;
-                                       priority_ob = eob;
-                                       len = VecLength(vec_to_part);
-                               }
-                               /* choose closest object with same priority */
-                               else if(temp == priority) {
-                                       float len2 = VecLength(vec_to_part);
-
-                                       if(len2 < len) {
-                                               priority_ob = eob;
-                                               len = len2;
-                                       }
+       /* first find out goal/predator with highest priority */
+       if(effectors) for(cur = effectors->first; cur; cur=cur->next) {
+               Object *eob = cur->ob;
+               PartDeflect *pd = cur->pd;
+
+               if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) {
+                       if(gabr->ob == eob) {
+                               /* TODO: objects without any effector and effectors with multiple points */
+                               if(get_effector_data(cur, &efd, &epoint, 0)) {
+                                       if(cur->pd && cur->pd->forcefield == PFIELD_BOID)
+                                               priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights);
+                                       else
+                                               priority = 1.0;
+
+                                       eff = cur;
                                }
+                               break;
+                       }
+               }
+               else if(rule->type == eBoidRuleType_Goal && eob == bpa->ground)
+                       ; /* skip current object */
+               else if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(eff, &efd, &epoint, 0)) {
+                       float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights);
+
+                       if(temp == 0.0f)
+                               ; /* do nothing */
+                       else if(temp > priority) {
+                               priority = temp;
+                               eff = cur;
+                               efd = cur_efd;
+                               len = efd.distance;
+                       }
+                       /* choose closest object with same priority */
+                       else if(temp == priority && efd.distance < len) {
+                               eff = cur;
+                               efd = cur_efd;
+                               len = efd.distance;
                        }
                }
        }
 
        /* then use that effector */
        if(priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */
-               Object *eob = priority_ob;
+               Object *eob = eff->ob;
                PartDeflect *pd = eob->pd;
-               float vec_to_part[3];
-               float surface = 0.0f;
-               float nor[3];
+               float surface = pd->shape == PFIELD_SHAPE_SURFACE ? 1.0f : 0.0f;
 
                if(gabr->options & BRULE_GOAL_AVOID_PREDICT) {
                        /* estimate future location of target */
-                       surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, vec, NULL); 
-
-                       VecSubf(vec_to_part, pa->prev_state.co, loc);
-                       len = Normalize(vec_to_part);
+                       get_effector_data(eff, &efd, &epoint, 1);
 
-                       VecMulf(vec, len / (val->max_speed * bbd->timestep));
-                       VecAddf(loc, loc, vec);
-                       VecSubf(vec_to_part, pa->prev_state.co, loc);
-               }
-               else {
-                       surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, NULL, NULL);
-
-                       VecSubf(vec_to_part, pa->prev_state.co, loc);
-                       len = VecLength(vec_to_part);
+                       VecMulf(efd.vel, efd.distance / (val->max_speed * bbd->timestep));
+                       VecAddf(efd.loc, efd.loc, efd.vel);
+                       VecSubf(efd.vec_to_point, pa->prev_state.co, efd.loc);
+                       efd.distance = VecLength(efd.vec_to_point);
                }
 
                if(rule->type == eBoidRuleType_Goal && boids->options & BOID_ALLOW_CLIMB && surface!=0.0f) {
                        if(!bbd->goal_ob || bbd->goal_priority < priority) {
                                bbd->goal_ob = eob;
-                               VECCOPY(bbd->goal_co, loc);
-                               VECCOPY(bbd->goal_nor, nor);
+                               VECCOPY(bbd->goal_co, efd.loc);
+                               VECCOPY(bbd->goal_nor, efd.nor);
                        }
                }
                else if(rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing &&
                        priority > 2.0f * gabr->fear_factor) {
                        /* detach from surface and try to fly away from danger */
-                       VECCOPY(vec_to_part, bpa->gravity);
-                       VecMulf(vec_to_part, -1.0f);
+                       VECCOPY(efd.vec_to_point, bpa->gravity);
+                       VecMulf(efd.vec_to_point, -1.0f);
                }
 
-               VECCOPY(bbd->wanted_co, vec_to_part);
+               VECCOPY(bbd->wanted_co, efd.vec_to_point);
                VecMulf(bbd->wanted_co, mul);
 
                bbd->wanted_speed = val->max_speed * priority;
@@ -188,8 +168,8 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
 
                        surface *= pa->size * boids->height;
 
-                       if(len2 > 0.0f && len - surface < len2) {
-                               len2 = (len - surface)/len2;
+                       if(len2 > 0.0f && efd.distance - surface < len2) {
+                               len2 = (efd.distance - surface)/len2;
                                bbd->wanted_speed *= pow(len2, boids->landing_smoothness);
                        }
                }
@@ -204,9 +184,9 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
 {
        BoidRuleAvoidCollision *acbr = (BoidRuleAvoidCollision*) rule;
        KDTreeNearest *ptn = NULL;
-       ParticleEffectorCache *ec;
        ParticleTarget *pt;
        BoidParticle *bpa = pa->boid;
+       ColliderCache *coll;
        float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
        float co1[3], vel1[3], co2[3], vel2[3];
        float  len, t, inp, t_min = 2.0f;
@@ -214,7 +194,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
        int ret = 0;
 
        //check deflector objects first
-       if(acbr->options & BRULE_ACOLL_WITH_DEFLECTORS) {
+       if(acbr->options & BRULE_ACOLL_WITH_DEFLECTORS && bbd->sim->colliders) {
                ParticleCollision col;
                BVHTreeRayHit hit;
                float radius = val->personal_space * pa->size, ray_dir[3];
@@ -228,20 +208,16 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
                hit.dist = col.ray_len = VecLength(ray_dir);
 
                /* find out closest deflector object */
-               for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) {
-                       if(ec->type & PSYS_EC_DEFLECT) {
-                               Object *eob = ec->ob;
-
-                               /* don't check with current ground object */
-                               if(eob == bpa->ground)
-                                       continue;
+               for(coll = bbd->sim->colliders->first; coll; coll=coll->next) {
+                       /* don't check with current ground object */
+                       if(coll->ob == bpa->ground)
+                               continue;
 
-                               col.md = ( CollisionModifierData * ) ( modifiers_findByType ( eob, eModifierType_Collision ) );
-                               col.ob_t = eob;
+                       col.ob = coll->ob;
+                       col.md = coll->collmd;
 
-                               if(col.md && col.md->bvhtree)
-                                       BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
-                       }
+                       if(col.md && col.md->bvhtree)
+                               BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
                }
                /* then avoid that object */
                if(hit.index>=0) {
@@ -756,25 +732,28 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
        if(bpa->data.mode == eBoidMode_Climbing) {
                SurfaceModifierData *surmd = NULL;
                float x[3], v[3];
-
+               
                surmd = (SurfaceModifierData *)modifiers_findByType ( bpa->ground, eModifierType_Surface );
 
                /* take surface velocity into account */
-               effector_find_co(bbd->sim->scene, pa->state.co, surmd, NULL, NULL, x, NULL, v, NULL);
+               closest_point_on_surface(surmd, pa->state.co, x, NULL, v);
                VecAddf(x, x, v);
 
                /* get actual position on surface */
-               effector_find_co(bbd->sim->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL);
+               closest_point_on_surface(surmd, x, ground_co, ground_nor, NULL);
 
                return bpa->ground;
        }
        else {
                float zvec[3] = {0.0f, 0.0f, 2000.0f};
                ParticleCollision col;
+               ColliderCache *coll;
                BVHTreeRayHit hit;
-               ParticleEffectorCache *ec;
                float radius = 0.0f, t, ray_dir[3];
 
+               if(!bbd->sim->colliders)
+                       return NULL;
+
                VECCOPY(col.co1, pa->state.co);
                VECCOPY(col.co2, pa->state.co);
                VecAddf(col.co1, col.co1, zvec);
@@ -785,16 +764,12 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
                hit.dist = col.ray_len = VecLength(ray_dir);
 
                /* find out upmost deflector object */
-               for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) {
-                       if(ec->type & PSYS_EC_DEFLECT) {
-                               Object *eob = ec->ob;
+               for(coll = bbd->sim->colliders->first; coll; coll = coll->next){
+                       col.ob = coll->ob;
+                       col.md = coll->collmd;
 
-                               col.md = ( CollisionModifierData * ) ( modifiers_findByType ( eob, eModifierType_Collision ) );
-                               col.ob_t = eob;
-
-                               if(col.md && col.md->bvhtree)
-                                       BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
-                       }
+                       if(col.md && col.md->bvhtree)
+                               BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
                }
                /* then use that object */
                if(hit.index>=0) {
@@ -802,7 +777,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
                        VecLerpf(ground_co, col.co1, col.co2, t);
                        VECCOPY(ground_nor, col.nor);
                        Normalize(ground_nor);
-                       return col.ob;
+                       return col.hit_ob;
                }
                else {
                        /* default to z=0 */
@@ -1068,6 +1043,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
        BoidSettings *boids = bbd->part->boids;
        BoidParticle *bpa = pa->boid;
        BoidValues val;
+       EffectedPoint epoint;
        float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3];
        float dvec[3], bvec[3];
        float new_dir[3], new_speed;
@@ -1208,7 +1184,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
        }
 
        /* account for effectors */
-       do_effectors(bbd->sim, p, pa, &pa->state, pa->state.co, force, tvel, bbd->dfra, bbd->cfra);
+       pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
+       pdDoEffectors(bbd->sim->psys->effectors, bbd->sim->colliders, bbd->part->effector_weights, &epoint, force, NULL);
 
        if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
                float length = Normalize(force);
index 5cfbd5c18dc2ad5752e629bdd8e4988c78a66f7a..74f88a77e63192937e2d03a49b9f99513bb8a405 100644 (file)
@@ -153,6 +153,9 @@ void cloth_init ( ClothModifierData *clmd )
        clmd->sim_parms->defgoal = 0.0f;
        clmd->sim_parms->goalspring = 1.0f;
        clmd->sim_parms->goalfrict = 0.0f;
+
+       if(!clmd->sim_parms->effector_weights)
+               clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
 }
 
 static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon)
@@ -402,6 +405,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
                VECCOPY(verts->xconst, mvert[i].co);
                Mat4MulVecfl(ob->obmat, verts->xconst);
        }
+
+       effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights);
        
        tstart();
 
@@ -411,6 +416,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
 
        tend();
 
+       pdEndEffectors(&effectors);
+
        // printf ( "%f\n", ( float ) tval() );
        
        return ret;
index 20fc170845457bafde7f488c01442b746e2323bd..8c664bc1a576d9f5dbba385f7ac15fd699c7a83b 100644 (file)
@@ -1392,6 +1392,97 @@ Object **get_collisionobjects(Scene *scene, Object *self, int *numcollobj)
        return objs;
 }
 
+ListBase *get_collider_cache(Scene *scene, Object *self)
+{
+       Base *base=NULL;
+       ListBase *objs = NULL;
+       Object *coll_ob = NULL;
+       CollisionModifierData *collmd = NULL;
+       ColliderCache *col;
+       
+       // check all collision objects
+       for ( base = scene->base.first; base; base = base->next )
+       {
+               /*Only proceed for mesh object in same layer */
+               if(base->object->type!=OB_MESH)
+                       continue;
+
+               if(self && (base->lay & self->lay)==0) 
+                       continue;
+
+               
+               coll_ob = base->object;
+               
+               if(coll_ob == self)
+                               continue;
+               
+               if(coll_ob->pd && coll_ob->pd->deflect)
+               {
+                       collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+               }
+               else
+                       collmd = NULL;
+               
+               if ( collmd )
+               {       
+                       if(objs == NULL)
+                               objs = MEM_callocN(sizeof(ListBase), "ColliderCache array");
+
+                       col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
+                       col->ob = coll_ob;
+                       col->collmd = collmd;
+                       /* make sure collider is properly set up */
+                       collision_move_object(collmd, 1.0, 0.0);
+                       BLI_addtail(objs, col);
+               }
+               else if ( coll_ob->dup_group )
+                       {
+                               GroupObject *go;
+                               Group *group = coll_ob->dup_group;
+
+                               for ( go= group->gobject.first; go; go= go->next )
+                               {
+                                       coll_ob = go->ob;
+                                       collmd = NULL;
+                                       
+                                       if(coll_ob == self)
+                                               continue;
+                                       
+                                       if(coll_ob->pd && coll_ob->pd->deflect)
+                                       {
+                                               collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+                                       }
+                                       else
+                                               collmd = NULL;
+
+                                       if ( !collmd )
+                                               continue;
+                                       
+                                       if( !collmd->bvhtree)
+                                               continue;
+
+                                       if(objs == NULL)
+                                               objs = MEM_callocN(sizeof(ListBase), "ColliderCache array");
+
+                                       col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
+                                       col->ob = coll_ob;
+                                       col->collmd = collmd;
+                                       /* make sure collider is properly set up */
+                                       collision_move_object(collmd, 1.0, 0.0);
+                                       BLI_addtail(objs, col);
+                               }
+                       }
+       }
+       return objs;
+}
+void free_collider_cache(ListBase **colliders)
+{
+       if(*colliders) {
+               BLI_freelistN(*colliders);
+               MEM_freeN(*colliders);
+               *colliders = NULL;
+       }
+}
 static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap)
 {
        int i;
index 608cfe03b723926e79ec0ec35fd7f3cfbb827031..a8cec6070a079719edfe35b7ed6128be4e485a25 100644 (file)
@@ -521,8 +521,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
     
        /* softbody collision  */
        if((ob->type==OB_MESH) || (ob->type==OB_CURVE) || (ob->type==OB_LATTICE))
-               if(modifiers_isSoftbodyEnabled(ob) || modifiers_isClothEnabled(ob))
-                       dag_add_collision_field_relation(dag, scene, ob, node);
+               if(modifiers_isSoftbodyEnabled(ob) || modifiers_isClothEnabled(ob) || ob->particlesystem.first)
+                       dag_add_collision_field_relation(dag, scene, ob, node); /* TODO: use effectorweight->group */
                
        if (ob->type==OB_MBALL) {
                Object *mom= find_basis_mball(scene, ob);
@@ -554,14 +554,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
        
        psys= ob->particlesystem.first;
        if(psys) {
-               ParticleEffectorCache *nec;
                GroupObject *go;
 
                for(; psys; psys=psys->next) {
                        BoidRule *rule = NULL;
                        BoidState *state = NULL;
-                       ParticleSimulationData sim = {scene, ob, psys, NULL};
                        ParticleSettings *part= psys->part;
+                       ListBase *effectors = NULL;
+                       EffectorCache *eff;
 
                        dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
 
@@ -593,33 +593,17 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
                                }
                        }
 
-                       psys_update_effectors(&sim, 0.0, 0);
+                       effectors = pdInitEffectors(scene, ob, psys, part->effector_weights);
 
-                       for(nec= psys->effectors.first; nec; nec= nec->next) {
-                               Object *ob1= nec->ob;
-
-                               if(nec->type & PSYS_EC_EFFECTOR) {
-                                       node2 = dag_get_node(dag, ob1);
-                                       if(ob1->pd->forcefield==PFIELD_GUIDE)
-                                               dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field");
-                                       else
-                                               dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Particle Field");
-                               }
-                               else if(nec->type & PSYS_EC_DEFLECT) {
-                                       node2 = dag_get_node(dag, ob1);
-                                       dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Collision");
-                               }
-                               else if(nec->type & PSYS_EC_PARTICLE) {
-                                       node2 = dag_get_node(dag, ob1);
-                                       dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Field");
-                               }
-                               
-                               if(nec->type & PSYS_EC_REACTOR) {
-                                       node2 = dag_get_node(dag, ob1);
-                                       dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Reactor");
+                       if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
+                               if(eff->psys) {
+                                       node2 = dag_get_node(dag, eff->ob);
+                                       dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field");
                                }
                        }
 
+                       pdEndEffectors(&effectors);
+
                        if(part->boids) {
                                for(state = part->boids->states.first; state; state=state->next) {
                                        for(rule = state->rules.first; rule; rule=rule->next) {
@@ -2217,7 +2201,7 @@ void DAG_id_flush_update(ID *id, short flag)
        /* set flags & pointcache for object */
        if(GS(id->name) == ID_OB) {
                ob= (Object*)id;
-               ob->recalc |= flag;
+               ob->recalc |= (flag & OB_RECALC);
                BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
 
                if(flag & OB_RECALC_DATA) {
@@ -2255,6 +2239,20 @@ void DAG_id_flush_update(ID *id, short flag)
                        }
                }
 
+               /* set flags based on particle settings */
+               if(idtype == ID_PA) {
+                       ParticleSystem *psys;
+                       for(obt=bmain->object.first; obt; obt= obt->id.next) {
+                               for(psys=obt->particlesystem.first; psys; psys=psys->next) {
+                                       if(&psys->part->id == id) {
+                                               BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
+                                               obt->recalc |= (flag & OB_RECALC);
+                                               psys->recalc |= (flag & PSYS_RECALC);
+                                       }
+                               }
+                       }
+               }
+
                /* update editors */
                dag_editors_update(bmain, id);
        }
index acf906e3163aaadb588d1d426fe2bbb9112062fc..7cc65de827aa3b51767c4e80ae8d6d630480e818 100644 (file)
 #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"
 #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
 
 //XXX #include "BIF_screen.h"
 
-PartDeflect *object_add_collision_fields(void)
+EffectorWeights *BKE_add_effector_weights(Group *group)
+{
+       EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights");
+       int i;
+
+       for(i=0; i<NUM_PFIELD_TYPES; i++)
+               weights->weight[i] = 1.0f;
+
+       weights->global_gravity = 1.0f;
+
+       weights->group = group;
+
+       return weights;
+}
+PartDeflect *object_add_collision_fields(int type)
 {
        PartDeflect *pd;
 
        pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
 
+       pd->forcefield = type;
        pd->pdef_sbdamp = 0.1f;
        pd->pdef_sbift  = 0.2f;
        pd->pdef_sboft  = 0.02f;
        pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128;
        pd->f_strength = 1.0f;
+       pd->f_damp = 1.0f;
+       pd->f_size = 1.0f;
+
+       /* set sensible defaults based on type */
+       switch(type) {
+               case PFIELD_VORTEX:
+                       pd->shape = PFIELD_SHAPE_PLANE;
+                       break;
+               case PFIELD_WIND:
+                       pd->shape = PFIELD_SHAPE_PLANE;
+                       pd->f_flow = 1.0f; /* realistic wind behavior */
+                       break;
+       }
+       pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION;
 
        return pd;
 }
@@ -156,93 +191,216 @@ void free_effects(ListBase *lb)
 }
 
 /* -------------------------- Effectors ------------------ */
+void free_partdeflect(PartDeflect *pd)
+{
+       if(!pd)
+               return;
+
+       if(pd->tex)
+               pd->tex->id.us--;
 
-static void add_to_effectorcache(ListBase *lb, Scene *scene, Object *ob, Object *obsrc)
+       if(pd->rng)
+               rng_free(pd->rng);
+
+       MEM_freeN(pd);
+}
+
+static void precalculate_effector(EffectorCache *eff)
 {
-       pEffectorCache *ec;
-       PartDeflect *pd= ob->pd;
-                       
-       if(pd->forcefield == PFIELD_GUIDE) {
-               if(ob->type==OB_CURVE && obsrc->type==OB_MESH) {        /* guides only do mesh particles */
-                       Curve *cu= ob->data;
-                       if(cu->flag & CU_PATH) {
-                               if(cu->path==NULL || cu->path->data==NULL)
-                                       makeDispListCurveTypes(scene, ob, 0);
-                               if(cu->path && cu->path->data) {
-                                       ec= MEM_callocN(sizeof(pEffectorCache), "effector cache");
-                                       ec->ob= ob;
-                                       BLI_addtail(lb, ec);
-                               }
+       unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra);
+       if(!eff->pd->rng)
+               eff->pd->rng = rng_new(eff->pd->seed + cfra);
+       else
+               rng_srandom(eff->pd->rng, eff->pd->seed + cfra);
+
+       if(eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
+               Curve *cu= eff->ob->data;
+               if(cu->flag & CU_PATH) {
+                       if(cu->path==NULL || cu->path->data==NULL)
+                               makeDispListCurveTypes(eff->scene, eff->ob, 0);
+
+                       if(cu->path && cu->path->data) {
+                               where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius);
+                               Mat4MulVecfl(eff->ob->obmat, eff->guide_loc);
+                               Mat4Mul3Vecfl(eff->ob->obmat, eff->guide_dir);
                        }
                }
        }
-       else if(pd->forcefield) {
-               
-               if(pd->forcefield == PFIELD_WIND)
-               {
-                       pd->rng = rng_new(pd->seed);
-               }
-       
-               ec= MEM_callocN(sizeof(pEffectorCache), "effector cache");
-               ec->ob= ob;
-               BLI_addtail(lb, ec);
+       else if(eff->pd->shape == PFIELD_SHAPE_SURFACE) {
+               eff->surmd = (SurfaceModifierData *)modifiers_findByType ( eff->ob, eModifierType_Surface );
+       }
+       else if(eff->psys)
+               psys_update_particle_tree(eff->psys, eff->scene->r.cfra);
+}
+static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
+{
+       EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache");
+       eff->scene = scene;
+       eff->ob = ob;
+       eff->psys = psys;
+       eff->pd = pd;
+       eff->frame = -1;
+
+       precalculate_effector(eff);
+
+       return eff;
+}
+static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src)
+{
+       EffectorCache *eff = NULL;
+
+       if( ob == ob_src || weights->weight[ob->pd->forcefield] == 0.0f )
+               return;
+
+       if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal )
+               return;
+
+       if(*effectors == NULL)
+               *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
+
+       eff = new_effector_cache(scene, ob, NULL, ob->pd);
+
+       BLI_addtail(*effectors, eff);
+}
+static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src)
+{
+       ParticleSettings *part= psys->part;
+
+       if( !psys_check_enabled(ob, psys) )
+               return;
+
+       if( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0)
+               return;
+
+       if( part->pd && part->pd->forcefield && weights->weight[part->pd->forcefield] != 0.0f) {
+               if(*effectors == NULL)
+                       *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
+
+               BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd));
+       }
+
+       if (part->pd2 && part->pd2->forcefield && weights->weight[part->pd2->forcefield] != 0.0f) {
+               if(*effectors == NULL)
+                       *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
+
+               BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2));
        }
 }
 
 /* returns ListBase handle with objects taking part in the effecting */
-ListBase *pdInitEffectors(Scene *scene, Object *obsrc, Group *group)
+ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, EffectorWeights *weights)
 {
-       static ListBase listb={NULL, NULL};
-       pEffectorCache *ec;
        Base *base;
-       unsigned int layer= obsrc->lay;
+       unsigned int layer= ob_src->lay;
+       ListBase *effectors = NULL;
        
-       if(group) {
+       if(weights->group) {
                GroupObject *go;
                
-               for(go= group->gobject.first; go; go= go->next) {
-                       if( (go->ob->lay & layer) && go->ob->pd && go->ob!=obsrc) {
-                               add_to_effectorcache(&listb, scene, go->ob, obsrc);
+               for(go= weights->group->gobject.first; go; go= go->next) {
+                       if( (go->ob->lay & layer) ) {
+                               if( go->ob->pd && go->ob->pd->forcefield )
+                                       add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src);
+
+                               if( go->ob->particlesystem.first ) {
+                                       ParticleSystem *psys= go->ob->particlesystem.first;
+
+                                       for( ; psys; psys=psys->next )
+                                               add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src);
+                               }
                        }
                }
        }
        else {
                for(base = scene->base.first; base; base= base->next) {
-                       if( (base->lay & layer) && base->object->pd && base->object!=obsrc) {
-                               add_to_effectorcache(&listb, scene, base->object, obsrc);
+                       if( (base->lay & layer) ) {
+                               if( base->object->pd && base->object->pd->forcefield )
+                               add_object_to_effectors(&effectors, scene, weights, base->object, ob_src);
+
+                               if( base->object->particlesystem.first ) {
+                                       ParticleSystem *psys= base->object->particlesystem.first;
+
+                                       for( ; psys; psys=psys->next )
+                                               add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src);
+                               }
                        }
                }
        }
-       
-       /* make a full copy */
-       for(ec= listb.first; ec; ec= ec->next) {
-               ec->obcopy= *(ec->ob);
-       }
-
-       if(listb.first)
-               return &listb;
-       
-       return NULL;
+       return effectors;
 }
 
-void pdEndEffectors(ListBase *lb)
+void pdEndEffectors(ListBase **effectors)
 {
-       if(lb) {
-               pEffectorCache *ec;
-               /* restore full copy */
-               for(ec= lb->first; ec; ec= ec->next)
-               {
-                       if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND))
-                               rng_free(ec->ob->pd->rng);
-                       
-                       *(ec->ob)= ec->obcopy;
+       if(*effectors) {
+               EffectorCache *eff = (*effectors)->first;
+
+               for(; eff; eff=eff->next) {
+                       if(eff->guide_data)
+                               MEM_freeN(eff->guide_data);
                }
 
-               BLI_freelistN(lb);
+               BLI_freelistN(*effectors);
+               MEM_freeN(*effectors);
+               *effectors = NULL;
        }
 }
 
 
+void pd_point_from_particle(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, EffectedPoint *point)
+{
+       point->loc = state->co;
+       point->vel = state->vel;
+       point->index = pa - sim->psys->particles;
+       point->size = pa->size;
+       /* TODO: point->charge */
+       point->charge = 1.0f;
+
+       point->vel_to_sec = 1.0f;
+       point->vel_to_frame = psys_get_timestep(sim);
+
+       point->flag = 0;
+
+       if(sim->psys->part->flag & PART_ROT_DYN) {
+               point->ave = state->ave;
+               point->rot = state->rot;
+       }
+       else
+               point->ave = point->rot = NULL;
+
+       point->psys = sim->psys;
+}
+
+void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
+{
+       point->loc = loc;
+       point->vel = vel;
+       point->index = index;
+       point->size = 0.0f;
+
+       point->vel_to_sec = (float)scene->r.frs_sec;
+       point->vel_to_frame = 1.0f;
+
+       point->flag = 0;
+
+       point->ave = point->rot = NULL;
+       point->psys = NULL;
+}
+void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
+{
+       point->loc = loc;
+       point->vel = vel;
+       point->index = index;
+       point->size = 0.0f;
+
+       point->vel_to_sec = (float)scene->r.frs_sec;
+       point->vel_to_frame = 1.0f;
+
+       point->flag = PE_WIND_AS_SPEED;
+
+       point->ave = point->rot = NULL;
+
+       point->psys = NULL;
+}
 /************************************************/
 /*                     Effectors               */
 /************************************************/
@@ -256,27 +414,33 @@ static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BV
 }
 
 // get visibility of a wind ray
-static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir)
+static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, EffectorData *efd, EffectedPoint *point)
 {
-       Object **collobjs = NULL;
-       int numcollobj = 0, i;
+       ListBase *colls = colliders;
+       ColliderCache *col;
        float norm[3], len = 0.0;
        float visibility = 1.0, absorption = 0.0;
        
-       collobjs = get_collisionobjects(scene, ob, &numcollobj);
-       
-       if(!collobjs)
-               return 0;
+       if(!(eff->pd->flag & PFIELD_VISIBILITY))
+               return visibility;
+
+       if(!colls)
+               colls = get_collider_cache(eff->scene, NULL);
+
+       if(!colls)
+               return visibility;
        
-       VECCOPY(norm, dir);
+       VECCOPY(norm, efd->vec_to_point);
        VecNegf(norm);
        len = Normalize(norm);
        
        // check all collision objects
-       for(i = 0; i < numcollobj; i++)
+       for(col = colls->first; col; col = col->next)
        {
-               Object *collob= collobjs[i];
-               CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision);
+               CollisionModifierData *collmd = col->collmd;
+
+               if(col->ob == eff->ob)
+                       continue;
                
                if(collmd->bvhtree)
                {
@@ -286,9 +450,9 @@ static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir
                        hit.dist = len + FLT_EPSILON;
                        
                        // check if the way is blocked
-                       if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0)
+                       if(BLI_bvhtree_ray_cast(collmd->bvhtree, point->loc, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0)
                        {
-                               absorption= (collob->pd)? collob->pd->absorption: 0.0f;
+                               absorption= col->ob->pd->absorption;
 
                                // visibility is only between 0 and 1, calculated from 1-absorption
                                visibility *= CLAMPIS(1.0f-absorption, 0.0f, 1.0f);
@@ -298,8 +462,9 @@ static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir
                        }
                }
        }
-       
-       MEM_freeN(collobjs);
+
+       if(!colliders)
+               free_collider_cache(&colls);
        
        return visibility;
 }
@@ -347,43 +512,39 @@ static float falloff_func_rad(PartDeflect *pd, float fac)
        return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r);
 }
 
-float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
+float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, EffectorWeights *weights)
 {
-       float eff_dir[3], temp[3];
-       float falloff=1.0, fac, r_fac;
-
-       if(pd->forcefield==PFIELD_LENNARDJ)
-               return falloff; /* Lennard-Jones field has it's own falloff built in */
+       float temp[3];
+       float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f;
+       float fac, r_fac;
 
-       VecCopyf(eff_dir,eff_velocity);
-       Normalize(eff_dir);
+       fac = Inpf(efd->nor, efd->vec_to_point);
 
-       if(pd->flag & PFIELD_POSZ && Inpf(eff_dir,vec_to_part)<0.0f)
+       if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f)
                falloff=0.0f;
-       else switch(pd->falloff){
+       else if(eff->pd->zdir == PFIELD_Z_NEG && fac > 0.0f)
+               falloff=0.0f;
+       else switch(eff->pd->falloff){
                case PFIELD_FALL_SPHERE:
-                       fac=VecLength(vec_to_part);
-                       falloff= falloff_func_dist(pd, fac);
+                       falloff*= falloff_func_dist(eff->pd, efd->distance);
                        break;
 
                case PFIELD_FALL_TUBE:
-                       fac=Inpf(vec_to_part,eff_dir);
-                       falloff= falloff_func_dist(pd, ABS(fac));
+                       falloff*= falloff_func_dist(eff->pd, ABS(fac));
                        if(falloff == 0.0f)
                                break;
 
-                       VECADDFAC(temp,vec_to_part,eff_dir,-fac);
-                       r_fac=VecLength(temp);
-                       falloff*= falloff_func_rad(pd, r_fac);
+                       VECADDFAC(temp, efd->vec_to_point, efd->nor, -fac);
+                       r_fac= VecLength(temp);
+                       falloff*= falloff_func_rad(eff->pd, r_fac);
                        break;
                case PFIELD_FALL_CONE:
-                       fac=Inpf(vec_to_part,eff_dir);
-                       falloff= falloff_func_dist(pd, ABS(fac));
+                       falloff*= falloff_func_dist(eff->pd, ABS(fac));
                        if(falloff == 0.0f)
                                break;
 
-                       r_fac=saacos(fac/VecLength(vec_to_part))*180.0f/(float)M_PI;
-                       falloff*= falloff_func_rad(pd, r_fac);
+                       r_fac=saacos(fac/VecLength(efd->vec_to_point))*180.0f/(float)M_PI;
+                       falloff*= falloff_func_rad(eff->pd, r_fac);
 
                        break;
        }
@@ -391,127 +552,391 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
        return falloff;
 }
 
-void do_physical_effector(Scene *scene, Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size)
+int closest_point_on_surface(SurfaceModifierData *surmd, float *co, float *surface_co, float *surface_nor, float *surface_vel)
 {
-       float mag_vec[3]={0,0,0};
-       float temp[3], temp2[3];
-       float eff_vel[3];
-       float noise = 0, visibility;
-       
-       // calculate visibility
-       visibility = eff_calc_visibility(scene, ob, opco, vec_to_part);
-       if(visibility <= 0.0)
-               return;
-       falloff *= visibility;
+       BVHTreeNearest nearest;
 
-       VecCopyf(eff_vel,eff_velocity);
-       Normalize(eff_vel);
+       nearest.index = -1;
+       nearest.dist = FLT_MAX;
 
-       switch(type){
-               case PFIELD_WIND:
-                       VECCOPY(mag_vec,eff_vel);
-                       
-                       // add wind noise here, only if we have wind
-                       if((noise_factor > 0.0f) && (force_val > FLT_EPSILON))
-                               noise = wind_func(rng, noise_factor);
+       BLI_bvhtree_find_nearest(surmd->bvhtree->tree, co, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree);
+
+       if(nearest.index != -1) {
+               VECCOPY(surface_co, nearest.co);
+
+               if(surface_nor) {
+                       VECCOPY(surface_nor, nearest.no);
+               }
+
+               if(surface_vel) {
+                       MFace *mface = CDDM_get_face(surmd->dm, nearest.index);
                        
-                       VecMulf(mag_vec,(force_val+noise)*falloff);
-                       VecAddf(field,field,mag_vec);
-                       break;
+                       VECCOPY(surface_vel, surmd->v[mface->v1].co);
+                       VecAddf(surface_vel, surface_vel, surmd->v[mface->v2].co);
+                       VecAddf(surface_vel, surface_vel, surmd->v[mface->v3].co);
+                       if(mface->v4)
+                               VecAddf(surface_vel, surface_vel, surmd->v[mface->v4].co);
 
-               case PFIELD_FORCE:
-                       if(planar)
-                               Projf(mag_vec,vec_to_part,eff_vel);
-                       else
-                               VecCopyf(mag_vec,vec_to_part);
+                       VecMulf(surface_vel, mface->v4 ? 0.25f : 0.333f);
+               }
+               return 1;
+       }
 
-                       Normalize(mag_vec);
+       return 0;
+}
+int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int real_velocity)
+{
+       float cfra = eff->scene->r.cfra;
+       int ret = 0;
 
-                       VecMulf(mag_vec,force_val*falloff);
-                       VecAddf(field,field,mag_vec);
-                       break;
+       if(eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) {
+               /* closest point in the object surface is an effector */
+               float vec[3];
 
-               case PFIELD_VORTEX:
-                       Crossf(mag_vec,eff_vel,vec_to_part);
+               /* using velocity corrected location allows for easier sliding over effector surface */
+               VecCopyf(vec, point->vel);
+               VecMulf(vec, point->vel_to_frame);
+               VecAddf(vec, vec, point->loc);
 
-                       Normalize(mag_vec);
+               ret = closest_point_on_surface(eff->surmd, vec, efd->loc, efd->nor, real_velocity ? efd->vel : NULL);
 
-                       VecMulf(mag_vec,force_val*distance*falloff);
-                       VecAddf(field,field,mag_vec);
+               efd->size = 0.0f;
+       }
+       else if(eff->pd->shape==PFIELD_SHAPE_POINTS) {
 
-                       break;
-               case PFIELD_MAGNET:
-                       if(planar)
-                               VecCopyf(temp,eff_vel);
-                       else
-                               /* magnetic field of a moving charge */
-                               Crossf(temp,eff_vel,vec_to_part);
+               if(eff->ob->derivedFinal) {
+                       DerivedMesh *dm = eff->ob->derivedFinal;
 
-                       Normalize(temp);
+                       dm->getVertCo(dm, *efd->index, efd->loc);
+                       dm->getVertNo(dm, *efd->index, efd->nor);
 
-                       Crossf(temp2,velocity,temp);
-                       VecAddf(mag_vec,mag_vec,temp2);
+                       Mat4MulVecfl(eff->ob->obmat, efd->loc);
+                       Mat4Mul3Vecfl(eff->ob->obmat, efd->nor);
 
-                       VecMulf(mag_vec,force_val*falloff);
-                       VecAddf(field,field,mag_vec);
-                       break;
-               case PFIELD_HARMONIC:
-                       if(planar)
-                               Projf(mag_vec,vec_to_part,eff_vel);
-                       else
-                               VecCopyf(mag_vec,vec_to_part);
+                       Normalize(efd->nor);
 
-                       VecMulf(mag_vec,force_val*falloff);
-                       VecSubf(field,field,mag_vec);
+                       efd->size = 0.0f;
 
-                       VecCopyf(mag_vec,velocity);
-                       VecMulf(mag_vec,damp*2.0f*(float)sqrt(force_val));
-                       VecSubf(field,field,mag_vec);
-                       break;
-               case PFIELD_CHARGE:
-                       if(planar)
-                               Projf(mag_vec,vec_to_part,eff_vel);
-                       else
-                               VecCopyf(mag_vec,vec_to_part);
+                       /**/
+                       ret = 1;
+               }
+       }
+       else if(eff->psys) {
+               ParticleSimulationData sim = {eff->scene, eff->ob, eff->psys, NULL, NULL};
+               ParticleData *pa = eff->psys->particles + *efd->index;
+               ParticleKey state;
+
+               /* exclude the particle itself for self effecting particles */
+               if(eff->psys == point->psys && *efd->index == point->index)
+                       ;
+               else {
+                       /* TODO: time from actual previous calculated frame (step might not be 1) */
+                       state.time = cfra - 1.0;
+                       ret = psys_get_particle_state(&sim, *efd->index, &state, 0);
+
+                       /* TODO */
+                       //if(eff->pd->forcefiled == PFIELD_HARMONIC && ret==0) {
+                       //      if(pa->dietime < eff->psys->cfra)
+                       //              eff->flag |= PE_VELOCITY_TO_IMPULSE;
+                       //}
+
+                       VECCOPY(efd->loc, state.co);
+                       VECCOPY(efd->nor, state.vel);
+                       if(real_velocity) {
+                               VECCOPY(efd->vel, state.vel);
+                       }
 
-                       Normalize(mag_vec);
+                       efd->size = pa->size;
+               }
+       }
+       else {
+               /* use center of object for distance calculus */
+               Object *ob = eff->ob;
+               Object obcopy = *ob;
+
+               where_is_object_time(eff->scene, ob, cfra);
+
+               /* use z-axis as normal*/
+               VECCOPY(efd->nor, ob->obmat[2]);
+               Normalize(efd->nor);
+
+               /* for vortex the shape chooses between old / new force */
+               if(eff->pd->shape == PFIELD_SHAPE_PLANE) {
+                       /* efd->loc is closes point on effector xy-plane */
+                       float temp[3];
+                       VecSubf(temp, point->loc, ob->obmat[3]);
+                       Projf(efd->loc, temp, efd->nor);
+                       VecSubf(efd->loc, point->loc, efd->loc);
+               }
+               else {
+                       VECCOPY(efd->loc, ob->obmat[3]);
+               }
 
-                       VecMulf(mag_vec,charge*force_val*falloff);
-                       VecAddf(field,field,mag_vec);
-                       break;
-               case PFIELD_LENNARDJ:
-               {
-                       float fac;
+               if(real_velocity) {
+                       VECCOPY(efd->vel, ob->obmat[3]);
+
+                       where_is_object_time(eff->scene, ob, cfra - 1.0);
+
+                       VecSubf(efd->vel, efd->vel, ob->obmat[3]);
+               }
+
+               *eff->ob = obcopy;
+
+               efd->size = 0.0f;
+
+               ret = 1;
+       }
+
+       if(ret) {
+               VecSubf(efd->vec_to_point, point->loc, efd->loc);
+               efd->distance = VecLength(efd->vec_to_point);
+
+               /* for some effectors we need the object center every time */
+               VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]);
+               VECCOPY(efd->nor2, eff->ob->obmat[2]);
+               Normalize(efd->nor2);
+       }
+
+       return ret;
+}
+static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p)
+{
+       if(eff->pd->shape == PFIELD_SHAPE_POINTS) {
+               efd->index = p;
+
+               *p = 0;
+               *tot = eff->ob->derivedFinal ? eff->ob->derivedFinal->numVertData : 1;
+
+               if(*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) {
+                       *p = point->index % *tot;
+                       *tot = *p+1;
+               }
+       }
+       else if(eff->psys) {
+               efd->index = p;
+
+               *p = 0;
+               *tot = eff->psys->totpart;
+               
+               if(eff->pd->forcefield == PFIELD_CHARGE) {
+                       /* Only the charge of the effected particle is used for 
+                       interaction, not fall-offs. If the fall-offs aren't the 
+                       same this will be unphysical, but for animation this            
+                       could be the wanted behavior. If you want physical
+                       correctness the fall-off should be spherical 2.0 anyways.
+                       */
+                       efd->charge = eff->pd->f_strength;
+               }
+               else if(eff->pd->forcefield == PFIELD_HARMONIC) {
+                       /* every particle is mapped to only one harmonic effector particle */
+                       *p= point->index % eff->psys->totpart;
+                       *tot= *p + 1;
+               }
+       }
+       else {
+               *p = 0;
+               *tot = 1;
+       }
+}
+static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force)
+{
+       TexResult result[4];
+       float tex_co[3], strength, force[3];
+       float nabla = eff->pd->tex_nabla;
+       int hasrgb;
+       short mode = eff->pd->tex_mode;
+
+       if(!eff->pd->tex)
+               return;
+
+       result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0;
+
+       strength= eff->pd->f_strength * efd->falloff;
+
+       VECCOPY(tex_co,point->loc);
+
+       if(eff->pd->flag & PFIELD_TEX_2D) {
+               float fac=-Inpf(tex_co, efd->nor);
+               VECADDFAC(tex_co, tex_co, efd->nor, fac);
+       }
+
+       if(eff->pd->flag & PFIELD_TEX_OBJECT) {
+               Mat4Mul3Vecfl(eff->ob->obmat, tex_co);
+       }
+
+       hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL,NULL, 1, result);
+
+       if(hasrgb && mode==PFIELD_TEX_RGB) {
+               force[0] = (0.5f - result->tr) * strength;
+               force[1] = (0.5f - result->tg) * strength;
+               force[2] = (0.5f - result->tb) * strength;
+       }
+       else {
+               strength/=nabla;
+
+               tex_co[0] += nabla;
+               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 1, result+1);
+
+               tex_co[0] -= nabla;
+               tex_co[1] += nabla;
+               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 1, result+2);
 
-                       if(planar) {
-                               Projf(mag_vec,vec_to_part,eff_vel);
-                               distance = VecLength(mag_vec);
+               tex_co[1] -= nabla;
+               tex_co[2] += nabla;
+               multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 1, result+3);
+
+               if(mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we dont have rgb fall back to grad */
+                       force[0] = (result[0].tin - result[1].tin) * strength;
+                       force[1] = (result[0].tin - result[2].tin) * strength;
+                       force[2] = (result[0].tin - result[3].tin) * strength;
+               }
+               else { /*PFIELD_TEX_CURL*/
+                       float dbdy, dgdz, drdz, dbdx, dgdx, drdy;
+
+                       dbdy = result[2].tb - result[0].tb;
+                       dgdz = result[3].tg - result[0].tg;
+                       drdz = result[3].tr - result[0].tr;
+                       dbdx = result[1].tb - result[0].tb;
+                       dgdx = result[1].tg - result[0].tg;
+                       drdy = result[2].tr - result[0].tr;
+
+                       force[0] = (dbdy - dgdz) * strength;
+                       force[1] = (drdz - dbdx) * strength;
+                       force[2] = (dgdx - drdy) * strength;
+               }
+       }
+
+       if(eff->pd->flag & PFIELD_TEX_2D){
+               float fac = -Inpf(force, efd->nor);
+               VECADDFAC(force, force, efd->nor, fac);
+       }
+
+       VecAddf(total_force, total_force, force);
+}
+void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force)
+{
+       PartDeflect *pd = eff->pd;
+       RNG *rng = pd->rng;
+       float force[3]={0,0,0};
+       float temp[3];
+       float fac;
+       float strength = pd->f_strength;
+       float damp = pd->f_damp;
+       float noise_factor = pd->f_noise;
+
+       if(noise_factor > 0.0f) {
+               strength += wind_func(rng, noise_factor);
+
+               if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG))
+                       damp += wind_func(rng, noise_factor);
+       }
+
+       VECCOPY(force, efd->vec_to_point);
+
+       switch(pd->forcefield){
+               case PFIELD_WIND:
+                       Normalize(force);
+                       strength *= (Inpf(force, efd->nor) >= 0.0f ? 1.0f : -1.0f);
+                       VecMulf(force, strength * efd->falloff);
+                       break;
+               case PFIELD_FORCE:
+                       Normalize(force);
+                       VecMulf(force, strength * efd->falloff);
+                       break;
+               case PFIELD_VORTEX:
+                       /* old vortex force */
+                       if(pd->shape == PFIELD_SHAPE_POINT) {
+                               Crossf(force, efd->nor, efd->vec_to_point);
+                               Normalize(force);
+                               VecMulf(force, strength * efd->distance * efd->falloff);
                        }
+                       else {
+                               /* new vortex force */
+                               Crossf(temp, efd->nor2, efd->vec_to_point2);
+                               VecMulf(temp, strength * efd->falloff);
+                               
+                               Crossf(force, efd->nor2, temp);
+                               VecMulf(force, strength * efd->falloff);
+                               
+                               VECADDFAC(temp, temp, point->vel, -point->vel_to_sec);
+                               VecAddf(force, force, temp);
+                       }
+                       break;
+               case PFIELD_MAGNET:
+                       if(eff->pd->shape == PFIELD_SHAPE_POINT)
+                               /* magnetic field of a moving charge */
+                               Crossf(temp, efd->nor, efd->vec_to_point);
                        else
-                               VecCopyf(mag_vec,vec_to_part);
-
-                       /* at this distance the field is 60 times weaker than maximum */
-                       if(distance > 2.22 * (size+pa_size))
-                               break;
+                               VecCopyf(temp, efd->nor);
 
-                       fac = pow((size+pa_size)/distance,6.0);
+                       Normalize(temp);
+                       VecMulf(temp, strength * efd->falloff);
+                       Crossf(force, point->vel, temp);
+                       VecMulf(force, point->vel_to_sec);
+                       break;
+               case PFIELD_HARMONIC:
+                       VecMulf(force, -strength * efd->falloff);
+                       VecCopyf(temp, point->vel);
+                       VecMulf(temp, -damp * 2.0f * (float)sqrt(fabs(strength)) * point->vel_to_sec);
+                       VecAddf(force, force, temp);
+                       break;
+               case PFIELD_CHARGE:
+                       VecMulf(force, point->charge * strength * efd->falloff);
+                       break;
+               case PFIELD_LENNARDJ:
+                       fac = pow((efd->size + point->size) / efd->distance, 6.0);
                        
-                       fac = - fac * (1.0 - fac) / distance;
+                       fac = - fac * (1.0 - fac) / efd->distance;
 
                        /* limit the repulsive term drastically to avoid huge forces */
                        fac = ((fac>2.0) ? 2.0 : fac);
 
-                       /* 0.003715 is the fac value at 2.22 times (size+pa_size),
-                          substracted to avoid discontinuity at the border
-                       */
-                       VecMulf(mag_vec, force_val * (fac-0.0037315));
-                       VecAddf(field,field,mag_vec);
+                       VecMulf(force, strength * fac);
                        break;
-               }
                case PFIELD_BOID:
                        /* Boid field is handled completely in boids code. */
+                       return;
+               case PFIELD_TURBULENCE:
+                       if(pd->flag & PFIELD_GLOBAL_CO) {
+                               VECCOPY(temp, point->loc);
+                       }
+                       else {
+                               VECADD(temp, efd->vec_to_point2, efd->nor2);
+                       }
+                       force[0] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[0], temp[1], temp[2], 2,0,2);
+                       force[1] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[1], temp[2], temp[0], 2,0,2);
+                       force[2] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[2], temp[0], temp[1], 2,0,2);
+                       VecMulf(force, strength * efd->falloff);
+                       break;
+               case PFIELD_DRAG:
+                       VECCOPY(force, point->vel);
+                       fac = Normalize(force) * point->vel_to_sec;
+
+                       strength = MIN2(strength, 2.0f);
+                       damp = MIN2(damp, 2.0f);
+
+                       VecMulf(force, -efd->falloff * fac * (strength * fac + damp));
                        break;
        }
+
+       if(pd->flag & PFIELD_DO_LOCATION) {
+               VECADDFAC(total_force, total_force, force, 1.0f/point->vel_to_sec);
+
+               if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)==0 && pd->f_flow != 0.0f) {
+                       VECADDFAC(total_force, total_force, point->vel, -pd->f_flow * efd->falloff);
+               }
+       }
+
+       if(pd->flag & PFIELD_DO_ROTATION && point->ave && point->rot) {
+               float xvec[3] = {1.0f, 0.0f, 0.0f};
+               float dave[3];
+               QuatMulVecf(point->rot, xvec);
+               Crossf(dave, xvec, force);
+               if(pd->f_flow != 0.0f) {
+                       VECADDFAC(dave, dave, point->ave, -pd->f_flow * efd->falloff);
+               }
+               VecAddf(point->ave, point->ave, dave);
+       }
 }
 
 /*  -------- pdDoEffectors() --------
@@ -528,7 +953,7 @@ void do_physical_effector(Scene *scene, Object *ob, float *opco, short type, flo
        guide           = old speed of particle
 
 */
-void pdDoEffectors(Scene *scene, ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags)
+void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse)
 {
 /*
        Modifies the force on a particle according to its
@@ -543,43 +968,45 @@ void pdDoEffectors(Scene *scene, ListBase *lb, float *opco, float *force, float
                (particles are guided along a curve bezier or old nurbs)
                (is independent of other effectors)
 */
-       Object *ob;
-       pEffectorCache *ec;
-       PartDeflect *pd;
-       
-       float distance, vec_to_part[3];
-       float falloff;
+       EffectorCache *eff;
+       EffectorData efd;
+       int p=0, tot = 1;
 
        /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
        /* Check for min distance here? (yes would be cool to add that, ton) */
        
-       for(ec = lb->first; ec; ec= ec->next) {
+       if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
                /* object effectors were fully checked to be OK to evaluate! */
-               ob= ec->ob;
-               pd= ob->pd;
-                       
-               /* Get IPO force strength and fall off values here */
-               where_is_object_time(scene, ob, cur_time);
-                       
-               /* use center of object for distance calculus */
-               VecSubf(vec_to_part, opco, ob->obmat[3]);
-               distance = VecLength(vec_to_part);
 
-               falloff=effector_falloff(pd,ob->obmat[2],vec_to_part);          
-               
-               if(falloff<=0.0f)
-                       ;       /* don't do anything */
-               else {
-                       float field[3]={0,0,0}, tmp[3];
-                       VECCOPY(field, force);
-                       do_physical_effector(scene, ob, opco, pd->forcefield,pd->f_strength,distance,
-                                                               falloff, pd->f_dist, pd->f_damp, ob->obmat[2], vec_to_part,
-                                                               speed,force, pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise, 0.0f, 0.0f);
-                       
-                       // for softbody backward compatibility
-                       if(flags & PE_WIND_AS_SPEED){
-                               VECSUB(tmp, force, field);
-                               VECSUB(speed, speed, tmp);
+               get_effector_tot(eff, &efd, point, &tot, &p);
+
+               for(; p<tot; p++) {
+                       if(get_effector_data(eff, &efd, point, 0)) {
+                               efd.falloff= effector_falloff(eff, &efd, point, weights);
+                               
+                               if(efd.falloff > 0.0f)
+                                       efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point);
+
+                               if(efd.falloff <= 0.0f)
+                                       ;       /* don't do anything */
+                               else if(eff->pd->forcefield == PFIELD_TEXTURE)
+                                       do_texture_effector(eff, &efd, point, force);
+                               else {
+                                       float temp1[3]={0,0,0}, temp2[3];
+                                       VECCOPY(temp1, force);
+
+                                       do_physical_effector(eff, &efd, point, force);
+                                       
+                                       // for softbody backward compatibility
+                                       if(point->flag & PE_WIND_AS_SPEED && impulse){
+                                               VECSUB(temp2, force, temp1);
+                                               VECSUB(impulse, impulse, temp2);
+                                       }
+                               }
+                       }
+                       else if(eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) {
+                               /* special case for harmonic effector */
+                               VECADD(impulse, impulse, efd.vel);
                        }
                }
        }
index ae2acd6aef7da0d11868a2dc8082c4889bcd4b45..de215ae4af913eafb191606fa79005542ce53f01 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "DNA_cloth_types.h"   
 #include "DNA_scene_types.h"
+#include "DNA_object_force.h"
 
 #include "BKE_effect.h"
 #include "BKE_global.h"
@@ -1482,15 +1483,19 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF,
        Cloth           *cloth          = clmd->clothObject;
        int             i               = 0;
        float           spring_air      = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */
-       float           gravity[3];
+       float           gravity[3] = {0.0f, 0.0f, 0.0f};
        float           tm2[3][3]       = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}};
        MFace           *mfaces         = cloth->mfaces;
        unsigned int numverts = cloth->numverts;
        LinkNode *search = cloth->springs;
        lfVector *winvec;
+       EffectedPoint epoint;
 
-       VECCOPY(gravity, clmd->sim_parms->gravity);
-       mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */
+       /* global acceleration (gravitation) */
+       if(clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+               VECCOPY(gravity, clmd->scene->physics_settings.gravity);
+               mul_fvector_S(gravity, gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity); /* scale gravity force */
+       }
 
        /* set dFdX jacobi matrix to zero */
        init_bfmatrix(dFdX, ZERO);
@@ -1525,10 +1530,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF,
                
                // precalculate wind forces
                for(i = 0; i < cloth->numverts; i++)
-               {
-                       float speed[3] = {0.0f, 0.0f,0.0f};
-                       
-                       pdDoEffectors(clmd->scene, effectors, lX[i], winvec[i], speed, frame, 0.0f, 0);
+               {       
+                       pd_point_from_loc(clmd->scene, (float*)lX[i], (float*)lV[i], i, &epoint);
+                       pdDoEffectors(effectors, NULL, clmd->sim_parms->effector_weights, &epoint, winvec[i], NULL);
                }
                
                for(i = 0; i < cloth->numfaces; i++)
@@ -1656,9 +1660,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
        while(step < tf)
        {       
                // calculate forces
-               effectors= pdInitEffectors(clmd->scene, ob, NULL);
                cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M);
-               if(effectors) pdEndEffectors(effectors);
                
                // calculate new velocity
                simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
@@ -1741,9 +1743,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
                                cp_lfvector(id->V, id->Vnew, numverts);
                                
                                // calculate 
-                               effectors= pdInitEffectors(clmd->scene, ob, NULL);
                                cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step+dt, id->M);      
-                               if(effectors) pdEndEffectors(effectors);
                                
                                simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
                        }
index b9b9ea6b4f39382c403b845a91fdd0bd1491f0fe..3b47c2f18305a2c8c0d8ad263e349a2f372f3661 100644 (file)
@@ -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);    
                
index 4c72984574543ce85ad38c89e7e510111b02b80e..579466ea6266dfdde7e52bc5ed20091f64942c08 100644 (file)
@@ -91,6 +91,7 @@
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
+#include "BKE_effect.h"
 #include "BKE_fcurve.h"
 #include "BKE_group.h"
 #include "BKE_icons.h"
@@ -298,11 +299,8 @@ void free_object(Object *ob)
        
        free_constraints(&ob->constraints);
        
-       if(ob->pd){
-               if(ob->pd->tex)
-                       ob->pd->tex->id.us--;
-               MEM_freeN(ob->pd);
-       }
+       free_partdeflect(ob->pd);
+
        if(ob->soft) sbFree(ob->soft);
        if(ob->bsoft) bsbFree(ob->bsoft);
        if(ob->gpulamp.first) GPU_lamp_free(ob);
@@ -1069,6 +1067,9 @@ SoftBody *copy_softbody(SoftBody *sb)
 
        sbn->pointcache= BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches);
 
+       if(sb->effector_weights)
+               sbn->effector_weights = MEM_dupallocN(sb->effector_weights);
+
        return sbn;
 }
 
@@ -1129,11 +1130,9 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
        psysn->pathcache= NULL;
        psysn->childcache= NULL;
        psysn->edit= NULL;
-       psysn->effectors.first= psysn->effectors.last= 0;
        
        psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL;
        psysn->childcachebufs.first = psysn->childcachebufs.last = NULL;
-       psysn->reactevents.first = psysn->reactevents.last = NULL;
        psysn->renderdata = NULL;
        
        psysn->pointcache= BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches);
@@ -1278,6 +1277,8 @@ Object *copy_object(Object *ob)
                obn->pd= MEM_dupallocN(ob->pd);
                if(obn->pd->tex)
                        id_us_plus(&(obn->pd->tex->id));
+               if(obn->pd->rng)
+                       obn->pd->rng = MEM_dupallocN(ob->pd->rng);
        }
        obn->soft= copy_softbody(ob->soft);
        obn->bsoft = copy_bulletsoftbody(ob->bsoft);
index e18e7f54e4981d06c9aa4db602280d701b5f5250..e63b77a134e0b3c66d4439a929a7f5b5da512e55 100644 (file)
@@ -53,7 +53,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_dynstr.h"
 #include "BLI_kdtree.h"
-#include "BLI_linklist.h"
+#include "BLI_listbase.h"
 #include "BLI_rand.h"
 #include "BLI_threads.h"
 
@@ -61,6 +61,7 @@
 
 #include "BKE_boids.h"
 #include "BKE_cloth.h"
+#include "BKE_effect.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_lattice.h"
@@ -96,8 +97,7 @@ int count_particles(ParticleSystem *psys){
        int tot=0;
 
        LOOP_SHOWN_PARTICLES {
-               if(pa->alive == PARS_KILLED);
-               else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
+               if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
                else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
                else tot++;
        }
@@ -109,8 +109,7 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){
        int tot=0;
 
        LOOP_SHOWN_PARTICLES {
-               if(pa->alive == PARS_KILLED);
-               else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
+               if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
                else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
                else if(p%totgr==cur) tot++;
        }
@@ -302,15 +301,11 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
 /************************************************/
 void psys_free_settings(ParticleSettings *part)
 {
-       if(part->pd) {
-               MEM_freeN(part->pd);
-               part->pd = NULL;
-       }
-       
-       if(part->pd2) {
-               MEM_freeN(part->pd2);
-               part->pd2 = NULL;
-       }
+       free_partdeflect(part->pd);
+       free_partdeflect(part->pd2);
+
+       if(part->effector_weights)
+               MEM_freeN(part->effector_weights);
 
        boid_free_settings(part->boids);
 }
@@ -428,21 +423,23 @@ void psys_free_particles(ParticleSystem *psys)
 }
 void psys_free_pdd(ParticleSystem *psys)
 {
-       if(psys->pdd->cdata)
-               MEM_freeN(psys->pdd->cdata);
-       psys->pdd->cdata = NULL;
+       if(psys->pdd) {
+               if(psys->pdd->cdata)
+                       MEM_freeN(psys->pdd->cdata);
+               psys->pdd->cdata = NULL;
 
-       if(psys->pdd->vdata)
-               MEM_freeN(psys->pdd->vdata);
-       psys->pdd->vdata = NULL;
+               if(psys->pdd->vdata)
+                       MEM_freeN(psys->pdd->vdata);
+               psys->pdd->vdata = NULL;
 
-       if(psys->pdd->ndata)
-               MEM_freeN(psys->pdd->ndata);
-       psys->pdd->ndata = NULL;
+               if(psys->pdd->ndata)
+                       MEM_freeN(psys->pdd->ndata);
+               psys->pdd->ndata = NULL;
 
-       if(psys->pdd->vedata)
-               MEM_freeN(psys->pdd->vedata);
-       psys->pdd->vedata = NULL;
+               if(psys->pdd->vedata)
+                       MEM_freeN(psys->pdd->vedata);
+               psys->pdd->vedata = NULL;
+       }
 }
 /* free everything */
 void psys_free(Object *ob, ParticleSystem * psys)
@@ -465,9 +462,6 @@ void psys_free(Object *ob, ParticleSystem * psys)
                        psys->child = 0;
                        psys->totchild = 0;
                }
-
-               if(psys->effectors.first)
-                       psys_end_effectors(psys);
                
                // check if we are last non-visible particle system
                for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){
@@ -493,10 +487,11 @@ void psys_free(Object *ob, ParticleSystem * psys)
                psys->pointcache = NULL;
                
                BLI_freelistN(&psys->targets);
-               BLI_freelistN(&psys->reactevents);
 
                BLI_kdtree_free(psys->tree);
 
+               pdEndEffectors(&psys->effectors);
+
                if(psys->frand)
                        MEM_freeN(psys->frand);
 
@@ -1896,124 +1891,135 @@ static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clu
                VecLerpf(state->co,state->co,par->co,clump);
        }
 }
+void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
+{
+       EffectedPoint point;
+       ParticleKey state;
+       EffectorData efd;
+       EffectorCache *eff;
+       ParticleSystem *psys = sim->psys;
+       EffectorWeights *weights = sim->psys->part->effector_weights;
+       GuideEffectorData *data;
+       PARTICLE_P;
+
+       if(!effectors)
+               return;
+
+       LOOP_PARTICLES {
+               psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,state.co,0,0,0,0,0);
+               pd_point_from_particle(sim, pa, &state, &point);
+
+               for(eff = effectors->first; eff; eff=eff->next) {
+                       if(eff->pd->forcefield != PFIELD_GUIDE)
+                               continue;
 
-int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase *lb)
+                       if(!eff->guide_data)
+                               eff->guide_data = MEM_callocN(sizeof(GuideEffectorData)*psys->totpart, "GuideEffectorData");
+
+                       data = eff->guide_data + p;
+
+                       VECSUB(efd.vec_to_point, state.co, eff->guide_loc);
+                       VECCOPY(efd.nor, eff->guide_dir);
+                       efd.distance = VecLength(efd.vec_to_point);
+
+                       VECCOPY(data->vec_to_point, efd.vec_to_point);
+                       data->strength = effector_falloff(eff, &efd, &point, weights);
+               }
+       }
+}
+int do_guides(ListBase *effectors, ParticleKey *state, int index, float time)
 {
+       EffectorCache *eff;
        PartDeflect *pd;
-       ParticleEffectorCache *ec;
-       Object *eob;
        Curve *cu;
        ParticleKey key, par;
+       GuideEffectorData *data;
 
-       float effect[3]={0.0,0.0,0.0}, distance, f_force, mindist, totforce=0.0;
-       float guidevec[4], guidedir[3], rot2[4], radius, temp[3], angle, pa_loc[3], pa_zero[3]={0.0f,0.0f,0.0f};
-       float veffect[3]={0.0,0.0,0.0}, guidetime;
+       float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
+       float guidevec[4], guidedir[3], rot2[4], temp[3];
+       float guidetime, radius, angle, totstrength = 0.0f;
+       float vec_to_point[3];
 
-       effect[0]=effect[1]=effect[2]=0.0;
+       if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
+               pd = eff->pd;
 
-       if(lb->first){
-               for(ec = lb->first; ec; ec= ec->next){
-                       eob= ec->ob;
-                       if(ec->type & PSYS_EC_EFFECTOR){
-                               pd=eob->pd;
-                               if(pd->forcefield==PFIELD_GUIDE){
-                                       cu = (Curve*)eob->data;
-
-                                       distance=ec->distances[pa_num];
-                                       mindist=pd->f_strength;
+               if(pd->forcefield != PFIELD_GUIDE)
+                       continue;
 
-                                       VECCOPY(pa_loc, ec->locations+3*pa_num);
-                                       VECCOPY(pa_zero,pa_loc);
-                                       VECADD(pa_zero,pa_zero,ec->firstloc);
+               data = eff->guide_data + index;
 
-                                       guidetime=time/(1.0-pd->free_end);
+               if(data->strength <= 0.0f)
+                       continue;
 
-                                       /* WARNING: bails out with continue here */
-                                       if(((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist) || guidetime>1.0f) continue;
+               guidetime = time / (1.0 - pd->free_end);
 
-                                       if(guidetime>1.0f) continue;
+               if(guidetime>1.0f)
+                       continue;
 
-                                       /* calculate contribution factor for this guide */
-                                       f_force=1.0f;
-                                       if(distance<=mindist);
-                                       else if(pd->flag & PFIELD_USEMAX) {
-                                               if(mindist>=pd->maxdist) f_force= 0.0f;
-                                               else if(pd->f_power!=0.0f){
-                                                       f_force= 1.0f - (distance-mindist)/(pd->maxdist - mindist);
-                                                       f_force = (float)pow(f_force, pd->f_power);
-                                               }
-                                       }
-                                       else if(pd->f_power!=0.0f){
-                                               f_force= 1.0f/(1.0f + distance-mindist);
-                                               f_force = (float)pow(f_force, pd->f_power);
-                                       }
+               cu = (Curve*)eff->ob->data;
 
-                                       if(pd->flag & PFIELD_GUIDE_PATH_ADD)
-                                               where_on_path(eob, f_force*guidetime, guidevec, guidedir, NULL, &radius);
-                                       else
-                                               where_on_path(eob, guidetime, guidevec, guidedir, NULL, &radius);
+               if(pd->flag & PFIELD_GUIDE_PATH_ADD) {
+                       if(where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius)==0)
+                               return 0;
+               }
+               else {
+                       if(where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius)==0)
+                               return 0;
+               }
 
-                                       Mat4MulVecfl(ec->ob->obmat,guidevec);
-                                       Mat4Mul3Vecfl(ec->ob->obmat,guidedir);
+               Mat4MulVecfl(eff->ob->obmat, guidevec);
+               Mat4Mul3Vecfl(eff->ob->obmat, guidedir);
 
-                                       Normalize(guidedir);
+               Normalize(guidedir);
 
-                                       if(guidetime!=0.0){
-                                               /* curve direction */
-                                               Crossf(temp, ec->firstdir, guidedir);
-                                               angle=Inpf(ec->firstdir,guidedir)/(VecLength(ec->firstdir));
-                                               angle=saacos(angle);
-                                               VecRotToQuat(temp,angle,rot2);
-                                               QuatMulVecf(rot2,pa_loc);
+               VECCOPY(vec_to_point, data->vec_to_point);
 
-                                               /* curve tilt */
-                                               VecRotToQuat(guidedir,guidevec[3]-ec->firstloc[3],rot2);
-                                               QuatMulVecf(rot2,pa_loc);
+               if(guidetime != 0.0){
+                       /* curve direction */
+                       Crossf(temp, eff->guide_dir, guidedir);
+                       angle = Inpf(eff->guide_dir, guidedir)/(VecLength(eff->guide_dir));
+                       angle = saacos(angle);
+                       VecRotToQuat(temp, angle, rot2);
+                       QuatMulVecf(rot2, vec_to_point);
 
-                                               //vectoquat(guidedir, pd->kink_axis, (pd->kink_axis+1)%3, q);
-                                               //QuatMul(par.rot,rot2,q);
-                                       }
-                                       //else{
-                                       //      par.rot[0]=1.0f;
-                                       //      par.rot[1]=par.rot[2]=par.rot[3]=0.0f;
-                                       //}
-
-                                       /* curve taper */
-                                       if(cu->taperobj)
-                                               VecMulf(pa_loc, calc_taper(scene, cu->taperobj, (int)(f_force*guidetime*100.0), 100));
-
-                                       else{ /* curve size*/
-                                               if(cu->flag & CU_PATH_RADIUS) {
-                                                       VecMulf(pa_loc, radius);
-                                               }
-                                       }
-                                       par.co[0]=par.co[1]=par.co[2]=0.0f;
-                                       VECCOPY(key.co,pa_loc);
-                                       do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0);
-                                       do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f);
-                                       VECCOPY(pa_loc,key.co);
-
-                                       VECADD(pa_loc,pa_loc,guidevec);
-                                       VECSUB(pa_loc,pa_loc,pa_zero);
-                                       VECADDFAC(effect,effect,pa_loc,f_force);
-                                       VECADDFAC(veffect,veffect,guidedir,f_force);
-                                       totforce+=f_force;
-                               }
-                       }
+                       /* curve tilt */
+                       VecRotToQuat(guidedir, guidevec[3] - eff->guide_loc[3], rot2);
+                       QuatMulVecf(rot2, vec_to_point);
                }
 
-               if(totforce!=0.0){
-                       if(totforce>1.0)
-                               VecMulf(effect,1.0f/totforce);
-                       CLAMP(totforce,0.0,1.0);
-                       VECADD(effect,effect,pa_zero);
-                       VecLerpf(state->co,state->co,effect,totforce);
+               /* curve taper */
+               if(cu->taperobj)
+                       VecMulf(vec_to_point, calc_taper(eff->scene, cu->taperobj, (int)(data->strength*guidetime*100.0), 100));
 
-                       Normalize(veffect);
-                       VecMulf(veffect,VecLength(state->vel));
-                       VECCOPY(state->vel,veffect);
-                       return 1;
+               else{ /* curve size*/
+                       if(cu->flag & CU_PATH_RADIUS) {
+                               VecMulf(vec_to_point, radius);
+                       }
                }
+               par.co[0] = par.co[1] = par.co[2] = 0.0f;
+               VECCOPY(key.co, vec_to_point);
+               do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0);
+               do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f);
+               VECCOPY(vec_to_point, key.co);
+
+               VECADD(vec_to_point, vec_to_point, guidevec);
+               //VECSUB(pa_loc,pa_loc,pa_zero);
+               VECADDFAC(effect, effect, vec_to_point, data->strength);
+               VECADDFAC(veffect, veffect, guidedir, data->strength);
+               totstrength += data->strength;
+       }
+
+       if(totstrength != 0.0){
+               if(totstrength > 1.0)
+                       VecMulf(effect, 1.0f / totstrength);
+               CLAMP(totstrength, 0.0, 1.0);
+               //VECADD(effect,effect,pa_zero);
+               VecLerpf(state->co, state->co, effect, totstrength);
+
+               Normalize(veffect);
+               VecMulf(veffect, VecLength(state->vel));
+               VECCOPY(state->vel, veffect);
+               return 1;
        }
        return 0;
 }
@@ -2053,14 +2059,18 @@ static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheK
 {
        float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f};
        ParticleKey eff_key;
-       ParticleData *pa;
+       EffectedPoint epoint;
+
+       /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */
+       if(sim->psys->flag & PSYS_HAIR_DYNAMICS)
+               return;
 
        VECCOPY(eff_key.co,(ca-1)->co);
        VECCOPY(eff_key.vel,(ca-1)->vel);
        QUATCOPY(eff_key.rot,(ca-1)->rot);
 
-       pa= sim->psys->particles+i;
-       do_effectors(sim, i, pa, &eff_key, rootco, force, vel, dfra, cfra);
+       pd_point_from_particle(sim, sim->psys->particles+i, &eff_key, &epoint);
+       pdDoEffectors(sim->psys->effectors, sim->colliders, sim->psys->part->effector_weights, &epoint, force, NULL);
 
        VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps);
 
@@ -2777,9 +2787,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
                                        do_path_effectors(sim, p, ca, k, steps, cache[p]->co, effector, dfra, cfra, &length, vec);
 
                                /* apply guide curves to path data */
-                               if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0)
+                               if(sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT)==0)
                                        /* ca is safe to cast, since only co and vel are used */
-                                       do_guide(sim->scene, (ParticleKey*)ca, p, (float)k/(float)steps, &psys->effectors);
+                                       do_guides(sim->psys->effectors, (ParticleKey*)ca, p, (float)k/(float)steps);
 
                                /* apply lattice */
                                if(psys->lattice)
@@ -3187,8 +3197,6 @@ void object_remove_particle_system(Scene *scene, Object *ob)
 }
 static void default_particle_settings(ParticleSettings *part)
 {
-       int i;
-
        part->type= PART_EMITTER;
        part->distr= PART_DISTR_JIT;
        part->draw_as = PART_DRAW_REND;
@@ -3199,7 +3207,7 @@ static void default_particle_settings(ParticleSettings *part)
        part->flag=PART_REACT_MULTIPLE|PART_HAIR_GEOMETRY|PART_EDISTR|PART_TRAND;
 
        part->sta= 1.0;
-       part->end= 100.0;
+       part->end= 200.0;
        part->lifetime= 50.0;
        part->jitfac= 1.0;
        part->totpart= 1000;
@@ -3249,10 +3257,6 @@ static void default_particle_settings(ParticleSettings *part)
 
        part->keyed_loops = 1;
 
-       for(i=0; i<10; i++)
-               part->effector_weight[i]=1.0f;
-
-
 #if 0 // XXX old animation system
        part->ipo = NULL;
 #endif // XXX old animation system
@@ -3261,6 +3265,9 @@ static void default_particle_settings(ParticleSettings *part)
        part->simplify_rate= 1.0f;
        part->simplify_transition= 0.1f;
        part->simplify_viewport= 0.8;
+
+       if(!part->effector_weights)
+               part->effector_weights = BKE_add_effector_weights(NULL);
 }
 
 
@@ -3348,24 +3355,6 @@ void make_local_particlesettings(ParticleSettings *part)
                }
        }
 }
-void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int recalc)
-{
-       Base *base = scene->base.first;
-       ParticleSystem *psys;
-       int flush;
-
-       for(base = scene->base.first; base; base = base->next) {
-               flush = 0;
-               for(psys = base->object->particlesystem.first; psys; psys=psys->next) {
-                       if(psys->part == part) {
-                               psys->recalc |= recalc;
-                               flush++;
-                       }
-               }
-               if(flush)
-                       DAG_id_flush_update(&base->object->id, OB_RECALC_DATA);
-       }
-}
 
 /************************************************/
 /*                     Textures                                                        */
@@ -3646,7 +3635,7 @@ static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *pte
 
        if(part->flag & PART_CHILD_EFFECT)
                /* state is safe to cast, since only co and vel are used */
-               guided = do_guide(sim->scene, (ParticleKey*)state, cpa->parent, t, &(sim->psys->effectors));
+               guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t);
 
        if(guided==0){
                if(part->kink)
@@ -3716,8 +3705,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                                Mat4MulVecfl(hairmat, state->co);
                                Mat4Mul3Vecfl(hairmat, state->vel);
 
-                               if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) {
-                                       do_guide(sim->scene, state, p, state->time, &psys->effectors);
+                               if(sim->psys->effectors && (part->flag & PART_CHILD_GUIDE)==0) {
+                                       do_guides(sim->psys->effectors, state, p, state->time);
                                        /* TODO: proper velocity handling */
                                }
 
@@ -3905,8 +3894,6 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
        }
 
        if(pa) {
-               if(pa->alive == PARS_KILLED) return 0;
-
                if(!always)
                        if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
                                || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
index 1b6d56e6459280155dde9b5b0639cbc93ea189e4..77cef689d09c30219dc64201e1c45787ce71a83b 100644 (file)
@@ -58,7 +58,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_kdtree.h"
 #include "BLI_kdopbvh.h"
-#include "BLI_linklist.h"
+#include "BLI_listbase.h"
 #include "BLI_threads.h"
 
 #include "BKE_anim.h"
@@ -132,9 +132,6 @@ void psys_reset(ParticleSystem *psys, int mode)
                        psys->totkeyed= 0;
                        psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED);
 
-                       if(psys->reactevents.first)
-                               BLI_freelistN(&psys->reactevents);
-
                        if(psys->edit && psys->free_edit) {
                                psys->free_edit(psys->edit);
                                psys->edit = NULL;
@@ -1796,8 +1793,9 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
                /* and gravity in r_ve */
                bpa->gravity[0] = bpa->gravity[1] = 0.0f;
                bpa->gravity[2] = -1.0f;
-               if(part->acc[2]!=0.0f)
-                       bpa->gravity[2] = part->acc[2];
+               if((sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)
+                       && sim->scene->physics_settings.gravity[2]!=0.0f)
+                       bpa->gravity[2] = sim->scene->physics_settings.gravity[2];
 
                /* calculate rotation matrix */
                Projf(dvec, r_vel, pa->state.ave);
@@ -1936,8 +1934,12 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
 
        pa->dietime = pa->time + pa->lifetime;
 
-       if(pa->time >= cfra)
+       if(pa->time > cfra)
                pa->alive = PARS_UNBORN;
+       else if(pa->dietime <= cfra)
+               pa->alive = PARS_DEAD;
+       else
+               pa->alive = PARS_ALIVE;
 
        pa->state.time = cfra;
 }
@@ -2203,12 +2205,12 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
 /************************************************/
 /*                     Effectors                                                       */
 /************************************************/
-static void update_particle_tree(ParticleSystem *psys)
+void psys_update_particle_tree(ParticleSystem *psys, float cfra)
 {
        if(psys) {
                PARTICLE_P;
 
-               if(!psys->tree || psys->tree_frame != psys->cfra) {
+               if(!psys->tree || psys->tree_frame != cfra) {
                        
                        BLI_kdtree_free(psys->tree);
 
@@ -2216,7 +2218,10 @@ static void update_particle_tree(ParticleSystem *psys)
                        
                        LOOP_SHOWN_PARTICLES {
                                if(pa->alive == PARS_ALIVE)
-                                       BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL);
+                                       if(pa->state.time == cfra)
+                                               BLI_kdtree_insert(psys->tree, p, pa->prev_state.co, NULL);
+                                       else
+                                               BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL);
                        }
                        BLI_kdtree_balance(psys->tree);
 
@@ -2224,535 +2229,12 @@ static void update_particle_tree(ParticleSystem *psys)
                }
        }
 }
-static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, short object, float *pa_co, float obmat[4][4], float force_val, float falloff, float *field)
-{
-       TexResult result[4];
-       float tex_co[3], strength, mag_vec[3];
-       int hasrgb;
-       if(tex==NULL) return;
-
-       result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0;
-
-       strength= force_val*falloff;
-
-       VECCOPY(tex_co,pa_co);
-
-       if(is_2d){
-               float fac=-Inpf(tex_co,obmat[2]);
-               VECADDFAC(tex_co,tex_co,obmat[2],fac);
-       }
-
-       if(object){
-               VecSubf(tex_co,tex_co,obmat[3]);
-               Mat4Mul3Vecfl(obmat,tex_co);
-       }
-
-       hasrgb = multitex_ext(tex, tex_co, NULL,NULL, 1, result);
-
-       if(hasrgb && mode==PFIELD_TEX_RGB){
-               mag_vec[0]= (0.5f-result->tr)*strength;
-               mag_vec[1]= (0.5f-result->tg)*strength;
-               mag_vec[2]= (0.5f-result->tb)*strength;
-       }
-       else{
-               strength/=nabla;
-
-               tex_co[0]+= nabla;
-               multitex_ext(tex, tex_co, NULL,NULL, 1, result+1);
-
-               tex_co[0]-= nabla;
-               tex_co[1]+= nabla;
-               multitex_ext(tex, tex_co, NULL,NULL, 1, result+2);
-
-               tex_co[1]-= nabla;
-               tex_co[2]+= nabla;
-               multitex_ext(tex, tex_co, NULL,NULL, 1, result+3);
-
-               if(mode==PFIELD_TEX_GRAD || !hasrgb){ /* if we dont have rgb fall back to grad */
-                       mag_vec[0]= (result[0].tin-result[1].tin)*strength;
-                       mag_vec[1]= (result[0].tin-result[2].tin)*strength;
-                       mag_vec[2]= (result[0].tin-result[3].tin)*strength;
-               }
-               else{ /*PFIELD_TEX_CURL*/
-                       float dbdy,dgdz,drdz,dbdx,dgdx,drdy;
-
-                       dbdy= result[2].tb-result[0].tb;
-                       dgdz= result[3].tg-result[0].tg;
-                       drdz= result[3].tr-result[0].tr;
-                       dbdx= result[1].tb-result[0].tb;
-                       dgdx= result[1].tg-result[0].tg;
-                       drdy= result[2].tr-result[0].tr;
-
-                       mag_vec[0]=(dbdy-dgdz)*strength;
-                       mag_vec[1]=(drdz-dbdx)*strength;
-                       mag_vec[2]=(dgdx-drdy)*strength;
-               }
-       }
-
-       if(is_2d){
-               float fac=-Inpf(mag_vec,obmat[2]);
-               VECADDFAC(mag_vec,mag_vec,obmat[2],fac);
-       }
-
-       VecAddf(field,field,mag_vec);
-}
-static void add_to_effectors(ParticleSimulationData *sim, ListBase *lb, Object *ob)
-{
-       ParticleEffectorCache *ec;
-       PartDeflect *pd= ob->pd;
-       short type=0,i;
-
-       if(pd && ob != sim->ob){
-               if(pd->forcefield == PFIELD_GUIDE) {
-                       if(ob->type==OB_CURVE) {
-                               Curve *cu= ob->data;
-                               if(cu->flag & CU_PATH) {
-                                       if(cu->path==NULL || cu->path->data==NULL)
-                                               makeDispListCurveTypes(sim->scene, ob, 0);
-                                       if(cu->path && cu->path->data) {
-                                               type |= PSYS_EC_EFFECTOR;
-                                       }
-                               }
-                       }
-               }
-               else if(pd->forcefield)
-               {
-                       type |= PSYS_EC_EFFECTOR;
-               }
-       }
-       
-       if(pd && pd->deflect)
-               type |= PSYS_EC_DEFLECT;
-
-       if(type){
-               ec= MEM_callocN(sizeof(ParticleEffectorCache), "effector cache");
-               ec->ob= ob;
-               ec->type=type;
-               ec->distances=0;
-               ec->locations=0;
-               ec->rng = rng_new(1);
-               rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed
-               
-               BLI_addtail(lb, ec);
-       }
-
-       type=0;
-
-       /* add particles as different effectors */
-       if(ob->particlesystem.first){
-               ParticleSystem *epsys=ob->particlesystem.first;
-               ParticleSettings *epart=0;
-               //Object *tob;
-
-               for(i=0; epsys; epsys=epsys->next,i++){
-                       if(!psys_check_enabled(ob, epsys))
-                               continue;
-                       type=0;
-                       if(epsys!=sim->psys || (sim->psys->part->flag & PART_SELF_EFFECT)){
-                               epart=epsys->part;
-
-                               if((epsys->part->pd && epsys->part->pd->forcefield)
-                                       || (epsys->part->pd2 && epsys->part->pd2->forcefield))
-                               {
-                                       type=PSYS_EC_PARTICLE;
-                               }
-
-                               //if(epart->type==PART_REACTOR) {
-                               //      tob=epsys->target_ob;
-                               //      if(tob==0)
-                               //              tob=ob;
-                               //      if(BLI_findlink(&tob->particlesystem,epsys->target_psys-1)==sim->psys)
-                               //              type|=PSYS_EC_REACTOR;
-                               //}
-
-                               if(type){
-                                       ec= MEM_callocN(sizeof(ParticleEffectorCache), "effector cache");
-                                       ec->ob= ob;
-                                       ec->type=type;
-                                       ec->psys_nbr=i;
-                                       ec->rng = rng_new(1);
-                                       rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer())));
-                                       
-                                       BLI_addtail(lb, ec);
-                               }
-                       }
-               }
-                               
-       }
-}
-
-static void psys_init_effectors_recurs(ParticleSimulationData *sim, Object *ob, ListBase *listb, int level)
-{
-       Group *group;
-       GroupObject *go;
-       unsigned int layer= sim->ob->lay;
-
-       if(level>MAX_DUPLI_RECUR) return;
-
-       if(ob->lay & layer) {
-               if(ob->pd || ob->particlesystem.first)
-                       add_to_effectors(sim, listb, ob);
-
-               if(ob->dup_group) {
-                       group= ob->dup_group;
-                       for(go= group->gobject.first; go; go= go->next)
-                               psys_init_effectors_recurs(sim, go->ob, listb, level+1);
-               }
-       }
-}
-
-static void psys_init_effectors(ParticleSimulationData *sim, Group *group)
-{
-       ListBase *listb= &sim->psys->effectors;
-       Base *base;
-
-       listb->first=listb->last=0;
-       
-       if(group) {
-               GroupObject *go;
-               
-               for(go= group->gobject.first; go; go= go->next)
-                       psys_init_effectors_recurs(sim, go->ob, listb, 0);
-       }
-       else {
-               for(base = sim->scene->base.first; base; base= base->next)
-                       psys_init_effectors_recurs(sim, base->object, listb, 0);
-       }
-}
-
-void psys_end_effectors(ParticleSystem *psys)
-{
-       /* NOTE:
-       ec->ob is not valid in here anymore! - dg
-       */
-       ParticleEffectorCache *ec = psys->effectors.first;
-
-       for(; ec; ec= ec->next){
-               if(ec->distances)
-                       MEM_freeN(ec->distances);
-
-               if(ec->locations)
-                       MEM_freeN(ec->locations);
-
-               if(ec->face_minmax)
-                       MEM_freeN(ec->face_minmax);
-
-               if(ec->vert_cos)
-                       MEM_freeN(ec->vert_cos);
-
-               if(ec->tree)
-                       BLI_kdtree_free(ec->tree);
-               
-               if(ec->rng)
-                       rng_free(ec->rng);
-       }
-
-       BLI_freelistN(&psys->effectors);
-}
-
-/* precalcs effectors and returns 1 if there were any collision object 
- * so collision checks can be avoided as quickly as possible */
-static int precalc_effectors(ParticleSimulationData *sim, float cfra)
-{
-       ParticleSystem *psys = sim->psys;
-       ListBase *lb=&psys->effectors;
-       ParticleEffectorCache *ec;
-       ParticleSettings *part=psys->part;
-       PARTICLE_P;
-       int totpart, collision = 0;
-       float vec2[3],loc[3],radius,*co=0;
-       
-       for(ec= lb->first; ec; ec= ec->next) {
-               PartDeflect *pd= ec->ob->pd;
-               co = NULL;
-               
-               if(ec->type==PSYS_EC_EFFECTOR && pd->forcefield==PFIELD_GUIDE && ec->ob->type==OB_CURVE 
-                       && part->phystype!=PART_PHYS_BOIDS) {
-                       float vec[4];
-
-                       where_on_path(ec->ob, 0.0, vec, vec2, NULL, &radius);
-
-                       Mat4MulVecfl(ec->ob->obmat,vec);
-                       Mat4Mul3Vecfl(ec->ob->obmat,vec2);
-
-                       QUATCOPY(ec->firstloc,vec);
-                       VECCOPY(ec->firstdir,vec2);
-
-                       /* TODO - use 'radius' to adjust the effector */
-
-                       totpart=psys->totpart;
-
-                       if(totpart){
-                               ec->distances=MEM_callocN(totpart*sizeof(float),"particle distances");
-                               ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations");
-
-                               LOOP_PARTICLES {
-                                       if(part->from == PART_FROM_PARTICLE) {
-                                               VECCOPY(loc, pa->fuv);
-                                       }
-                                       else
-                                               psys_particle_on_emitter(sim->psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0);
-
-                                       Mat4MulVecfl(sim->ob->obmat,loc);
-                                       ec->distances[p]=VecLenf(loc,vec);
-                                       VECSUB(loc,loc,vec);
-                                       VECCOPY(ec->locations+3*p,loc);
-                               }
-                       }
-               }
-               else if(ec->type==PSYS_EC_PARTICLE){
-                       ParticleSimulationData esim = {sim->scene, ec->ob, BLI_findlink(&ec->ob->particlesystem, ec->psys_nbr), NULL};
-                       ParticleSettings *epart = esim.psys->part;
-                       ParticleData *epa;
-                       int p, totepart = esim.psys->totpart;
-
-                       if(psys->part->phystype==PART_PHYS_BOIDS){
-                               ParticleKey state;
-                               PartDeflect *pd;
-                               
-                               pd= epart->pd;
-                               if(pd->forcefield==PFIELD_FORCE && totepart){
-                                       KDTree *tree;
-
-                                       tree=BLI_kdtree_new(totepart);
-                                       ec->tree=tree;
-
-                                       for(p=0, epa=esim.psys->particles; p<totepart; p++,epa++)
-                                               if(epa->alive==PARS_ALIVE && psys_get_particle_state(&esim,p,&state,0))
-                                                       BLI_kdtree_insert(tree, p, state.co, NULL);
-
-                                       BLI_kdtree_balance(tree);
-                               }
-                       }
-
-               }
-               else if(ec->type==PSYS_EC_DEFLECT) {
-                       CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) );
-                       if(collmd) {
-                               collision_move_object(collmd, 1.0, 0.0);
-                               collision = 1;
-                       }
-               }
-       }
-
-       return collision;
-}
 
-/* updates particle effectors and returns if any collision objects were found */
-int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc)
-{
-       psys_end_effectors(sim->psys);
-       psys_init_effectors(sim, sim->psys->part->eff_group);
-       return (precalc ? precalc_effectors(sim, cfra) : 0);
-}
-int effector_find_co(Scene *scene, float *pco, SurfaceModifierData *sur, Object *ob, PartDeflect *pd, float *co, float *nor, float *vel, int *index)
+static void psys_update_effectors(ParticleSimulationData *sim)
 {
-       SurfaceModifierData *surmd = NULL;
-       int ret = 0;
-
-       if(sur)
-               surmd = sur;
-       else if(pd && pd->flag&PFIELD_SURFACE)
-       {
-               surmd = (SurfaceModifierData *)modifiers_findByType ( ob, eModifierType_Surface );
-       }
-
-       if(surmd) {
-               /* closest point in the object surface is an effector */
-               BVHTreeNearest nearest;
-
-               nearest.index = -1;
-               nearest.dist = FLT_MAX;
-
-               BLI_bvhtree_find_nearest(surmd->bvhtree->tree, pco, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree);
-
-               if(nearest.index != -1) {
-                       VECCOPY(co, nearest.co);
-
-                       if(nor) {
-                               VECCOPY(nor, nearest.no);
-                       }
-
-                       if(vel) {
-                               MFace *mface = CDDM_get_face(surmd->dm, nearest.index);
-                               
-                               VECCOPY(vel, surmd->v[mface->v1].co);
-                               VecAddf(vel, vel, surmd->v[mface->v2].co);
-                               VecAddf(vel, vel, surmd->v[mface->v3].co);
-                               if(mface->v4)
-                                       VecAddf(vel, vel, surmd->v[mface->v4].co);
-
-                               VecMulf(vel, mface->v4 ? 0.25f : 0.333f);
-                       }
-
-                       if(index)
-                               *index = nearest.index;
-
-                       ret = 1;
-               }
-               else {
-                       co[0] = co[1] = co[2] = 0.0f;
-
-                       if(nor)
-                               nor[0] = nor[1] = nor[2] = 0.0f;
-
-                       if(vel)
-                               vel[0] = vel[1] = vel[2] = 0.0f;
-               }
-       }
-       else {
-               /* use center of object for distance calculus */
-               VECCOPY(co, ob->obmat[3]);
-
-               if(nor) {
-                       VECCOPY(nor, ob->obmat[2]);
-               }
-
-               if(vel) {
-                       Object obcopy = *ob;
-                       
-                       VECCOPY(vel, ob->obmat[3]);
-
-                       where_is_object_time(scene, ob, scene->r.cfra - 1.0);
-
-                       VecSubf(vel, vel, ob->obmat[3]);
-
-                       *ob = obcopy;
-               }
-       }
-
-       return ret;
-}
-/* calculate forces that all effectors apply to a particle*/
-void do_effectors(ParticleSimulationData *sim, int pa_no, ParticleData *pa, ParticleKey *state, float *rootco, float *force_field, float *vel,float framestep, float cfra)
-{
-       Object *eob;
-       ParticleSystem *psys = sim->psys;
-       ParticleSettings *epart;
-       ParticleData *epa;
-       ParticleKey estate;
-       PartDeflect *pd;
-       ListBase *lb=&psys->effectors;
-       ParticleEffectorCache *ec;
-       float distance, vec_to_part[3], pco[3], co[3];
-       float falloff, charge = 0.0f, strength;
-       int p, face_index=-1;
-
-       /* check all effector objects for interaction */
-       if(lb->first){
-               if(psys->part->pd && psys->part->pd->forcefield==PFIELD_CHARGE){
-                       /* Only the charge of the effected particle is used for 
-                          interaction, not fall-offs. If the fall-offs aren't the      
-                          same this will be unphysical, but for animation this         
-                          could be the wanted behavior. If you want physical
-                          correctness the fall-off should be spherical 2.0 anyways.
-                        */
-                       charge = psys->part->pd->f_strength;
-               }
-               if(psys->part->pd2 && psys->part->pd2->forcefield==PFIELD_CHARGE){
-                       charge += psys->part->pd2->f_strength;
-               }
-               for(ec = lb->first; ec; ec= ec->next){
-                       eob= ec->ob;
-                       if(ec->type & PSYS_EC_EFFECTOR){
-                               pd=eob->pd;
-                               if(psys->part->type!=PART_HAIR && psys->part->integrator)
-                                       where_is_object_time(sim->scene, eob, cfra);
-
-                               if(pd && pd->flag&PFIELD_SURFACE) {
-                                       float velocity[3];
-                                       /* using velocity corrected location allows for easier sliding over effector surface */
-                                       VecCopyf(velocity, state->vel);
-                                       VecMulf(velocity, psys_get_timestep(sim));
-                                       VecAddf(pco, state->co, velocity);
-                               }
-                               else 
-                                       VECCOPY(pco, state->co);
-
-                               effector_find_co(sim->scene, pco, NULL, eob, pd, co, NULL, NULL, &face_index);
-                               
-                               VecSubf(vec_to_part, state->co, co);
-
-                               distance = VecLength(vec_to_part);
-
-                               falloff=effector_falloff(pd,eob->obmat[2],vec_to_part);
-
-                               strength = pd->f_strength * psys->part->effector_weight[0] * psys->part->effector_weight[pd->forcefield];
-
-                               if(falloff<=0.0f)
-                                       ;       /* don't do anything */
-                               else if(pd->forcefield==PFIELD_TEXTURE) {
-                                       do_texture_effector(pd->tex, pd->tex_mode, pd->flag&PFIELD_TEX_2D, pd->tex_nabla,
-                                                                       pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat,
-                                                                       strength, falloff, force_field);
-                               } else {
-                                       do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance,
-                                                                               falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part,
-                                                                               state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size);
-                               }
-                       }
-                       if(ec->type & PSYS_EC_PARTICLE){
-                               ParticleSimulationData esim = {sim->scene, eob, BLI_findlink(&eob->particlesystem,ec->psys_nbr), NULL};
-                               int totepart, i;
-
-                               epart = esim.psys->part;
-                               pd = epart->pd;
-                               totepart = esim.psys->totpart;
-                               
-                               if(totepart <= 0)
-                                       continue;
-                               
-                               if(pd && pd->forcefield==PFIELD_HARMONIC){
-                                       /* every particle is mapped to only one harmonic effector particle */
-                                       p= pa_no%esim.psys->totpart;
-                                       totepart= p+1;
-                               }
-                               else{
-                                       p=0;
-                               }
-
-                               esim.psys->lattice= psys_get_lattice(sim);
-
-                               for(; p<totepart; p++){
-                                       /* particle skips itself as effector */
-                                       if(esim.psys == psys && p == pa_no) continue;
-
-                                       epa = esim.psys->particles + p;
-                                       estate.time = cfra;
-                                       if(psys_get_particle_state(&esim, p, &estate, 0)){
-                                               VECSUB(vec_to_part, state->co, estate.co);
-                                               distance = VecLength(vec_to_part);
-                                               
-                                               for(i=0, pd = epart->pd; i<2; i++,pd = epart->pd2) {
-                                                       if(pd==NULL || pd->forcefield==0) continue;
-
-                                                       falloff = effector_falloff(pd, estate.vel, vec_to_part);
-
-                                                       strength = pd->f_strength * psys->part->effector_weight[0] * psys->part->effector_weight[pd->forcefield];
-
-                                                       if(falloff<=0.0f)
-                                                               ;       /* don't do anything */
-                                                       else
-                                                               do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance,
-                                                               falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
-                                                               state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size);
-                                               }
-                                       }
-                                       else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){
-                                               /* first step after key release */
-                                               psys_get_particle_state(&esim, p, &estate, 1);
-                                               VECADD(vel, vel, estate.vel);
-                                               /* TODO: add rotation handling here too */
-                                       }
-                               }
-
-                               if(esim.psys->lattice){
-                                       end_latt_deform(esim.psys->lattice);
-                                       esim.psys->lattice= NULL;
-                               }
-                       }
-               }
-       }
+       pdEndEffectors(&sim->psys->effectors);
+       sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys, sim->psys->part->effector_weights);
+       precalc_guides(sim, sim->psys->effectors);
 }
 
 /************************************************/
@@ -2763,9 +2245,10 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
 {
        ParticleSettings *part = sim->psys->part;
        ParticleData *pa = sim->psys->particles + p;
+       EffectedPoint epoint;
        ParticleKey states[5], tkey;
        float timestep = psys_get_timestep(sim);
-       float force[3],tvel[3],dx[4][3],dv[4][3];
+       float force[3],impulse[3],dx[4][3],dv[4][3];
        float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=sim->psys->cfra;
        int i, steps=1;
        
@@ -2791,10 +2274,11 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
 
        for(i=0; i<steps; i++){
                force[0]=force[1]=force[2]=0.0;
-               tvel[0]=tvel[1]=tvel[2]=0.0;
+               impulse[0]=impulse[1]=impulse[2]=0.0;
                /* add effectors */
-               if(part->type != PART_HAIR)
-                       do_effectors(sim, p, pa, states+i, states->co, force, tvel, dfra, fra);
+               pd_point_from_particle(sim, pa, states+i, &epoint);
+               if(part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)
+                       pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse);
 
                /* calculate air-particle interaction */
                if(part->dragfac!=0.0f){
@@ -2813,10 +2297,17 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
                VecMulf(force,1.0f/pa_mass);
 
                /* add global acceleration (gravitation) */
-               VECADD(force,force,part->acc);
+               if(sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY
+                       /* normal gravity is too strong for hair so it's disabled by default */
+                       && (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) {
+                       float gravity[3];
+                       VECCOPY(gravity, sim->scene->physics_settings.gravity);
+                       VecMulf(gravity, part->effector_weights->global_gravity);
+                       VECADD(force,force,gravity);
+               }
                
                /* calculate next state */
-               VECADD(states[i].vel,states[i].vel,tvel);
+               VECADD(states[i].vel,states[i].vel,impulse);
 
                switch(part->integrator){
                        case PART_INT_EULER:
@@ -2889,6 +2380,8 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
        if(part->dampfac!=0.0)
                VecMulf(pa->state.vel,1.0f-part->dampfac);
 
+       VECCOPY(pa->state.ave, states->ave);
+
        /* finally we do guides */
        time=(cfra-pa->time)/pa->lifetime;
        CLAMP(time,0.0,1.0);
@@ -2898,7 +2391,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra
        tkey.time=pa->state.time;
 
        if(part->type != PART_HAIR) {
-               if(do_guide(sim->scene, &tkey, p, time, &sim->psys->effectors)) {
+               if(do_guides(sim->psys->effectors, &tkey, p, time)) {
                        VECCOPY(pa->state.co,tkey.co);
                        /* guides don't produce valid velocity */
                        VECSUB(pa->state.vel,tkey.co,pa->prev_state.co);
@@ -3129,7 +2622,8 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B
 
                                        VECCOPY(col->vel,vel);
 
-                                       col->ob = col->ob_t;
+                                       col->hit_ob = col->ob;
+                                       col->hit_md = col->md;
                                }
                        }
                }
@@ -3146,7 +2640,8 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B
 
                                        VECCOPY(col->vel,vel);
 
-                                       col->ob = col->ob_t;
+                                       col->hit_ob = col->ob;
+                                       col->hit_md = col->md;
                                }
                        }
                }
@@ -3163,13 +2658,11 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B
 /* 1. check for all possible deflectors for closest intersection on particle path */
 /* 2. if deflection was found kill the particle or calculate new coordinates */
 static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){
-       Object *ob = NULL, *skip_ob = NULL;
+       Object *ground_ob = NULL;
        ParticleSettings *part = sim->psys->part;
-       ListBase *lb=&sim->psys->effectors;
-       ParticleEffectorCache *ec;
-       ParticleKey reaction_state;
-       ParticleCollision col;
        ParticleData *pa = sim->psys->particles + p;
+       ParticleCollision col;
+       ColliderCache *coll;
        BVHTreeRayHit hit;
        float ray_dir[3], zerovec[3]={0.0,0.0,0.0};
        float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z = 0.0f;
@@ -3185,11 +2678,11 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
                BoidParticle *bpa = pa->boid;
                radius = pa->size;
                boid_z = pa->state.co[2];
-               skip_ob = bpa->ground;
+               ground_ob = bpa->ground;
        }
 
        /* 10 iterations to catch multiple deflections */
-       if(lb->first) while(deflections < max_deflections){
+       if(sim->colliders) while(deflections < max_deflections){
                /* 1. */
 
                VECSUB(ray_dir, col.co2, col.co1);
@@ -3201,32 +2694,25 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
                if(hit.dist == 0.0f)
                        hit.dist = col.ray_len = 0.000001f;
 
-               for(ec=lb->first; ec; ec=ec->next){
-                       if(ec->type & PSYS_EC_DEFLECT){
-                               ob= ec->ob;
-
-                               /* for boids: don't check with current ground object */
-                               if(ob==skip_ob)
-                                       continue;
-
-                               /* particles should not collide with emitter at birth */
-                               if(ob==sim->ob && pa->time < cfra && pa->time >= sim->psys->cfra)
-                                       continue;
+               for(coll = sim->colliders->first; coll; coll=coll->next){
+                       /* for boids: don't check with current ground object */
+                       if(coll->ob == ground_ob)
+                               continue;
 
-                               if(part->type!=PART_HAIR)
-                                       where_is_object_time(sim->scene, sim->ob, cfra);
+                       /* particles should not collide with emitter at birth */
+                       if(coll->ob == sim->ob && pa->time < cfra && pa->time >= sim->psys->cfra)
+                               continue;
 
-                               col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) );
-                               col.ob_t = ob;
+                       col.ob = coll->ob;
+                       col.md = coll->collmd;
 
-                               if(col.md && col.md->bvhtree)
-                                       BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
-                       }
+                       if(col.md && col.md->bvhtree)
+                               BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col);
                }
 
                /* 2. */
                if(hit.index>=0) {
-                       PartDeflect *pd = col.ob->pd;
+                       PartDeflect *pd = col.hit_ob->pd;
                        int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0;
                        float co[3]; /* point of collision */
                        float vec[3]; /* movement through collision */
@@ -3253,9 +2739,6 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
 
                                /* particle is dead so we don't need to calculate further */
                                deflections=max_deflections;
-
-                               /* store for reactors */
-                               copy_particle_key(&reaction_state, &pa->state, 0);
                        }
                        else {
                                float nor_vec[3], tan_vec[3], tan_vel[3], vel[3];
@@ -3416,7 +2899,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
 
        if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0)
                skip = 1; /* only hair, keyed and baked stuff can have paths */
-       else if(part->ren_as != PART_DRAW_PATH)
+       else if(part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
                skip = 1; /* particle visualization must be set as path */
        else if(!psys->renderdata) {
                if(part->draw_as != PART_DRAW_REND)
@@ -3555,8 +3038,11 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
                psys->hair_out_dm->release(psys->hair_out_dm);
 
        psys->clmd->point_cache = psys->pointcache;
+       psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
 
        psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, 0, 0);
+
+       psys->clmd->sim_parms->effector_weights = NULL;
 }
 static void hair_step(ParticleSimulationData *sim, float cfra)
 {
@@ -3586,7 +3072,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra)
        if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS)
                do_hair_dynamics(sim);
 
-       psys_update_effectors(sim, cfra, 1);
+       psys_update_effectors(sim);
 
        psys_update_path_cache(sim, cfra);
 
@@ -3653,7 +3139,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
        BoidBrainData bbd;
        PARTICLE_P;
        float timestep;
-       int totpart, check_collisions = 0;
+       int totpart;
        /* current time */
        float ctime, ipotime; // XXX old animation system
        /* frame & time changes */
@@ -3665,7 +3151,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
 
        totpart=psys->totpart;
 
-       timestep=psys_get_timestep(sim);
+       timestep = psys_get_timestep(sim);
        dtime= dfra*timestep;
        ctime= cfra*timestep;
        ipotime= cfra; // XXX old animation system
@@ -3703,15 +3189,6 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
                        }
                        else{
                                pa->loop = 0;
-                               if(cfra <= pa->time)
-                                       pa->alive = PARS_UNBORN;
-                                               /* without dynamics the state is allways known so no need to kill */
-                               else if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)){
-                                       if(cfra < pa->dietime)
-                                               pa->alive = PARS_ALIVE;
-                               }
-                               else
-                                       pa->alive = PARS_KILLED;
                        }
                }
 
@@ -3721,7 +3198,10 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
        else{
                BLI_srandom(31415926 + (int)cfra + psys->seed);
 
-               psys_update_effectors(sim, cfra, 1);
+               psys_update_effectors(sim);
+
+               if(part->type != PART_HAIR)
+                       sim->colliders = get_collider_cache(sim->scene, NULL);
 
                if(part->phystype==PART_PHYS_BOIDS){
                        ParticleTarget *pt = psys->targets.first;
@@ -3731,13 +3211,13 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
                        bbd.dfra = dfra;
                        bbd.timestep = timestep;
 
-                       update_particle_tree(psys);
+                       psys_update_particle_tree(psys, cfra);
 
                        boids_precalc_rules(part, cfra);
 
                        for(; pt; pt=pt->next) {
                                if(pt->ob)
-                                       update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1));
+                                       psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra);
                        }
                }
 
@@ -3798,7 +3278,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
                                                apply_particle_forces(sim, p, pa_dfra, cfra);
                        
                                                /* deflection */
-                                               if(check_collisions)
+                                               if(sim->colliders)
                                                        deflect_particle(sim, p, pa_dfra, cfra);
 
                                                /* rotations */
@@ -3812,7 +3292,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
                                                        boid_body(&bbd, pa);
 
                                                        /* deflection */
-                                                       deflect_particle(sim, p, pa_dfra, cfra);
+                                                       if(sim->colliders)
+                                                               deflect_particle(sim, p, pa_dfra, cfra);
                                                }
                                                break;
                                        }
@@ -3837,9 +3318,9 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
                                //push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state);
                        }
                }
+
+               free_collider_cache(&sim->colliders);
        }
-       if(psys->reactevents.first)
-               BLI_freelistN(&psys->reactevents);
 
        if(tree)
                BLI_kdtree_free(tree);
@@ -3860,7 +3341,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
        if(part->from!=PART_FROM_PARTICLE)
                vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE);
 
-       psys_update_effectors(sim, cfra, 1);
+       psys_update_effectors(sim);
        
        disp= (float)get_current_display_percentage(psys)/100.0f;
 
@@ -4195,6 +3676,13 @@ static void system_step(ParticleSimulationData *sim, float cfra)
                else if(framenr > endframe) {
                        framenr= endframe;
                }
+
+               if(framenr == startframe) {
+                       BKE_ptcache_id_reset(sim->scene, &pid, PTCACHE_RESET_OUTDATED);
+                       cache->simframe= framenr;
+                       cache->flag |= PTCACHE_SIMULATION_VALID;
+                       cache->flag &= ~PTCACHE_REDO_NEEDED;
+               }
        }
 
        /* verify if we need to reallocate */
@@ -4226,7 +3714,7 @@ static void system_step(ParticleSimulationData *sim, float cfra)
                        if(alloc) {
                                realloc_particles(sim, totpart);
 
-                               if(usecache && !only_children_changed) {
+                               if(oldtotpart && usecache && !only_children_changed) {
                                        BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
                                        BKE_ptcache_id_from_particles(&pid, sim->ob, psys);
                                }
@@ -4286,7 +3774,7 @@ static void system_step(ParticleSimulationData *sim, float cfra)
                                        pa->alive = PARS_ALIVE;
                        }
                }
-               else if(sim->ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
+               else if(cfra != startframe && (sim->ob->id.lib || (cache->flag & PTCACHE_BAKED))) {
                        psys_reset(psys, PSYS_RESET_CACHE_MISS);
                        psys->cfra=cfra;
                        psys->recalc = 0;
@@ -4383,7 +3871,7 @@ static int hair_needs_recalc(ParticleSystem *psys)
 /* main particle update call, checks that things are ok on the large scale before actual particle calculations */
 void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
 {
-       ParticleSimulationData sim = {scene, ob, psys, NULL};
+       ParticleSimulationData sim = {scene, ob, psys, NULL, NULL};
        float cfra;
 
        /* drawdata is outdated after ANY change */
index 3915a6901a0edf926f83ef13a3e22ca7c3ec103b..bffe4566f74384e34ed2a396c53543d796337ec7 100644 (file)
@@ -292,6 +292,9 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f
        else
                BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
 
+       if(cfra > pa->time)
+               cfra1 = MAX2(cfra1, pa->time);
+
        dfra = cfra2 - cfra1;
 
        VecMulf(keys[1].vel, dfra / frs_sec);
@@ -2266,6 +2269,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
                                                }
                                        }
                                }
+                               BLI_freelistN(&pidlist2);
                        }
 
                        if(bake || cache->flag & PTCACHE_REDO_NEEDED)
index b3f00f884bc794ece37630294fd56dae8c8d33bb..4f72ca96f5f8d4fc66f1135d941fccb454e00cce 100644 (file)
@@ -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;
 
index 62463b3d5554b269e6cac4848f2c01267b9de536..4f7a8cda81b2396ed6e601e6e4fdb1382470e146 100644 (file)
@@ -832,8 +832,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
                                                        size_t i = 0;                                                                   
                                                        size_t index = 0;                                                                       
                                                        int badcell = 0;                                                                                                                                                
-                                                       if(pa->alive == PARS_KILLED) continue;                                                                  
-                                                       else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue;                                                                    
+                                                       if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue;                                                                 
                                                        else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue;                                                                        
                                                        else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;                                                                                                                                               
                                                        // VECCOPY(pos, pa->state.co);                                                                  
index 450a64d72eb21324bd524c347d7f458cf155afb2..089f2a5ebfba388c6f9e20ffb3e41de6c4f225f5 100644 (file)
@@ -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);
index 94478b0d235d2e42a1428f23222d52f395458ff3..d1da29bef704ce6ca524a1aeb667b040de6bac06 100644 (file)
@@ -3044,6 +3044,10 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
                        part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
                        part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
                        part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
+
+                       if(part->effector_weights)
+                               part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group);
+
                        if(part->boids) {
                                BoidState *state = part->boids->states.first;
                                BoidRule *rule;
@@ -3079,6 +3083,11 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
        part->pd= newdataadr(fd, part->pd);
        part->pd2= newdataadr(fd, part->pd2);
 
+       if(part->effector_weights)
+               part->effector_weights = newdataadr(fd, part->effector_weights);
+       else
+               part->effector_weights = BKE_add_effector_weights(part->eff_group);
+
        part->boids= newdataadr(fd, part->boids);
 
        if(part->boids) {
@@ -3155,18 +3164,17 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
                }
 
 
-               psys->child=newdataadr(fd,psys->child);
-               psys->effectors.first=psys->effectors.last=0;
+               psys->child = newdataadr(fd,psys->child);
+               psys->effectors = NULL;
 
                link_list(fd, &psys->targets);
 
                psys->edit = NULL;
                psys->free_edit = NULL;
-               psys->pathcache = 0;
-               psys->childcache = 0;
-               psys->pathcachebufs.first = psys->pathcachebufs.last = 0;
-               psys->childcachebufs.first = psys->childcachebufs.last = 0;
-               psys->reactevents.first = psys->reactevents.last = 0;
+               psys->pathcache = NULL;
+               psys->childcache = NULL;
+               psys->pathcachebufs.first = psys->pathcachebufs.last = NULL;
+               psys->childcachebufs.first = psys->childcachebufs.last = NULL;
                psys->frand = NULL;
                psys->pdd = NULL;
 
@@ -3642,12 +3650,24 @@ static void lib_link_object(FileData *fd, Main *main)
                                        smd->domain->fluid_group = newlibadr_us(fd, ob->id.lib, smd->domain->fluid_group);
                                }
                        }
+
+                       {
+                               ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+                               
+                               if(clmd) 
+                               {
+                                       clmd->sim_parms->effector_weights->group = newlibadr(fd, ob->id.lib, clmd->sim_parms->effector_weights->group);
+                               }
+                       }
                        
                        /* texture field */
                        if(ob->pd)
                                if(ob->pd->tex)
                                        ob->pd->tex=newlibadr_us(fd, ob->id.lib, ob->pd->tex);
 
+                       if(ob->soft)
+                               ob->soft->effector_weights->group = newlibadr(fd, ob->id.lib, ob->soft->effector_weights->group);
+
                        lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
                        lib_link_modifiers(fd, ob);
                }
@@ -3727,6 +3747,11 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                                if(clmd->sim_parms->presets > 10)
                                        clmd->sim_parms->presets = 0;
                        }
+
+                       if(clmd->sim_parms->effector_weights)
+                               clmd->sim_parms->effector_weights = newdataadr(fd, clmd->sim_parms->effector_weights);
+                       else
+                               clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
                        
                }
                else if (md->type==eModifierType_Fluidsim) {
@@ -3948,6 +3973,8 @@ static void direct_link_object(FileData *fd, Object *ob)
        }
 
        ob->pd= newdataadr(fd, ob->pd);
+       if(ob->pd)
+               ob->pd->rng=NULL;
        ob->soft= newdataadr(fd, ob->soft);
        if(ob->soft) {
                SoftBody *sb= ob->soft;         
@@ -3965,6 +3992,11 @@ static void direct_link_object(FileData *fd, Object *ob)
                        }
                }
 
+               if(sb->effector_weights)
+                       sb->effector_weights = newdataadr(fd, sb->effector_weights);
+               else
+                       sb->effector_weights = BKE_add_effector_weights(NULL);
+
                direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache);
        }
        ob->bsoft= newdataadr(fd, ob->bsoft);
@@ -9702,6 +9734,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Object *ob;
                Material *ma;
                Tex *tex;
+               ParticleSettings *part;
+               int do_gravity = 0;
 
                for(sce = main->scene.first; sce; sce = sce->id.next)
                        if(sce->unit.scale_length == 0.0f)
@@ -9741,6 +9775,48 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        sce->audio.doppler_factor = 1.0;
                        sce->audio.speed_of_sound = 343.3;
                }
+
+               /* Add default gravity to scenes */
+               for(sce= main->scene.first; sce; sce= sce->id.next) {
+                       if((sce->physics_settings.flag & PHYS_GLOBAL_GRAVITY) == 0
+                               && VecLength(sce->physics_settings.gravity) == 0.0f) {
+
+                               sce->physics_settings.gravity[0] = sce->physics_settings.gravity[1] = 0.0f;
+                               sce->physics_settings.gravity[2] = -9.81f;
+                               sce->physics_settings.flag = PHYS_GLOBAL_GRAVITY;
+                               do_gravity = 1;
+                       }
+               }
+
+               /* Assign proper global gravity weights for dynamics (only z-coordinate is taken into account) */
+               if(do_gravity) for(part= main->particle.first; part; part= part->id.next)
+                       part->effector_weights->global_gravity = part->acc[2]/-9.81f;
+
+               for(ob = main->object.first; ob; ob = ob->id.next) {
+                       ModifierData *md;
+
+                       if(do_gravity) {
+                               for(md= ob->modifiers.first; md; md= md->next) {
+                                       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+                                       if(clmd)
+                                               clmd->sim_parms->effector_weights->global_gravity = clmd->sim_parms->gravity[2]/-9.81;
+                               }
+
+                               if(ob->soft)
+                                       ob->soft->effector_weights->global_gravity = ob->soft->grav/9.81;
+                       }
+
+                       /* Normal wind shape is plane */
+                       if(ob->pd) {
+                               if(ob->pd->forcefield == PFIELD_WIND)
+                                       ob->pd->shape = PFIELD_SHAPE_PLANE;
+                               
+                               if(ob->pd->flag & PFIELD_PLANAR)
+                                       ob->pd->shape = PFIELD_SHAPE_PLANE;
+                               else if(ob->pd->flag & PFIELD_SURFACE)
+                                       ob->pd->shape = PFIELD_SHAPE_SURFACE;
+                       }
+               }
        }
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
index fda35d28d0e4623ec02ee3d1dae90feeb903a38b..528704208335622d912401d3a08f3a96214ee295 100644 (file)
@@ -620,6 +620,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
                        if (part->adt) write_animdata(wd, part->adt);
                        writestruct(wd, DATA, "PartDeflect", 1, part->pd);
                        writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
+                       writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights);
 
                        if(part->boids && part->phystype == PART_PHYS_BOIDS) {
                                BoidState *state = part->boids->states.first;
@@ -1140,6 +1141,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                        
                        writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
                        writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
+                       writestruct(wd, DATA, "EffectorWeights", 1, clmd->sim_parms->effector_weights);
                        write_pointcaches(wd, &clmd->ptcaches);
                } 
                else if(md->type==eModifierType_Smoke) {
@@ -1227,7 +1229,10 @@ static void write_objects(WriteData *wd, ListBase *idbase)
                        
                        writestruct(wd, DATA, "PartDeflect", 1, ob->pd);
                        writestruct(wd, DATA, "SoftBody", 1, ob->soft);
-                       if(ob->soft) write_pointcaches(wd, &ob->soft->ptcaches);
+                       if(ob->soft) {
+                               write_pointcaches(wd, &ob->soft->ptcaches);
+                               writestruct(wd, DATA, "EffectorWeights", 1, ob->soft->effector_weights);
+                       }
                        writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft);
                        
                        write_particlesystems(wd, &ob->particlesystem);
index 05905cd42a44d33ddfd647b2d235590add20d7f6..7188368a95ffbb6fd9512ae47488412c983630e7 100644 (file)
@@ -38,6 +38,7 @@
 #include "DNA_meta_types.h"
 #include "DNA_object_fluidsim.h"
 #include "DNA_object_types.h"
+#include "DNA_object_force.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_userdef_types.h"
@@ -56,6 +57,7 @@
 #include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
+#include "BKE_effect.h"
 #include "BKE_global.h"
 #include "BKE_group.h"
 #include "BKE_lattice.h"
@@ -190,6 +192,90 @@ void OBJECT_OT_add(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", object_type_items, 0, "Type", "");
 }
 
+/********************* Add Effector Operator ********************/
+/* copy from rna_object_force.c*/
+static EnumPropertyItem field_type_items[] = {
+       {0, "NONE", 0, "None", ""},
+       {PFIELD_FORCE, "FORCE", 0, "Force", ""},
+       {PFIELD_WIND, "WIND", 0, "Wind", ""},
+       {PFIELD_VORTEX, "VORTEX", 0, "Vortex", ""},
+       {PFIELD_MAGNET, "MAGNET", 0, "Magnetic", ""},
+       {PFIELD_HARMONIC, "HARMONIC", 0, "Harmonic", ""},
+       {PFIELD_CHARGE, "CHARGE", 0, "Charge", ""},
+       {PFIELD_LENNARDJ, "LENNARDJ", 0, "Lennard-Jones", ""},
+       {PFIELD_TEXTURE, "TEXTURE", 0, "Texture", ""},
+       {PFIELD_GUIDE, "GUIDE", 0, "Curve Guide", ""},
+       {PFIELD_BOID, "BOID", 0, "Boid", ""},
+       {PFIELD_TURBULENCE, "TURBULENCE", 0, "Turbulence", ""},
+       {PFIELD_DRAG, "DRAG", 0, "Drag", ""},
+       {0, NULL, 0, NULL, NULL}};
+
+void add_effector_draw(Scene *scene, View3D *v3d, int type)    /* for toolbox or menus, only non-editmode stuff */
+{
+       /* keep here to get things compile, remove later */
+}
+
+/* for effector add primitive operators */
+static Object *effector_add_type(bContext *C, int type)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *ob;
+       
+       /* for as long scene has editmode... */
+       if (CTX_data_edit_object(C)) 
+               ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
+       
+       /* deselects all, sets scene->basact */
+       if(type==PFIELD_GUIDE) {
+               ob = add_object(scene, OB_CURVE);
+               ((Curve*)ob->data)->flag |= CU_PATH|CU_3D;
+               ED_object_enter_editmode(C, 0);
+               BLI_addtail(curve_get_editcurve(ob), add_nurbs_primitive(C, CU_NURBS|CU_PRIM_PATH, 1));
+               ED_object_exit_editmode(C, EM_FREEDATA);
+       }
+       else
+               ob=     add_object(scene, OB_EMPTY);
+
+       ob->pd= object_add_collision_fields(type);
+
+       /* editor level activate, notifiers */
+       ED_base_object_activate(C, BASACT);
+
+       /* more editor stuff */
+       ED_object_base_init_from_view(C, BASACT);
+
+       DAG_scene_sort(scene);
+
+       return ob;
+}
+
+/* for object add operator */
+static int effector_add_exec(bContext *C, wmOperator *op)
+{
+       effector_add_type(C, RNA_int_get(op->ptr, "type"));
+       
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_effector_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Effector";
+       ot->description = "Add an empty object with a physics effector to the scene.";
+       ot->idname= "OBJECT_OT_effector_add";
+       
+       /* api callbacks */
+       ot->invoke= WM_menu_invoke;
+       ot->exec= effector_add_exec;
+       
+       ot->poll= ED_operator_scene_editable;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
+}
+
 /* ***************** add primitives *************** */
 /* ******  work both in and outside editmode ****** */
 
@@ -616,6 +702,8 @@ static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *eve
        uiItemS(layout);
        uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_CAMERA, "OBJECT_OT_add", "type", OB_CAMERA);
        uiItemMenuEnumO(layout, "Lamp", ICON_OUTLINER_OB_LAMP, "OBJECT_OT_lamp_add", "type");
+       uiItemS(layout);
+       uiItemMenuEnumO(layout, "Force Field", ICON_OUTLINER_OB_EMPTY, "OBJECT_OT_effector_add", "type");
        
        uiPupMenuEnd(C, pup);
        
index ee0b043a9a1a317aafa66e00da5219baac7ccd7b..54df3ae92da4226a79b3c97d5f076bebb47924a2 100644 (file)
@@ -346,6 +346,7 @@ void ED_object_exit_editmode(bContext *C, int flag)
                        if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
                                pid->cache->flag |= PTCACHE_OUTDATED;
                }
+               BLI_freelistN(&pidlist);
                
                BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
 
index c5499ef8f5df65c490bf1ebafd4df85380e23a2d..474715c593b1bdac545deaa88ec2e819285c003a 100644 (file)
@@ -91,6 +91,7 @@ void OBJECT_OT_text_add(struct wmOperatorType *ot);
 void OBJECT_OT_armature_add(struct wmOperatorType *ot);
 void OBJECT_OT_lamp_add(struct wmOperatorType *ot);
 void OBJECT_OT_primitive_add(struct wmOperatorType *ot); /* only used as menu */
+void OBJECT_OT_effector_add(struct wmOperatorType *ot);
 
 void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
 void OBJECT_OT_duplicate(struct wmOperatorType *ot);
index cc8cc420bf725133e68090da67816acb20b4a904..7f0f1876417a176c170f591caedd85aae26d1888 100644 (file)
@@ -110,7 +110,7 @@ int ED_object_modifier_add(ReportList *reports, Scene *scene, Object *ob, int ty
                }
                else if(type == eModifierType_Collision) {
                        if(!ob->pd)
-                               ob->pd= object_add_collision_fields();
+                               ob->pd= object_add_collision_fields(0);
 
                        ob->pd->deflect= 1;
                        DAG_scene_sort(scene);
@@ -159,8 +159,8 @@ int ED_object_modifier_remove(ReportList *reports, Scene *scene, Object *ob, Mod
         DAG_scene_sort(scene);
        }
        else if(md->type == eModifierType_Surface) {
-               if(ob->pd)
-                       ob->pd->flag &= ~PFIELD_SURFACE;
+               if(ob->pd && ob->pd->shape == PFIELD_SHAPE_SURFACE)
+                       ob->pd->shape = PFIELD_SHAPE_PLANE;
 
         DAG_scene_sort(scene);
        }
index 3f975d1e80770ae166f5d3013d32983b192c3f07..9bfd6a4201c963a18978bc7472c32c4bb823a862 100644 (file)
@@ -117,6 +117,7 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_armature_add);
        WM_operatortype_append(OBJECT_OT_lamp_add);
        WM_operatortype_append(OBJECT_OT_add);
+       WM_operatortype_append(OBJECT_OT_effector_add);
        WM_operatortype_append(OBJECT_OT_primitive_add);
        WM_operatortype_append(OBJECT_OT_mesh_add);
        WM_operatortype_append(OBJECT_OT_metaball_add);
index 47d073e2dbba0c4dac2a7c23d5ae9a9fe4219674..0b63f1a98ff158182113283716deef38bc4eb482 100644 (file)
@@ -78,7 +78,7 @@ static int rule_add_exec(bContext *C, wmOperator *op)
 
        BLI_addtail(&state->rules, rule);
 
-       psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
+       DAG_id_flush_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
        
        return OPERATOR_FINISHED;
@@ -129,7 +129,7 @@ static int rule_del_exec(bContext *C, wmOperator *op)
                rule->flag |= BOIDRULE_CURRENT;
 
        DAG_scene_sort(scene);
-       psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
+       DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
 
        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
        
@@ -168,7 +168,7 @@ static int rule_move_up_exec(bContext *C, wmOperator *op)
                        BLI_remlink(&state->rules, rule);
                        BLI_insertlink(&state->rules, rule->prev->prev, rule);
 
-                       psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
+                       DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
                        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
                        break;
                }
@@ -207,7 +207,7 @@ static int rule_move_down_exec(bContext *C, wmOperator *op)
                        BLI_remlink(&state->rules, rule);
                        BLI_insertlink(&state->rules, rule->next, rule);
 
-                       psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
+                       DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
                        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
                        break;
                }
@@ -303,7 +303,7 @@ static int state_del_exec(bContext *C, wmOperator *op)
        state->flag |= BOIDSTATE_CURRENT;
 
        DAG_scene_sort(scene);
-       psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
+       DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
 
        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
        
@@ -378,7 +378,7 @@ static int state_move_down_exec(bContext *C, wmOperator *op)
                if(state->flag & BOIDSTATE_CURRENT && state->next) {
                        BLI_remlink(&boids->states, state);
                        BLI_insertlink(&boids->states, state->next, state);
-                       psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
+                       DAG_id_flush_update(&psys->part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
                        break;
                }
        }
index 60ae91e7a897f3f4051b132ce7a58173a88a8242..db3b7130ab3d06ad3b2ee674af970719e334adad 100644 (file)
@@ -3159,9 +3159,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                ma_g = ma->g;
                ma_b = ma->b;
 
-               pdd->ma_r = &ma_r;
-               pdd->ma_g = &ma_g;
-               pdd->ma_b = &ma_b;
+               if(pdd) {
+                       pdd->ma_r = &ma_r;
+                       pdd->ma_g = &ma_g;
+                       pdd->ma_b = &ma_b;
+               }
 
                create_cdata = 1;
        }
index 8d709d1b38a74e8f196cab1c078a58c4125c6084..f6d30a7bec9f4be273b96ff409df7d851a3aea29 100644 (file)
@@ -4848,6 +4848,7 @@ void special_aftertrans_update(TransInfo *t)
                                        if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
                                                pid->cache->flag |= PTCACHE_OUTDATED;
                                }
+                               BLI_freelistN(&pidlist);
 
                                /* pointcache refresh */
                                if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
index 5cfecf7cc019318db800a5ebf4c1c8416c0e5daa..9423e871c776cab38e4e7c1d2e12681e0f629684 100644 (file)
@@ -79,6 +79,8 @@ typedef struct ClothSimSettings
        short   vgroup_struct;  /* vertex group for scaling structural stiffness */
        short   presets; /* used for presets on GUI */
        short   pad;
+
+       struct EffectorWeights *effector_weights;
 } ClothSimSettings;
 
 
index 468ad35de852e69196d387327e2f37a90ff78fa4..e7e785e605b9bd61f6f0a8da9e7afdca8e43ac55 100644 (file)
@@ -35,47 +35,91 @@ extern "C" {
 #endif
 
 #include "DNA_listBase.h"
+
+/* pd->forcefield:  Effector Fields types */
+typedef enum PFieldType {
+       PFIELD_NULL = 0,        /* (this is used for general effector weight)                                                   */
+       PFIELD_FORCE,           /* Force away/towards a point depending on force strength                               */
+       PFIELD_VORTEX,          /* Force around the effector normal                                                                             */
+       PFIELD_MAGNET,          /* Force from the cross product of effector normal and point velocity   */
+       PFIELD_WIND,            /* Force away and towards a point depending which side of the effector  */
+                                               /*       normal the point is                                                                                            */
+       PFIELD_GUIDE,           /* Force along curve for dynamics, a shaping curve for hair paths               */
+       PFIELD_TEXTURE,         /* Force based on texture values calculated at point coordinates                */
+       PFIELD_HARMONIC,        /* Force of a harmonic (damped) oscillator                                                              */
+       PFIELD_CHARGE,          /* Force away/towards a point depending on point charge                                 */
+       PFIELD_LENNARDJ,        /* Force due to a Lennard-Jones potential                                                               */
+       PFIELD_BOID,            /* Defines predator / goal for boids                                                                    */
+       PFIELD_TURBULENCE,      /* Force defined by BLI_gTurbulence                                                                             */
+       PFIELD_DRAG,            /* Linear & quadratic drag                                                                                              */
+       NUM_PFIELD_TYPES
+} PFieldType;
        
 typedef struct PartDeflect {
-       short deflect;          /* Deflection flag - does mesh deflect particles*/
-       short forcefield;       /* Force field type, do the vertices attract / repel particles ? */
-       short flag;                     /* general settings flag */
-       short falloff;          /* fall-off type*/
+       short deflect;          /* Deflection flag - does mesh deflect particles                                */
+       short forcefield;       /* Force field type, do the vertices attract / repel particles? */
+       short flag;                     /* general settings flag                                                                                */
+       short falloff;          /* fall-off type                                                                                                */
+       short shape;            /* point, plane or surface                                                                              */
+       short tex_mode;         /* texture effector                                                                                             */
+       short kink, kink_axis; /* for curve guide                                                                                       */
+       short zdir, rt;
        
+       /* Main effector values */
+       float f_strength;       /* The strength of the force (+ or - )                                  */
+       float f_damp;           /* Damping ratio of the harmonic effector.                              */
+       float f_flow;           /* How much force is converted into "air flow", i.e.    */
+                                               /* force used as the velocity of surrounding medium.    */
+
+       float f_size;
+
+       /* fall-off */
+       float f_power;          /* The power law - real gravitation is 2 (square)       */
+       float maxdist;          /* if indicated, use this maximum                                       */
+       float mindist;          /* if indicated, use this minimum                                       */
+       float f_power_r;        /* radial fall-off power                                                        */
+       float maxrad;           /* radial versions of above                                                     */
+       float minrad;
+
+       /* particle collisions */
        float pdef_damp;        /* Damping factor for particle deflection       */
        float pdef_rdamp;       /* Random element of damping for deflection     */
        float pdef_perm;        /* Chance of particle passing through mesh      */
        float pdef_frict;       /* Friction factor for particle deflection              */
        float pdef_rfrict;      /* Random element of friction for deflection    */
 
-       float f_strength;       /* The strength of the force (+ or - )       */
-       float f_power;          /* The power law - real gravitation is 2 (square)  */
-       float f_dist;
-       float f_damp;           /* The dampening factor, currently only for harmonic force      */
-       float maxdist;          /* if indicated, use this maximum */
-       float mindist;          /* if indicated, use this minimum */
-       float maxrad;           /* radial versions of above */
-       float minrad;
-       float f_power_r;        /* radial fall-off power*/
+       float absorption, pad;  /* used for forces */
        
+       /* softbody collisions */
        float pdef_sbdamp;      /* Damping factor for softbody deflection       */
        float pdef_sbift;       /* inner face thickness for softbody deflection */
        float pdef_sboft;       /* outer face thickness for softbody deflection */
 
-       float absorption, pad;  /* used for forces */
-
-       /* variables for guide curve */
+       /* guide curve, same as for particle child effects */
        float clump_fac, clump_pow;
        float kink_freq, kink_shape, kink_amp, free_end;
 
-       float tex_nabla;
-       short tex_mode, kink, kink_axis, rt2;
-       struct Tex *tex;        /* Texture of the texture effector */
-       struct RNG *rng; /* random noise generator for e.g. wind */
-       float f_noise; /* noise of force (currently used for wind) */
-       int seed; /* wind noise random seed */
+       /* texture effector */
+       float tex_nabla;        /* Used for calculating partial derivatives */
+       struct Tex *tex;        /* Texture of the texture effector                      */
+
+       /* effector noise */
+       struct RNG *rng;        /* random noise generator for e.g. wind */
+       float f_noise;          /* noise of force                                               */
+       int seed;                       /* noise random seed                                    */
 } PartDeflect;
 
+typedef struct EffectorWeights {
+       struct Group *group;            /* only use effectors from this group of objects */
+       
+       float weight[13];                       /* effector type specific weights */
+       float global_gravity;
+       short flag, rt[3];
+} EffectorWeights;
+
+/* EffectorWeights->flag */
+#define EFF_WEIGHT_DO_HAIR             1
+
 /* Point cache file data types:
  * - used as (1<<flag) so poke jahka if you reach the limit of 15
  * - to add new data types update:
@@ -256,48 +300,51 @@ typedef struct SoftBody {
        struct PointCache *pointcache;
        struct ListBase ptcaches;
 
-} SoftBody;
+       struct EffectorWeights *effector_weights;
 
-/* pd->forcefield:  Effector Fields types */
-#define PFIELD_FORCE   1
-#define PFIELD_VORTEX  2
-#define PFIELD_MAGNET  3
-#define PFIELD_WIND            4
-#define PFIELD_GUIDE   5
-#define PFIELD_TEXTURE 6
-#define PFIELD_HARMONIC        7
-#define PFIELD_CHARGE  8
-#define PFIELD_LENNARDJ        9
-#define PFIELD_BOID            10
+} SoftBody;
 
 
 /* pd->flag: various settings */
 #define PFIELD_USEMAX                  1
 #define PDEFLE_DEFORM                  2
-#define PFIELD_GUIDE_PATH_ADD  4
-#define PFIELD_PLANAR                  8
+#define PFIELD_GUIDE_PATH_ADD  4                       /* TODO: do_versions for below */
+#define PFIELD_PLANAR                  8                       /* used for do_versions */
 #define PDEFLE_KILL_PART               16
-#define PFIELD_POSZ                            32
+#define PFIELD_POSZ                            32                      /* used for do_versions */
 #define PFIELD_TEX_OBJECT              64
+#define PFIELD_GLOBAL_CO               64                      /* used for turbulence */
 #define PFIELD_TEX_2D                  128
 #define PFIELD_USEMIN                  256
 #define PFIELD_USEMAXR                 512
 #define PFIELD_USEMINR                 1024
 #define PFIELD_TEX_ROOTCO              2048
-#define PFIELD_SURFACE                 4096
+#define PFIELD_SURFACE                 (1<<12)         /* used for do_versions */
+#define PFIELD_VISIBILITY              (1<<13)
+#define PFIELD_DO_LOCATION             (1<<14)
+#define PFIELD_DO_ROTATION             (1<<15)
 
 /* pd->falloff */
 #define PFIELD_FALL_SPHERE             0
 #define PFIELD_FALL_TUBE               1
 #define PFIELD_FALL_CONE               2
-//reserved for near future
-//#define PFIELD_FALL_INSIDE           3
+
+/* pd->shape */
+#define PFIELD_SHAPE_POINT             0
+#define PFIELD_SHAPE_PLANE             1
+#define PFIELD_SHAPE_SURFACE   2
+#define PFIELD_SHAPE_POINTS            3
 
 /* pd->tex_mode */
 #define PFIELD_TEX_RGB 0
 #define PFIELD_TEX_GRAD        1
 #define PFIELD_TEX_CURL        2
 
+/* pd->zdir */
+#define PFIELD_Z_BOTH  0
+#define PFIELD_Z_POS   1
+#define PFIELD_Z_NEG   2
+
 /* pointcache->flag */
 #define PTCACHE_BAKED                          1
 #define PTCACHE_OUTDATED                       2
index 089c1c76bcf0828ed8b44c005556320bb6b02dae..4c620ae527e4c643442db0d528215e6e52e91941 100644 (file)
@@ -114,6 +114,8 @@ typedef struct ParticleSettings {
 
        struct BoidSettings *boids;
 
+       struct EffectorWeights *effector_weights;
+
        int flag;
        short type, from, distr;
        /* physics modes */
@@ -176,10 +178,8 @@ typedef struct ParticleSettings {
        /* keyed particles */
        int keyed_loops;
 
-       float effector_weight[10];
-
        struct Group *dup_group;
-       struct Group *eff_group;
+       struct Group *eff_group;                // deprecated
        struct Object *dup_ob;
        struct Object *bb_ob;
        struct Ipo *ipo;                                // xxx depreceated... old animation system
@@ -209,8 +209,6 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
        struct Object *lattice;
        struct Object *parent;                                  /* particles from global space -> parent space */
 
-       struct ListBase effectors, reactevents; /* runtime */
-
        struct ListBase targets;                                /* used for keyed and boid physics */
 
        char name[32];                                                  /* particle system name */
@@ -233,6 +231,8 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
        struct PointCache *pointcache;
        struct ListBase ptcaches;
 
+       struct ListBase *effectors;
+
        struct KDTree *tree;                                    /* used for interactions with self and other systems */
 
        struct ParticleDrawData *pdd;
@@ -270,7 +270,7 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 #define PART_ROT_DYN           (1<<14) /* dynamic rotation */
 #define PART_SIZEMASS          (1<<16)
 
-//#define PART_KEYED_TIMING    (1<<15)
+//#define PART_HAIR_GRAVITY    (1<<15)
 
 //#define PART_ABS_TIME                (1<<17)
 //#define PART_GLOB_TIME               (1<<18)
@@ -407,11 +407,13 @@ typedef struct ParticleSystem{                            /* note, make sure all (runtime) are NULL's in
 #define PART_CHILD_FACES               2
 
 /* psys->recalc */
-#define PSYS_RECALC_REDO       1       /* only do pathcache etc */
-#define PSYS_RECALC_RESET      2       /* reset everything including pointcache */
-#define PSYS_RECALC_TYPE       4       /* handle system type change */
-#define PSYS_RECALC_CHILD      16      /* only child settings changed */
-#define PSYS_RECALC_PHYS       32      /* physics type changed */
+/* starts from 8 so that the first bits can be ob->recalc */
+#define PSYS_RECALC_REDO       8       /* only do pathcache etc */
+#define PSYS_RECALC_RESET      16      /* reset everything including pointcache */
+#define PSYS_RECALC_TYPE       32      /* handle system type change */
+#define PSYS_RECALC_CHILD      64      /* only child settings changed */
+#define PSYS_RECALC_PHYS       128     /* physics type changed */
+#define PSYS_RECALC                    248
 
 /* psys->flag */
 #define PSYS_CURRENT           1
@@ -436,7 +438,7 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 #define PARS_REKEY                     8
 
 /* pars->alive */
-#define PARS_KILLED                    0
+//#define PARS_KILLED                  0 /* deprecated */
 #define PARS_DEAD                      1
 #define PARS_UNBORN                    2
 #define PARS_ALIVE                     3
index 5521f0e93155b385e4f19b110468231a623e6736..c5691b471572323da5e9e67d965e05a288582c85 100644 (file)
@@ -667,6 +667,11 @@ typedef struct UnitSettings {
        short flag; /* imperial, metric etc */
 } UnitSettings;
 
+typedef struct PhysicsSettings {
+       float gravity[3];
+       int flag;
+} PhysicsSettings;
+
 typedef struct Scene {
        ID id;
        struct AnimData *adt;   /* animation data (must be immediately after id for utilities to use it) */ 
@@ -731,6 +736,9 @@ typedef struct Scene {
        
        /* Grease Pencil */
        struct bGPdata *gpd;
+
+       /* Physics simulation settings */
+       struct PhysicsSettings physics_settings;
 } Scene;
 
 
@@ -1127,6 +1135,9 @@ typedef enum SculptFlags {
 #define        SK_RETARGET_ROLL_VIEW                   1
 #define        SK_RETARGET_ROLL_JOINT                  2
 
+/* physics_settings->flag */
+#define PHYS_GLOBAL_GRAVITY            1
+
 /* UnitSettings */
 
 /* UnitSettings->system */
index 8002aa89313e87aed4e81dd893e457285df56aae..36a648c8a82f061452e6d01a8f98c83d31086454 100644 (file)
@@ -74,44 +74,33 @@ EnumPropertyItem boidruleset_type_items[] ={
 
 static void rna_Boids_reset(bContext *C, PointerRNA *ptr)
 {
-       Scene *scene = CTX_data_scene(C);
-       ParticleSettings *part;
-
        if(ptr->type==&RNA_ParticleSystem) {
                ParticleSystem *psys = (ParticleSystem*)ptr->data;
-               Object *ob = psys_find_object(scene, psys);
                
                psys->recalc = PSYS_RECALC_RESET;
 
-               if(ob)
-                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
-       }
-       else {
-               part = ptr->id.data;
-               psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
+               DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA);
        }
+       else
+               DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET);
 
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL);
 }
 static void rna_Boids_reset_deps(bContext *C, PointerRNA *ptr)
 {
        Scene *scene = CTX_data_scene(C);
-       ParticleSettings *part;
 
        if(ptr->type==&RNA_ParticleSystem) {
                ParticleSystem *psys = (ParticleSystem*)ptr->data;
-               Object *ob = psys_find_object(scene, psys);
                
                psys->recalc = PSYS_RECALC_RESET;
 
-               if(ob)
-                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
-       }
-       else {
-               part = ptr->id.data;
-               psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
-               DAG_scene_sort(scene);
+               DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA);
        }
+       else
+               DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET);
+
+       DAG_scene_sort(scene);
 
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL);
 }
index 22cc2e2c9c34d1f14c8b4dbcc38017bac85aa242..d64e2c7119b31fb65f1d020f517555849b5eb6fb 100644 (file)
@@ -306,6 +306,11 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Bending Stiffness Vertex Group", "Vertex group for fine control over bending stiffness.");
        RNA_def_property_update(prop, 0, "rna_cloth_update");
 
+       prop= RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "EffectorWeights");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Effector Weights", "");
+
        /* unused */
 
        /* unused still
index a2b4d6d7335dd6aa7a63cf45b0bda15037295473..afc820165023670cedf71119558995af9a96f5b3 100644 (file)
@@ -741,7 +741,7 @@ static PointerRNA rna_Object_field_get(PointerRNA *ptr)
 
        /* weak */
        if(!ob->pd)
-               ob->pd= object_add_collision_fields();
+               ob->pd= object_add_collision_fields(0);
        
        return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, ob->pd);
 }
@@ -752,7 +752,7 @@ static PointerRNA rna_Object_collision_get(PointerRNA *ptr)
 
        /* weak */
        if(!ob->pd)
-               ob->pd= object_add_collision_fields();
+               ob->pd= object_add_collision_fields(0);
        
        return rna_pointer_inherit_refine(ptr, &RNA_CollisionSettings, ob->pd);
 }
index 1f0d01ce784b4a247bd05bf8a598fabd2438087c..652a80a24eba3d0de5cca030849a2a61d555dae7 100644 (file)
 
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
+#include "DNA_particle_types.h"
 #include "DNA_scene_types.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
+EnumPropertyItem effector_shape_items[] = {
+       {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
+       {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
+       {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface", ""},
+       {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem empty_shape_items[] = {
+       {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
+       {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem vortex_shape_items[] = {
+       {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""},
+       {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""},
+       {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface falloff (New)", ""},
+       {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point (New)", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem empty_vortex_shape_items[] = {
+       {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""},
+       {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
 #ifdef RNA_RUNTIME
 
 #include "MEM_guardedalloc.h"
@@ -358,65 +387,115 @@ static void rna_SoftBodySettings_goal_vgroup_set(PointerRNA *ptr, const char *va
        rna_object_vgroup_name_index_set(ptr, value, &sb->vertgroup);
 }
 
+static int particle_field_check(PointerRNA *ptr)
+{
+       ID *id= ptr->id.data;
+
+       return (GS(id->name) == ID_PA);
+}
 static void rna_FieldSettings_update(bContext *C, PointerRNA *ptr)
 {
-       Object *ob= (Object*)ptr->id.data;
+       if(particle_field_check(ptr)) {
+               ParticleSettings *part = (ParticleSettings*)ptr->id.data;
+
+               if(part->pd->forcefield != PFIELD_TEXTURE && part->pd->tex) {
+                       part->pd->tex->id.us--;
+                       part->pd->tex= 0;
+               }
+
+               if(part->pd2->forcefield != PFIELD_TEXTURE && part->pd2->tex) {
+                       part->pd2->tex->id.us--;
+                       part->pd2->tex= 0;
+               }
+
+               DAG_id_flush_update(&part->id, OB_RECALC|PSYS_RECALC_RESET);
+               WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
 
-       if(ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) {
-               ob->pd->tex->id.us--;
-               ob->pd->tex= 0;
        }
+       else {
+               Object *ob = (Object*)ptr->id.data;
 
-       DAG_id_flush_update(&ob->id, OB_RECALC_OB);
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+               if(ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) {
+                       ob->pd->tex->id.us--;
+                       ob->pd->tex= 0;
+               }
+
+               DAG_id_flush_update(&ob->id, OB_RECALC_OB);
+               WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       }
 }
 
-static void rna_FieldSettings_surface_update(bContext *C, PointerRNA *ptr)
+static void rna_FieldSettings_shape_update(bContext *C, PointerRNA *ptr)
 {
        Scene *scene= CTX_data_scene(C);
-       Object *ob= (Object*)ptr->id.data;
-       PartDeflect *pd= ob->pd;
-       ModifierData *md= modifiers_findByType(ob, eModifierType_Surface);
 
-       /* add/remove modifier as needed */
-       if(!md) {
-               if(pd && (pd->flag & PFIELD_SURFACE))
-                       if(ELEM6(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ,PFIELD_BOID))
+       if(!particle_field_check(ptr)) {
+               Object *ob= (Object*)ptr->id.data;
+               PartDeflect *pd= ob->pd;
+               ModifierData *md= modifiers_findByType(ob, eModifierType_Surface);
+
+               /* add/remove modifier as needed */
+               if(!md) {
+                       if(pd && (pd->shape == PFIELD_SHAPE_SURFACE) && ELEM(pd->forcefield,PFIELD_GUIDE,PFIELD_TEXTURE)==0)
                                if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE))
                                        ED_object_modifier_add(NULL, scene, ob, eModifierType_Surface);
-       }
-       else {
-               if(!pd || !(pd->flag & PFIELD_SURFACE))
-                       ED_object_modifier_remove(NULL, scene, ob, md);
-       }
+               }
+               else {
+                       if(!pd || pd->shape != PFIELD_SHAPE_SURFACE)
+                               ED_object_modifier_remove(NULL, scene, ob, md);
+               }
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+               WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       }
 }
 
 static void rna_FieldSettings_dependency_update(bContext *C, PointerRNA *ptr)
 {
        Scene *scene= CTX_data_scene(C);
-       Object *ob= (Object*)ptr->id.data;
 
-       /* do this before scene sort, that one checks for CU_PATH */
-       /* XXX if(ob->type==OB_CURVE && ob->pd->forcefield==PFIELD_GUIDE) {
-               Curve *cu= ob->data;
-               cu->flag |= (CU_PATH|CU_3D);
-               do_curvebuts(B_CU3D);  // all curves too
-       }*/
+       if(particle_field_check(ptr)) {
+               DAG_id_flush_update((ID*)ptr->id.data, OB_RECALC|PSYS_RECALC_RESET);
+       }
+       else {
+               Object *ob= (Object*)ptr->id.data;
 
-       rna_FieldSettings_surface_update(C, ptr);
+               /* do this before scene sort, that one checks for CU_PATH */
+               /* XXX if(ob->type==OB_CURVE && ob->pd->forcefield==PFIELD_GUIDE) {
+                       Curve *cu= ob->data;
+                       cu->flag |= (CU_PATH|CU_3D);
+                       do_curvebuts(B_CU3D);  // all curves too
+               }*/
 
-       DAG_scene_sort(scene);
+               rna_FieldSettings_shape_update(C, ptr);
 
-       if(ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE)
-               DAG_id_flush_update(&ob->id, OB_RECALC);
-       else
-               DAG_id_flush_update(&ob->id, OB_RECALC_OB);
+               DAG_scene_sort(scene);
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+               if(ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE)
+                       DAG_id_flush_update(&ob->id, OB_RECALC);
+               else
+                       DAG_id_flush_update(&ob->id, OB_RECALC_OB);
+
+               WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       }
+}
+
+static void rna_EffectorWeight_update(bContext *C, PointerRNA *ptr)
+{
+       DAG_id_flush_update((ID*)ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET);
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
 }
 
+static void rna_EffectorWeight_dependency_update(bContext *C, PointerRNA *ptr)
+{
+       Scene *scene= CTX_data_scene(C);
+
+       DAG_scene_sort(scene);
+
+       DAG_id_flush_update((ID*)ptr->id.data, OB_RECALC_DATA|PSYS_RECALC_RESET);
+
+       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
+}
 static void rna_CollisionSettings_dependency_update(bContext *C, PointerRNA *ptr)
 {
        Scene *scene= CTX_data_scene(C);
@@ -448,6 +527,47 @@ static void rna_softbody_update(bContext *C, PointerRNA *ptr)
        WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
 }
 
+
+static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+       Object *ob= NULL;
+
+       if(C==NULL) {
+               EnumPropertyItem *item= NULL;
+               int totitem= 0;
+               
+               /* needed for doc generation */
+               RNA_enum_items_add(&item, &totitem, effector_shape_items);
+               RNA_enum_items_add(&item, &totitem, empty_shape_items);
+               RNA_enum_items_add(&item, &totitem, vortex_shape_items);
+               RNA_enum_items_add(&item, &totitem, empty_shape_items);
+               RNA_enum_item_end(&item, &totitem);
+               
+               *free= 1;
+               
+               return item;
+       }
+
+       if(particle_field_check(ptr))
+               return empty_shape_items;
+       
+       ob= (Object*)ptr->id.data;
+       
+       if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
+               if(ob->pd->forcefield == PFIELD_VORTEX)
+                       return vortex_shape_items;
+
+               return effector_shape_items;
+       }
+       else {
+               if(ob->pd->forcefield == PFIELD_VORTEX)
+                       return empty_vortex_shape_items;
+
+               return empty_shape_items;
+       }
+}
+
+
 #else
 
 static void rna_def_pointcache(BlenderRNA *brna)
@@ -625,6 +745,129 @@ static void rna_def_collision(BlenderRNA *brna)
        RNA_def_property_update(prop, 0, "rna_CollisionSettings_update");
 }
 
+static void rna_def_effector_weight(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna= RNA_def_struct(brna, "EffectorWeights", NULL);
+       RNA_def_struct_ui_text(srna, "Effector Weights", "Effector weights for physics simulation.");
+       RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
+
+       /* Flags */
+       prop= RNA_def_property(srna, "do_growing_hair", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", EFF_WEIGHT_DO_HAIR);
+       RNA_def_property_ui_text(prop, "Use For Growing Hair", "Use force fields when growing hair.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+       
+       /* General */
+       prop= RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "group");
+       RNA_def_property_struct_type(prop, "Group");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this Group.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_dependency_update");
+
+       prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "global_gravity");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Gravity", "Global gravity weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       /* Effector weights */
+       prop= RNA_def_property(srna, "all", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[0]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "All", "All effector's weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "spherical", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[1]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "vortex", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[2]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Vortex", "Vortex effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "magnetic", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[3]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Magnetic", "Magnetic effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "wind", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[4]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Wind", "Wind effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "curveguide", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[5]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Curve Guide", "Curve guide effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "texture", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[6]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Texture", "Texture effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "harmonic", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[7]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Harmonic", "Harmonic effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "charge", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[8]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Charge", "Charge effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "lennardjones", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[9]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Lennard-Jones", "Lennard-Jones effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "boid", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[10]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Boid", "Boid effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "turbulence", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[11]");
+       RNA_def_property_range(prop, -200.0f, 200.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Turbulence", "Turbulence effector weight.");
+       RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
+
+       prop= RNA_def_property(srna, "drag", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "weight[12]");
+       RNA_def_property_range(prop,&