From BlenderWiki
Simulations
In this section we access Blender's simulation capacity from Python. Several of the examples were inspired by the book Bounce, Tumble and Splash by Tony Mullen. However, most renders do not look as pretty as they do in Mullen's book, since the purpose of these note is not to find the optimal way to tweak parameters, but rather to illustrate how the can be tweaked from Python.
Particles
This program adds two particle systems.
#--------------------------------------------------- # File particle.py #--------------------------------------------------- import bpy, mathutils, math from mathutils import Vector, Matrix from math import pi def run(origo): # Add emitter mesh origin = Vector(origo) bpy.ops.mesh.primitive_plane_add(location=origin) emitter = bpy.context.object # --- Particle system 1: Falling and blowing drops --- # Add first particle system bpy.ops.object.particle_system_add() psys1 = emitter.particle_systems[-1] psys1.name = 'Drops' # Emission pset1 = psys1.settings pset1.name = 'DropSettings' pset1.frame_start = 40 pset1.frame_end = 200 pset1.lifetime = 50 pset1.lifetime_random = 0.4 pset1.emit_from = 'FACE' pset1.use_render_emitter = True pset1.object_align_factor = (0,0,1) # Physics pset1.physics_type = 'NEWTON' pset1.mass = 2.5 pset1.particle_size = 0.3 pset1.use_multiply_size_mass = True # Effector weights ew = pset1.effector_weights ew.gravity = 1.0 ew.wind = 1.0 # Children pset1.child_nbr = 10 pset1.rendered_child_count = 10 pset1.child_type = 'SIMPLE' # Display and render pset1.draw_percentage = 100 pset1.draw_method = 'CROSS' pset1.material = 1 pset1.particle_size = 0.1 pset1.render_type = 'HALO' pset1.render_step = 3 # ------------ Wind effector ----- # Add wind effector bpy.ops.object.effector_add( type='WIND', enter_editmode=False, location = origin - Vector((0,3,0)), rotation = (-pi/2, 0, 0)) wind = bpy.context.object # Field settings fld = wind.field fld.strength = 2.3 fld.noise = 3.2 fld.flow = 0.3 # --- Particle system 2: Monkeys in the wind ---- # Add monkey to be used as dupli object # Hide the monkey on layer 2 layers = 20*[False] layers[1] = True bpy.ops.mesh.primitive_monkey_add( location=origin+Vector((0,5,0)), rotation = (pi/2, 0, 0), layers = layers) monkey = bpy.context.object #Add second particle system bpy.context.scene.objects.active = emitter bpy.ops.object.particle_system_add() psys2 = emitter.particle_systems[-1] psys2.name = 'Monkeys' pset2 = psys2.settings pset2.name = 'MonkeySettings' # Emission pset2.count = 4 pset2.frame_start = 1 pset2.frame_end = 50 pset2.lifetime = 250 pset2.emit_from = 'FACE' pset2.use_render_emitter = True # Velocity pset2.factor_random = 0.5 # Physics pset2.physics_type = 'NEWTON' pset2.brownian_factor = 0.5 # Effector weights ew = pset2.effector_weights ew.gravity = 0 ew.wind = 0.2 # Children pset2.child_nbr = 1 pset2.rendered_child_count = 1 pset2.child_size = 3 pset2.child_type = 'SIMPLE' # Display and render pset2.draw_percentage = 1 pset2.draw_method = 'RENDER' pset2.dupli_object = monkey pset2.material = 1 pset2.particle_size = 0.1 pset2.render_type = 'OBJECT' pset2.render_step = 3 return if __name__ == "__main__": bpy.ops.object.select_by_type(type='MESH') bpy.ops.object.delete() run((0,0,0)) bpy.ops.screen.animation_play(reverse=False, sync=False)
Hair
This program adds a sphere with hair. A strand shader is constructed for the hair.
#--------------------------------------------------- # File hair.py #--------------------------------------------------- import bpy def createHead(origin): # Add emitter mesh bpy.ops.mesh.primitive_ico_sphere_add(location=origin) ob = bpy.context.object bpy.ops.object.shade_smooth() # Create scalp vertex group, and add verts and weights scalp = ob.vertex_groups.new('Scalp') for v in ob.data.vertices: z = v.co[2] y = v.co[1] if z > 0.3 or y > 0.3: w = 2*(z-0.3) if w > 1: w = 1 scalp.add([v.index], w, 'REPLACE') return ob def createMaterials(ob): # Some material for the skin skinmat = bpy.data.materials.new('Skin') skinmat.diffuse_color = (0.6,0.3,0) # Strand material for hair hairmat = bpy.data.materials.new('Strand') hairmat.diffuse_color = (0.2,0.04,0.0) hairmat.specular_intensity = 0 # Transparency hairmat.use_transparency = True hairmat.transparency_method = 'Z_TRANSPARENCY' hairmat.alpha = 0 # Strand. Must use Blender units before sizes are pset. strand = hairmat.strand strand.use_blender_units = True strand.root_size = 0.01 strand.tip_size = 0.0025 strand.size_min = 0.001 #strand.use_surface_diffuse = True # read-only strand.use_tangent_shading = True # Texture tex = bpy.data.textures.new('Blend', type = 'BLEND') tex.progression = 'LINEAR' tex.use_flip_axis = 'HORIZONTAL' # Create a color ramp for color and alpha tex.use_color_ramp = True tex.color_ramp.interpolation = 'B_SPLINE' # Points in color ramp: (pos, rgba) # Have not figured out how to add points to ramp rampTable = [ (0.0, (0.23,0.07,0.03,0.75)), #(0.2, (0.4,0.4,0,0.5)), #(0.7, (0.6,0.6,0,0.5)), (1.0, (0.4,0.3,0.05,0)) ] elts = tex.color_ramp.elements n = 0 for (pos, rgba) in rampTable: elts[n].position = pos elts[n].color = rgba n += 1 # Add blend texture to hairmat mtex = hairmat.texture_slots.add() mtex.texture = tex mtex.texture_coords = 'STRAND' mtex.use_map_color_diffuse = True mtex.use_map_alpha = True # Add materials to mesh ob.data.materials.append(skinmat) # Material 1 = Skin ob.data.materials.append(hairmat) # Material 2 = Strand return def createHair(ob): # Create hair particle system bpy.ops.object.particle_system_add() psys = ob.particle_systems.active psys.name = 'Hair' # psys.global_hair = True psys.vertex_group_density = 'Scalp' pset = psys.settings pset.type = 'HAIR' pset.name = 'HairSettings' # Emission pset.count = 40 pset.hair_step = 7 pset.emit_from = 'FACE' # Render pset.material = 2 pset.use_render_emitter = True pset.render_type = 'PATH' pset.use_strand_primitive = True pset.use_hair_bspline = True # Children pset.child_type = 'SIMPLE' pset.child_nbr = 10 pset.rendered_child_count = 500 pset.child_length = 1.0 pset.child_length_threshold = 0.0 pset.child_roundness = 0.4 pset.clump_factor = 0.862 pset.clump_shape = 0.999 pset.roughness_endpoint = 0.0 pset.roughness_end_shape = 1.0 pset.roughness_1 = 0.0 pset.roughness_1_size = 1.0 pset.roughness_2 = 0.0 pset.roughness_2_size = 1.0 pset.roughness_2_threshold = 0.0 pset.kink = 'CURL' pset.kink_amplitude = 0.2 pset.kink_shape = 0.0 pset.kink_frequency = 2.0 return def run(origin): ob = createHead(origin) createMaterials(ob) createHair(ob) return if __name__ == "__main__": bpy.ops.object.select_by_type(type='MESH') bpy.ops.object.delete() run((0,0,0))
Editable hair
This program adds a sphere with editable hair from given hair guides. If we toggle to edit mode, all strands become straight, i.e. the editing is lost. This is prevented if you toggle to particle mode, select the object, and toggle back into object mode. Unfortunately, I have not found a way to do this with a script.
#--------------------------------------------------- # File edit_hair.py # Has flaws, but may be of interest anyway. #--------------------------------------------------- import bpy def createHead(): # Add emitter mesh bpy.ops.mesh.primitive_ico_sphere_add() ob = bpy.context.object ob.name = 'EditedHair' bpy.ops.object.shade_smooth() return ob def createHair(ob, guides): nGuides = len(guides) nSteps = len(guides[0]) # Create hair particle system bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.particle_system_add() psys = ob.particle_systems.active psys.name = 'Hair' # Particle settings pset = psys.settings pset.type = 'HAIR' pset.name = 'HairSettings' pset.count = nGuides pset.hair_step = nSteps-1 pset.emit_from = 'FACE' pset.use_render_emitter = True # Children pset.child_type = 'SIMPLE' pset.child_nbr = 6 pset.rendered_child_count = 300 pset.child_length = 1.0 pset.child_length_threshold = 0.0 # Disconnect hair and switch to particle edit mode bpy.ops.particle.disconnect_hair(all=True) bpy.ops.particle.particle_edit_toggle() # Set all hair-keys dt = 100.0/(nSteps-1) dw = 1.0/(nSteps-1) for m in range(nGuides): guide = guides[m] part = psys.particles[m] part.location = guide[0] for n in range(1, nSteps): point = guide[n] h = part.hair_keys[n-1] h.co_hair_space = point h.time = n*dt h.weight = 1.0 - n*dw # Toggle particle edit mode bpy.ops.particle.select_all(action='SELECT') bpy.ops.particle.particle_edit_toggle() # Connect hair to mesh # Segmentation violation during render if this line is absent. bpy.ops.particle.connect_hair(all=True) # Unfortunately, here a manual step appears to be needed: # 1. Toggle to particle mode # 2. Touch object with a brush # 3. Toggle to object mode # 4. Toggle to edit mode # 5. Toggle to object mode # This should correspond to the code below, but fails due to # wrong context ''' bpy.ops.particle.particle_edit_toggle() bpy.ops.particle.brush_edit() bpy.ops.particle.particle_edit_toggle() bpy.ops.object.editmode_toggle() bpy.ops.object.editmode_toggle() ''' return # Hair guides. Four hair with five points each. hairGuides = [ [(-0.334596,0.863821,0.368362), (-0.351643,2.33203,-0.24479), (0.0811583,2.76695,-0.758137), (0.244019,2.73683,-1.5408), (0.199297,2.60424,-2.32847)], [(0.646501,0.361173,0.662151), (1.33538,-0.15509,1.17099), (2.07275,0.296789,0.668891), (2.55172,0.767097,-0.0723231), (2.75942,1.5089,-0.709962)], [(-0.892345,-0.0182112,0.438324), (-1.5723,0.484807,0.971839), (-2.2393,0.116525,0.324168), (-2.18426,-0.00867975,-0.666435), (-1.99681,-0.0600535,-1.64737)], [(-0.0154996,0.0387489,0.995887), (-0.205679,-0.528201,1.79738), (-0.191354,0.36126,2.25417), (0.0876127,1.1781,1.74925), (0.300626,1.48545,0.821801)] ] def run(origin): ob = createHead() createHair(ob, hairGuides) ob.location = origin return if __name__ == "__main__": run((0,0,0))
Cloth
This program adds a plane with a cloth modifier. The plane is parented to a hoop which moves downward, where it meets a sphere obstacle. The influence of the cloth modifier is controlled by a vertex group, which means that the corners move with the hoop while the middle is deformed by the obstacle. The plane is given a material with stress-mapped transparency.
#---------------------------------------------------------- # File cloth.py #---------------------------------------------------------- import bpy, mathutils, math from mathutils import Vector def run(origin): side = 4 diagonal = side/math.sqrt(2) hoopRad = 0.1 eps = 0.75 nDivs = 40 scn = bpy.context.scene # Add a sphere acting as a collision object bpy.ops.mesh.primitive_ico_sphere_add(location=origin) sphere = bpy.context.object bpy.ops.object.shade_smooth() # Add a collision modifier to the sphere bpy.ops.object.modifier_add(type='COLLISION') cset = sphere.modifiers[0].settings cset.thickness_outer = 0.2 cset.thickness_inner = 0.5 cset.permeability = 0.2 cset.stickness = 0.2 bpy.ops.object.modifier_add(type='SUBSURF') # Add ring center = origin+Vector((0,0,2)) bpy.ops.mesh.primitive_torus_add( major_radius= diagonal + hoopRad, minor_radius= hoopRad, location=center, rotation=(0, 0, 0)) bpy.ops.object.shade_smooth() ring = bpy.context.object # Add a plane over the sphere and parent it to ring bpy.ops.mesh.primitive_plane_add(location=(0,0,0)) bpy.ops.transform.resize(value=(side/2,side/2,1)) bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.subdivide(number_cuts=nDivs) bpy.ops.object.mode_set(mode='OBJECT') plane = bpy.context.object plane.parent = ring me = plane.data # Create vertex group. Object must not be active? scn.objects.active = None grp = plane.vertex_groups.new('Group') for v in plane.data.vertices: r = v.co - center x = r.length/diagonal w = 3*(x-eps)/(1-eps) if w > 1: w = 1 if w > 0: grp.add([v.index], w, 'REPLACE') # Reactivate plane scn.objects.active = plane # Add cloth modifier cloth = plane.modifiers.new(name='Cloth', type='CLOTH') cset = cloth.settings cset.use_pin_cloth = True cset.vertex_group_mass = 'Group' # Silk presets, copied from "scripts/presets/cloth/silk.py" cset.quality = 5 cset.mass = 0.150 cset.structural_stiffness = 5 cset.bending_stiffness = 0.05 cset.spring_damping = 0 cset.air_damping = 1 # Smooth shading plane.select = True bpy.ops.object.shade_smooth() bpy.ops.object.modifier_add(type='SUBSURF') # Blend texture tex = bpy.data.textures.new('Blend', type = 'BLEND') tex.progression = 'SPHERICAL' tex.intensity = 1.0 tex.contrast = 1.0 tex.use_color_ramp = True elts = tex.color_ramp.elements elts[0].color = (0, 0, 0, 1) elts[0].position = 0.56 elts[1].color = (1, 1, 1, 0) elts[1].position = 0.63 # Rubber material mat = bpy.data.materials.new('Rubber') mat.diffuse_color = (1,0,0) mat.use_transparency = True mat.alpha = 0.25 mtex = mat.texture_slots.add() mtex.texture = tex mtex.texture_coords = 'STRESS' mtex.use_map_color_diffuse = True mtex.diffuse_color_factor = 0.25 mtex.use_map_alpha = True mtex.alpha_factor = 1.0 mtex.blend_type = 'ADD' # Add material to plane plane.data.materials.append(mat) # Animate ring ring.location = center ring.keyframe_insert('location', index=2, frame=1) ring.location = origin - Vector((0,0,0.5)) ring.keyframe_insert('location', index=2, frame=20) ring.location = center return if __name__ == "__main__": bpy.ops.object.select_by_type(type='MESH') bpy.ops.object.delete() run(Vector((0,0,0))) scn = bpy.context.scene scn.frame_current = 1 bpy.ops.screen.animation_play()
Softbodies
This program adds a sphere with a softbody modifier and a plane obstacle.
#---------------------------------------------------------- # File softbody.py #---------------------------------------------------------- import bpy import mathutils from mathutils import Vector def run(origin): # Add materials red = bpy.data.materials.new('Red') red.diffuse_color = (1,0,0) blue = bpy.data.materials.new('Blue') blue.diffuse_color = (0,0,1) # Add a cone bpy.ops.mesh.primitive_cone_add( vertices=4, radius=1.5, cap_end=True) ob1 = bpy.context.object me1 = ob1.data bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.subdivide(number_cuts=5, smoothness=1, fractal=1) bpy.ops.object.mode_set(mode='OBJECT') # Weirdly, need new mesh which is a copy of verts = [] faces = [] for v in me1.vertices: verts.append(v.co) for f in me1.faces: faces.append(f.vertices) me2 = bpy.data.meshes.new('Drop') me2.from_pydata(verts, [], faces) me2.update(calc_edges=True) # Set faces smooth for f in me2.faces: f.use_smooth = True # Add new object and make it active ob2 = bpy.data.objects.new('Drop', me2) scn = bpy.context.scene scn.objects.link(ob2) scn.objects.unlink(ob1) scn.objects.active = ob2 # Add vertex groups top = ob2.vertex_groups.new('Top') bottom = ob2.vertex_groups.new('Bottom') for v in me2.vertices: w = v.co[2] - 0.2 if w < 0: if w < -1: w = -1 bottom.add([v.index], -w, 'REPLACE') elif w > 0: if w > 1: w = 1 top.add([v.index], w, 'REPLACE') bpy.ops.object.mode_set(mode='OBJECT') ob2.location = origin me2.materials.append(blue) # Add a softbody modifier mod = ob2.modifiers.new(name='SoftBody', type='SOFT_BODY') sbset = mod.settings # Soft body sbset.friction = 0.6 sbset.speed = 0.4 sbset.mass = 8.1 # Goal sbset.goal_default = 0.7 sbset.goal_spring = 0.3 sbset.goal_friction = 0.0 sbset.vertex_group_goal = 'Top' # Soft body edges sbset.pull = 0.6 sbset.push = 0.1 sbset.bend = 0.1 sbset.aerodynamics_type = 'LIFT_FORCE' sbset.aero = 0.5 # Add a vortex bpy.ops.object.effector_add( type='VORTEX', location=origin+Vector((0,0,-4))) vortex = bpy.context.object fset = vortex.field fset.strength = 4.5 fset.shape = 'PLANE' fset.apply_to_location = False fset.apply_to_rotation = True fset.falloff_type = 'TUBE' # Add collision plane # Warning. Collision objects make simulation very slow! bpy.ops.mesh.primitive_plane_add( location=origin-Vector((0,0,1.7))) bpy.ops.transform.resize(value=(4, 4, 4)) plane = bpy.context.object plane.data.materials.append(red) mod = plane.modifiers.new(name='Collision', type='COLLISION') return if __name__ == "__main__": bpy.context.scene.frame_end = 600 bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete() run(Vector((0,0,6))) bpy.ops.screen.animation_play() #bpy.ops.render.opengl(animation=True)
Cloth, softbodies and displacement textures
This program illustrates three different methods to make a waving flag: with a cloth modifier, with a softbody modifier, and with animated displacement textures.
#---------------------------------------------------------- # File flags.py # Creates a softbody flag and a cloth flag in the wind. # Update to API rev. 36816 #---------------------------------------------------------- import bpy, mathutils, math from mathutils import Vector from math import pi # Flag size, global variables xmax = 40 zmax = 24 ds = 2.0/xmax def makeFlag(name, origin, invert): # Add new mesh that will be the flag me = bpy.data.meshes.new(name) flag = bpy.data.objects.new(name, me) scn = bpy.context.scene scn.objects.link(flag) scn.objects.active = flag # Build flag mesh verts = [] faces = [] for x in range(xmax): for z in range(zmax): verts.append(((x+0.5)*ds, 0, z*ds)) if x > 0 and z > 0: faces.append(((x-1)*zmax+(z-1), (x-1)*zmax+z, x*zmax+z, x*zmax+(z-1))) me.from_pydata(verts, [], faces) me.update(calc_edges=True) flag.location = origin # Add vertex groups grp = flag.vertex_groups.new('Pole') for v in me.vertices: w = 1.5 - 7*v.co[0] if invert: if w > 1: grp.add([v.index], 0.0, 'REPLACE') else: grp.add([v.index], 1-w, 'REPLACE') else: if w > 1: grp.add([v.index], 1.0, 'REPLACE') elif w > 0: grp.add([v.index], w, 'REPLACE') bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.shade_smooth() return flag def makePole(origin): bpy.ops.mesh.primitive_cylinder_add( vertices=32, radius=ds/2, depth=1, cap_ends=True) bpy.ops.transform.resize(value=(1, 1, 2.5)) pole = bpy.context.object pole.location = origin return pole def addSoftBodyModifier(ob): mod = ob.modifiers.new(name='SoftBody', type='SOFT_BODY') sbset = mod.settings # Soft body sbset.friction = 0.3 sbset.speed = 1.4 sbset.mass = 0.9 # Goal sbset.goal_default = 0.3 sbset.goal_spring = 0.1 sbset.goal_friction = 0.1 sbset.vertex_group_goal = 'Pole' # Soft body edges sbset.pull = 0.1 sbset.push = 0.1 sbset.bend = 0.1 sbset.aerodynamics_type = 'LIFT_FORCE' sbset.aero = 0.5 #Effector weights ew = sbset.effector_weights ew.gravity = 0.1 ew.wind = 0.8 return def addClothModifier(ob): cloth = ob.modifiers.new(name='Cloth', type='CLOTH') cset = cloth.settings cset.quality = 4 cset.mass = 0.2 cset.structural_stiffness = 0.5 cset.bending_stiffness = 0.05 cset.spring_damping = 0 cset.air_damping = 0.3 cset.use_pin_cloth = True cset.vertex_group_mass = 'Pole' #Effector weights ew = cset.effector_weights ew.gravity = 0.1 ew.wind = 1.0 return def addWindEffector(origin): # Add wind effector bpy.ops.object.effector_add( type='WIND', location=origin, rotation=(pi/2,0,0)) wind = bpy.context.object fset = wind.field fset.strength = -2.0 fset.noise = 10.0 fset.flow = 0.8 fset.shape = 'PLANE' return def addFlagMaterial(name, ob, color1, color2): # Flag texture tex = bpy.data.textures.new('Flag', type = 'WOOD') tex.noise_basis_2 = 'TRI' tex.wood_type = 'RINGS' # Create material mat = bpy.data.materials.new(name) mat.diffuse_color = color1 # Add texture slot for color texture mtex = mat.texture_slots.add() mtex.texture = tex mtex.texture_coords = 'ORCO' mtex.use_map_color_diffuse = True mtex.color = color2 # Add material to flags ob.data.materials.append(mat) return mat def createDisplacementTexture(mat): tex = bpy.data.textures.new('Flag', type = 'WOOD') tex.noise_basis_2 = 'SIN' tex.wood_type = 'BANDNOISE' tex.noise_type = 'SOFT_NOISE' tex.noise_scale = 0.576 tex.turbulence = 9.0 # Store texture in material for easy access. Not really necessary mtex = mat.texture_slots.add() mtex.texture = tex mat.use_textures[1] = False return tex def addDisplacementModifier(ob, tex, vgrp, empty): mod = ob.modifiers.new('Displace', 'DISPLACE') mod.texture = tex mod.vertex_group = vgrp mod.direction = 'NORMAL' mod.texture_coords = 'OBJECT' mod.texture_coords_object = empty mod.mid_level = 0.0 mod.strength = 0.1 print("'%s' '%s'" % (vgrp, mod.vertex_group)) mod.vertex_group = vgrp print("'%s' '%s'" % (vgrp, mod.vertex_group)) return mod def createAndAnimateEmpty(origin): bpy.ops.object.add(type='EMPTY', location=origin) empty = bpy.context.object scn = bpy.context.scene scn.frame_current = 1 bpy.ops.anim.keyframe_insert_menu(type='Location') scn.frame_current = 26 bpy.ops.transform.translate(value=(1,0,1)) bpy.ops.anim.keyframe_insert_menu(type='Location') scn.frame_current = 1 for fcu in empty.animation_data.action.fcurves: fcu.extrapolation = 'LINEAR' for kp in fcu.keyframe_points: kp.interpolation = 'LINEAR' return empty def run(origin): # Create flags and poles flag1 = makeFlag('SoftBodyFlag', origin+Vector((-3,0,0)), False) flag2 = makeFlag('ClothFlag', origin+Vector((0,0,0)), False) flag3 = makeFlag('DisplacementFlag', origin+Vector((3,0,0)), True) pole1 = makePole(origin+Vector((-3,0,0))) pole2 = makePole(origin+Vector((0,0,0))) pole3 = makePole(origin+Vector((3,0,0))) # Materials mat1 = addFlagMaterial('SoftBodyFlag', flag1, (1,0,0), (0,0,1)) mat2 = addFlagMaterial('ClothFlag', flag2, (0,1,0), (1,1,0)) mat3 = addFlagMaterial('DisplacementFlag', flag3, (1,0,1), (0,1,0)) white = bpy.data.materials.new('White') white.diffuse_color = (1,1,1) pole1.data.materials.append(white) pole2.data.materials.append(white) pole3.data.materials.append(white) # Add modifiers and wind addSoftBodyModifier(flag1) addClothModifier(flag2) addWindEffector(origin+Vector((-1,-2,0))) # Create displacement tex3 = createDisplacementTexture(mat3) empty = createAndAnimateEmpty(origin + Vector((3,0,0))) mod = addDisplacementModifier(flag3, tex3, 'POLE', empty) return if __name__ == "__main__": bpy.ops.object.select_by_type(type='MESH') bpy.ops.object.delete() run(Vector((0,0,0))) bpy.ops.screen.animation_play()
Particles and explode modifier
A bullet with an invisible particle system is fired at a crystal ball. The ball is shattered and the pieces fall to the floot.
The effect is achieved by giving the ball an explode modifier which is triggered by a particle system. The idea was to make this into a reaction particle system, which is triggered by the particle system of the bullet. However, reactor particles are apparently not yet implemented in Blender 2.5, so the balls particles are set to emit at a specific time instead.
#---------------------------------------------------------- # File crystal.py #---------------------------------------------------------- import bpy, mathutils, math from mathutils import * def addSphere(name, size, origin): bpy.ops.mesh.primitive_ico_sphere_add( subdivisions=2, size=size, location=origin) bpy.ops.object.shade_smooth() bpy.ops.object.modifier_add(type='SUBSURF') ob = bpy.context.object ob.name = name return ob def addFloor(name, origin, hidden): bpy.ops.mesh.primitive_plane_add(location=origin) bpy.ops.transform.resize(value=(30, 30, 30)) floor = bpy.context.object floor.name = name if hidden: floor.hide = True floor.hide_render = True return floor # Floor material voronoi = bpy.data.textures.new('Voronoi', type = 'VORONOI') voronoi.color_mode = 'POSITION' voronoi.noise_scale = 0.1 plastic = bpy.data.materials.new('Plastic') plastic.diffuse_color = (1,1,0) plastic.diffuse_intensity = 0.1 mtex = plastic.texture_slots.add() mtex.texture = voronoi mtex.texture_coords = 'ORCO' mtex.color = (0,0,1) floor.data.materials.append(plastic) return floor def run(origin): # ----------- Materials red = bpy.data.materials.new('Red') red.diffuse_color = (1,0,0) red.specular_hardness = 200 rmir = red.raytrace_mirror rmir.use = True rmir.distance = 0.001 rmir.fade_to = 'FADE_TO_MATERIAL' rmir.distance = 0.0 rmir.reflect_factor = 0.7 rmir.gloss_factor = 0.4 grey = bpy.data.materials.new('Grey') grey.diffuse_color = (0.5,0.5,0.5) # ----------- Bullet - a small sphere bullet = addSphere('Bullet', 0.2, origin) bullet.data.materials.append(grey) # Animate bullet scn = bpy.context.scene scn.frame_current = 51 bullet.location = origin bpy.ops.anim.keyframe_insert_menu(type='Location') bullet.location = origin+Vector((0,30,0)) scn.frame_current = 251 bpy.ops.anim.keyframe_insert_menu(type='Location') scn.frame_current = 1 action = bullet.animation_data.action for fcu in action.fcurves: fcu.extrapolation = 'LINEAR' for kp in fcu.keyframe_points: kp.interpolation = 'LINEAR' # Trail particle system for bullet bpy.ops.object.particle_system_add() trail = bullet.particle_systems[0] trail.name = 'Trail' fset = trail.settings # Emission fset.name = 'TrailSettings' fset.count = 1000 fset.frame_start = 1 fset.frame_end = 250 fset.lifetime = 25 fset.emit_from = 'FACE' fset.use_render_emitter = True # Velocity fset.normal_factor = 1.0 fset.factor_random = 0.5 # Physics fset.physics_type = 'NEWTON' fset.mass = 0 # Set all effector weights to zero ew = fset.effector_weights ew.gravity = 0.0 # Don't render fset.draw_method = 'DOT' fset.render_type = 'NONE' # -------------- Ball ball = addSphere('Ball', 1.0, origin) ball.data.materials.append(red) # Particle system bpy.ops.object.particle_system_add() react = ball.particle_systems[0] react.name = 'React' fset = react.settings # Emission fset.name = 'TrailSettings' fset.count = 50 fset.frame_start = 47 fset.frame_end = 57 fset.lifetime = 250 fset.emit_from = 'FACE' fset.use_render_emitter = True # Velocity fset.normal_factor = 5.0 fset.factor_random = 2.5 # Physics fset.physics_type = 'NEWTON' fset.mass = 1.0 # Don't render fset.draw_method = 'CROSS' fset.render_type = 'NONE' # Explode modifier mod = ball.modifiers.new(name='Explode', type='EXPLODE') mod.use_edge_cut = True mod.show_unborn = True mod.show_alive = True mod.show_dead = True mod.use_size = False # ----------- Hidden floor with collision modifier hidden = addFloor('Hidden', origin+Vector((0,0,-3.9)), True) mod = hidden.modifiers.new(name='Collision', type='COLLISION') mset = mod.settings mset.permeability = 0.01 mset.stickness = 0.1 mset.use_particle_kill = False mset.damping_factor = 0.6 mset.damping_random = 0.2 mset.friction_factor = 0.3 mset.friction_random = 0.1 addFloor('Floor', Vector((0,0,-4)), False) return if __name__ == "__main__": bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete() # Camera, lights bpy.ops.object.camera_add( location = Vector((12,-12,4)), rotation = Vector((70,0,45))*math.pi/180) cam = bpy.context.object.data cam.lens = 35 bpy.ops.object.lamp_add(type='POINT', location = Vector((11,-7,6))) bpy.ops.object.lamp_add(type='POINT', location =Vector((-7,-10,2))) run(Vector((0,0,0)))
Particle fire and smoke
This program adds two particle systems for fire and smoke. The particles render as billboards with procedural textures.
#--------------------------------------------------- # File fire.py #--------------------------------------------------- import bpy, mathutils, math from mathutils import Vector, Matrix from math import pi def createEmitter(origin): bpy.ops.mesh.primitive_plane_add(location=origin) emitter = bpy.context.object bpy.ops.mesh.uv_texture_add() return emitter def createFire(emitter): # Add first particle system bpy.context.scene.objects.active = emitter bpy.ops.object.particle_system_add() fire = emitter.particle_systems[-1] fire.name = 'Fire' fset = fire.settings # Emission fset.name = 'FireSettings' fset.count = 100 fset.frame_start = 1 fset.frame_end = 200 fset.lifetime = 70 fset.lifetime_random = 0.2 fset.emit_from = 'FACE' fset.use_render_emitter = False fset.distribution = 'RAND' fset.object_align_factor = (0,0,1) # Velocity fset.normal_factor = 0.55 fset.factor_random = 0.5 # Physics fset.physics_type = 'NEWTON' fset.mass = 1.0 fset.particle_size = 10.0 fset.use_multiply_size_mass = False # Effector weights ew = fset.effector_weights ew.gravity = 0.0 ew.wind = 1.0 # Display and render fset.draw_percentage = 100 fset.draw_method = 'RENDER' fset.material = 1 fset.particle_size = 0.3 fset.render_type = 'BILLBOARD' fset.render_step = 3 # Children fset.child_type = 'SIMPLE' fset.rendered_child_count = 50 fset.child_radius = 1.1 fset.child_roundness = 0.5 return fire def createSmoke(emitter): # Add second particle system bpy.context.scene.objects.active = emitter bpy.ops.object.particle_system_add() smoke = emitter.particle_systems[-1] smoke.name = 'Smoke' sset = smoke.settings # Emission sset.name = 'FireSettings' sset.count = 100 sset.frame_start = 1 sset.frame_end = 100 sset.lifetime = 70 sset.lifetime_random = 0.2 sset.emit_from = 'FACE' sset.use_render_emitter = False sset.distribution = 'RAND' # Velocity sset.normal_factor = 0.0 sset.factor_random = 0.5 # Physics sset.physics_type = 'NEWTON' sset.mass = 2.5 sset.particle_size = 0.3 sset.use_multiply_size_mass = True # Effector weights ew = sset.effector_weights ew.gravity = 0.0 ew.wind = 1.0 # Display and render sset.draw_percentage = 100 sset.draw_method = 'RENDER' sset.material = 2 sset.particle_size = 0.5 sset.render_type = 'BILLBOARD' sset.render_step = 3 # Children sset.child_type = 'SIMPLE' sset.rendered_child_count = 50 sset.child_radius = 1.6 return smoke def createWind(origin): bpy.ops.object.effector_add( type='WIND', enter_editmode=False, location = origin - Vector((0,3,0)), rotation = (-pi/2, 0, 0)) wind = bpy.context.object # Field settings fld = wind.field fld.strength = 2.3 fld.noise = 3.2 fld.flow = 0.3 return wind def createColorRamp(tex, values): tex.use_color_ramp = True ramp = tex.color_ramp for n,value in enumerate(values): elt = ramp.elements[n] (pos, color) = value elt.position = pos elt.color = color return def createFlameTexture(): tex = bpy.data.textures.new('Flame', type = 'CLOUDS') createColorRamp(tex, [(0.2, (1,0.5,0.1,1)), (0.8, (0.5,0,0,0))]) tex.noise_type = 'HARD_NOISE' tex.noise_scale = 0.7 tex.noise_depth = 5 return tex def createStencilTexture(): tex = bpy.data.textures.new('Stencil', type = 'BLEND') tex.progression = 'SPHERICAL' createColorRamp(tex, [(0.0, (0,0,0,0)), (0.85, (1,1,1,0.6))]) return tex def createEmitTexture(): tex = bpy.data.textures.new('Emit', type = 'BLEND') tex.progression = 'LINEAR' createColorRamp(tex, [(0.1, (1,1,0,1)), (0.3, (1,0,0,1))]) return tex def createSmokeTexture(): tex = bpy.data.textures.new('Smoke', type = 'CLOUDS') createColorRamp(tex, [(0.2, (0,0,0,1)), (0.6, (1,1,1,1))]) tex.noise_type = 'HARD_NOISE' tex.noise_scale = 1.05 tex.noise_depth = 5 return tex def createFireMaterial(textures, objects): (flame, stencil, emit) = textures (emitter, empty) = objects mat = bpy.data.materials.new('Fire') mat.specular_intensity = 0.0 mat.use_transparency = True mat.transparency_method = 'Z_TRANSPARENCY' mat.alpha = 0.0 mat.use_raytrace = False mat.use_face_texture = True mat.use_shadows = False mat.use_cast_buffer_shadows = True mtex = mat.texture_slots.add() mtex.texture = emit mtex.texture_coords = 'UV' mtex.use_map_color_diffuse = True mtex = mat.texture_slots.add() mtex.texture = stencil mtex.texture_coords = 'UV' mtex.use_map_color_diffuse = False mtex.use_map_emit = True mtex.use_stencil = True mtex = mat.texture_slots.add() mtex.texture = flame mtex.texture_coords = 'UV' mtex.use_map_color_diffuse = True mtex.use_map_alpha = True #mtex.object = empty return mat def createSmokeMaterial(textures, objects): (smoke, stencil) = textures (emitter, empty) = objects mat = bpy.data.materials.new('Smoke') mat.specular_intensity = 0.0 mat.use_transparency = True mat.transparency_method = 'Z_TRANSPARENCY' mat.alpha = 0.0 mat.use_raytrace = False mat.use_face_texture = True mat.use_shadows = True mat.use_cast_buffer_shadows = True mtex = mat.texture_slots.add() mtex.texture = stencil mtex.texture_coords = 'UV' mtex.use_map_color_diffuse = False mtex.use_map_alpha = True mtex.use_stencil = True mtex = mat.texture_slots.add() mtex.texture = smoke mtex.texture_coords = 'OBJECT' mtex.object = empty return mat def run(origin): emitter = createEmitter(origin) #wind = createWind() bpy.ops.object.add(type='EMPTY') empty = bpy.context.object fire = createFire(emitter) flameTex = createFlameTexture() stencilTex = createStencilTexture() emitTex = createEmitTexture() flameMat = createFireMaterial( (flameTex, stencilTex, emitTex), (emitter, empty)) emitter.data.materials.append(flameMat) smoke = createSmoke(emitter) smokeTex = createSmokeTexture() smokeMat = createSmokeMaterial( (smokeTex, stencilTex), (emitter, empty)) emitter.data.materials.append(smokeMat) return if __name__ == "__main__": bpy.ops.object.select_by_type(type='MESH') bpy.ops.object.delete() run((0,0,0)) bpy.ops.screen.animation_play(reverse=False, sync=False)
Smoke
This program sets up a smoke simulation and assigns a voxel material.
#---------------------------------------------------------- # File smoke.py # Creates smoke and smoke material. # Heavily inspired by Andrew Price's tutorial at # http://www.blenderguru.com/introduction-to-smoke-simulation/ #---------------------------------------------------------- import bpy, mathutils, math from mathutils import Vector from math import pi def createDomain(origin): # Add cube as domain bpy.ops.mesh.primitive_cube_add(location=origin) bpy.ops.transform.resize(value=(4, 4, 4)) domain = bpy.context.object domain.name = 'Domain' # Add domain modifier dmod = domain.modifiers.new(name='Smoke', type='SMOKE') dmod.smoke_type = 'DOMAIN' dset = dmod.domain_settings # Domain settings dset.resolution_max = 32 dset.alpha = -0.001 dset.beta = 2.0 dset.time_scale = 1.2 dset.vorticity = 2.0 dset.use_dissolve_smoke = True dset.dissolve_speed = 80 dset.use_dissolve_smoke_log = True dset.use_high_resolution = True dset.show_high_resolution = True # Effector weights ew = dset.effector_weights ew.gravity = 0.4 ew.force = 0.8 return domain def createFlow(origin): # Add plane as flow bpy.ops.mesh.primitive_plane_add(location = origin) bpy.ops.transform.resize(value=(2, 2, 2)) flow = bpy.context.object flow.name = 'Flow' # Add smoke particle system pmod = flow.modifiers.new(name='SmokeParticles', type='PARTICLE_SYSTEM') pmod.name = 'SmokeParticles' psys = pmod.particle_system psys.seed = 4711 # Particle settings pset = psys.settings pset.type = 'EMITTER' pset.lifetime = 1 pset.emit_from = 'VOLUME' pset.use_render_emitter = False pset.render_type = 'NONE' pset.normal_factor = 8.0 # Add smoke modifier smod = flow.modifiers.new(name='Smoke', type='SMOKE') smod.smoke_type = 'FLOW' sfset = smod.flow_settings # Flow settings sfset.use_outflow = False sfset.temperature = 0.7 sfset.density = 0.8 sfset.initial_velocity = True sfset.particle_system = psys return flow def createVortexEffector(origin): bpy.ops.object.effector_add(type='VORTEX', location=origin) vortex = bpy.context.object return vortex def createVoxelTexture(domain): tex = bpy.data.textures.new('VoxelTex', type = 'VOXEL_DATA') voxdata = tex.voxel_data voxdata.file_format = 'SMOKE' voxdata.domain_object = domain return tex def createVolumeMaterial(tex): mat = bpy.data.materials.new('VolumeMat') mat.type = 'VOLUME' vol = mat.volume vol.density = 0.0 vol.density_scale = 8.0 vol.scattering = 6.0 vol.asymmetry = 0.3 vol.emission = 0.3 vol.emission_color = (1,1,1) vol.transmission_color = (0.9,0.2,0) vol.reflection = 0.7 vol.reflection_color = (0.8,0.9,0) # To remove pixelation effects vol.step_size = 0.05 # Add voxdata texture mtex = mat.texture_slots.add() mtex.texture = tex mtex.texture_coords = 'ORCO' mtex.use_map_density = True mtex.use_map_emission = True mtex.use_map_scatter = False mtex.use_map_reflect = True mtex.use_map_color_emission = True mtex.use_map_color_transmission = True mtex.use_map_color_reflection = True mtex.density_factor = 1.0 mtex.emission_factor = 0.2 mtex.scattering_factor = 0.2 mtex.reflection_factor = 0.3 mtex.emission_color_factor = 0.9 mtex.transmission_color_factor = 0.5 mtex.reflection_color_factor = 0.6 return mat def addFloor(origin): # Create floor that receives transparent shadows bpy.ops.mesh.primitive_plane_add( location = origin, rotation = (0, 0, pi/4)) bpy.ops.transform.resize(value=(4, 4, 4)) bpy.ops.transform.resize(value=(2, 2, 2), constraint_axis=(True, False, False), constraint_orientation='LOCAL') floor = bpy.context.object mat = bpy.data.materials.new('Floor') mat.use_transparent_shadows = True floor.data.materials.append(mat) return def setupWorld(): scn = bpy.context.scene # Blue blend sky scn.world.use_sky_blend = True scn.world.horizon_color = (0.25, 0.3, 0.4) scn.world.zenith_color = (0, 0, 0.7) # PAL 4:3 render scn.render.resolution_x = 720 scn.render.resolution_y = 567 return def run(origin): domain = createDomain(origin) flow = createFlow(origin-Vector((0,0,3.5))) vortex = createVortexEffector(origin) tex = createVoxelTexture(domain) mat = createVolumeMaterial(tex) domain.data.materials.append(mat) return if __name__ == "__main__": for ob in bpy.context.scene.objects: bpy.context.scene.objects.unlink(ob) addFloor(Vector((0,0,-4))) setupWorld() # Lights and camera bpy.ops.object.lamp_add( type = 'POINT', location=(4,6,1)) bpy.ops.object.lamp_add( type = 'POINT', location=(-7,-5,0)) bpy.ops.object.camera_add(location=Vector((8,-8,3)), rotation=(pi/3, 0, pi/6)) run(Vector((0,0,0))) bpy.ops.screen.animation_play()
Rigid body simulation
This program uses the Blender game engine to simulate a pile of objects falling to the ground. The animation is recorded and can be replayed afterwards.
#---------------------------------------------------------- # File pile.py #---------------------------------------------------------- import bpy, mathutils, math, random from mathutils import Vector NObjects = 7 Seed = 444 def addSceneGameSettings(scn): # SceneGameData sgdata = scn.game_settings sgdata.fps = 25 sgdata.frequency = True sgdata.material_mode = 'GLSL' sgdata.show_debug_properties = True sgdata.show_framerate_profile = True sgdata.show_fullscreen = True sgdata.show_physics_visualization = True sgdata.use_animation_record = True return def addMonkeyGameSettings(ob): # GameObjectSettings goset = ob.game goset.physics_type = 'RIGID_BODY' goset.use_actor = True goset.use_ghost = False goset.mass = 7.0 goset.damping = 0.0 goset.use_collision_bounds = True goset.collision_bounds_type = 'BOX' goset.show_actuators = True goset.show_controllers = True goset.show_debug_state = True goset.show_sensors = True goset.show_state_panel = True return def run(origin): # Change render engine from BLENDER_RENDER to BLENDER_GAME bpy.context.scene.render.engine = 'BLENDER_GAME' # Create floor bpy.ops.mesh.primitive_plane_add(location=origin) bpy.ops.transform.resize(value=(20, 20, 20)) floor = bpy.context.object mat = bpy.data.materials.new(name = 'FloorMaterial') mat.diffuse_color = (0.5, 0.5, 0.5) # Create a pile of objects objectType = ["cube", "ico_sphere", "monkey"] objects = [] deg2rad = math.pi/180 random.seed(Seed) for n in range(NObjects): x = [] for i in range(3): x.append( random.randrange(0, 360, 1) ) dx = 0.5*random.random() dy = 0.5*random.random() obType = objectType[ random.randrange(0, 3, 1) ] fcn = eval("bpy.ops.mesh.primitive_%s_add" % obType) fcn(location=origin+Vector((dx, dy, 3*n+3)), rotation=deg2rad*Vector((x[0], x[1], x[2]))) ob = bpy.context.object objects.append( ob ) mat = bpy.data.materials.new(name='Material_%02d' % n) c = [] for j in range(3): c.append( random.random() ) mat.diffuse_color = c ob.data.materials.append(mat) # Set game settings for floor fset = floor.game fset.physics_type = 'STATIC' # Set game settings for monkeys for n in range(NObjects): addMonkeyGameSettings(objects[n]) # Set game settings for scene scn = bpy.context.scene addSceneGameSettings(scn) scn.frame_start = 1 scn.frame_end = 200 return if __name__ == "__main__": bpy.ops.object.select_by_type(type='MESH') bpy.ops.object.delete() run(Vector((0,0,0))) bpy.ops.view3d.game_start()
Fluids
This program sets up a fluid simulation with a domain, a fluid, a moving obstacle, an inflow, an outflow, and three kinds of drops. Note that we must bake the simulation first; I don't think that used to be necessary.
The pictures are from frame 57, after some materials have been added. The drop dominate the render completely unless they are given a low opacity, around alpha = 0.2.
#---------------------------------------------------------- # File fluid.py #---------------------------------------------------------- import bpy, math from mathutils import Vector from math import pi def createDomain(origin): bpy.ops.mesh.primitive_cube_add(location=origin) bpy.ops.transform.resize(value=(4, 4, 4)) domain = bpy.context.object domain.name = 'Domain' bpy.ops.object.shade_smooth() # Add domain modifier mod = domain.modifiers.new(name='FluidDomain', type='FLUID_SIMULATION') # mod.settings is FluidSettings mod.settings.type = 'DOMAIN' # mod.settings now changed to DomainFluidSettings settings = mod.settings settings.use_speed_vectors = False settings.simulation_scale = 3.0 settings.slip_type = 'FREESLIP' settings.tracer_particles = 10 settings.generate_particles = 1.5 #settings.start_time = 0.0 #settings.end_time = 2.0 return domain def createFluid(origin): bpy.ops.mesh.primitive_ico_sphere_add( size=3.5, subdivisions=1, location=origin) fluid = bpy.context.object fluid.name = 'Fluid' fluid.hide = True fluid.hide_render = True # Add fluid modifier. mod = fluid.modifiers.new(name='Fluid', type='FLUID_SIMULATION') mod.settings.type = 'FLUID' return fluid def createObstacle(origin): bpy.ops.mesh.primitive_cylinder_add( vertices=12, radius=0.3, depth=2, cap_ends=True, location=origin + Vector((0,0,-2.5)), rotation=(pi/2, 0, 0)) bpy.ops.object.modifier_add(type='FLUID_SIMULATION') obst = bpy.context.object obst.name = 'Obstacle' # Add fluid modifier bpy.ops.object.modifier_add(type='FLUID_SIMULATION') mod = obst.modifiers[-1] mod.settings.type = 'OBSTACLE' # Animate obstacle scn = bpy.context.scene scn.frame_current = 1 bpy.ops.anim.keyframe_insert_menu(type='Rotation') scn.frame_current = 26 bpy.ops.transform.rotate(value=(pi/2,), axis=(-0, -0, -1)) bpy.ops.anim.keyframe_insert_menu(type='Rotation') scn.frame_current = 1 for fcu in obst.animation_data.action.fcurves: fcu.extrapolation = 'LINEAR' for kp in fcu.keyframe_points: kp.interpolation = 'LINEAR' return obst def createInflow(origin): bpy.ops.mesh.primitive_circle_add( radius=0.75, fill=True, location=origin+Vector((-3.9,0,3)), rotation=(0, pi/2, 0)) inflow = bpy.context.object inflow.name = 'Inflow' # Add fluid modifier bpy.ops.object.modifier_add(type='FLUID_SIMULATION') mod = inflow.modifiers[-1] mod.settings.type = 'INFLOW' settings = mod.settings settings.inflow_velocity = (1.5,0,0) settings.volume_initialization = 'SHELL' return inflow def createOutflow(origin): bpy.ops.mesh.primitive_circle_add( radius=0.75, fill=True, location=origin+Vector((3.9,0,-3)), rotation=(0, -pi/2, 0)) outflow = bpy.context.object outflow.name = 'Outflow' # Add fluid modifier bpy.ops.object.modifier_add(type='FLUID_SIMULATION') mod = outflow.modifiers[-1] mod.settings.type = 'OUTFLOW' mod.settings.volume_initialization = 'SHELL' return outflow def createFluidParticle(name, origin, data): bpy.ops.mesh.primitive_monkey_add(location=origin) monkey = bpy.context.object monkey.name = name # Add fluid modifier bpy.ops.object.modifier_add(type='FLUID_SIMULATION') mod = monkey.modifiers[-1] mod.settings.type = 'PARTICLE' (drops, floats, tracer) = data mod.settings.use_drops = drops mod.settings.use_floats = floats mod.settings.show_tracer = tracer # Setting type to particle created a particle system psys = monkey.modifiers[-1].particle_system psys.name = name+'Psys' #psys.settings.name = name+'Pset' return (mod.settings, None) def run(origin): domain = createDomain(origin) fluid = createFluid(origin) obst = createObstacle(origin) inflow = createInflow(origin) outflow = createOutflow(origin) (settings, pset) = createFluidParticle('Drops', origin+Vector((-2,7,0)), (True, False, False)) settings.particle_influence = 0.7 settings.alpha_influence = 0.3 (settings, pset) = createFluidParticle('Floats', origin+Vector((0,7,0)), (False, True, False)) (settings, pset) = createFluidParticle('Tracer', origin+Vector((2,7,0)), (False, False, True)) settings.particle_influence = 1.5 settings.alpha_influence = 1.2 return if __name__ == "__main__": bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete() run(Vector((0,0,0))) #bpy.ops.fluid.bake()