From cb634b910010c04543cb3361f7a16a261e5b9f89 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 10 Oct 2012 13:18:07 +0000 Subject: Google Summer of Code project: "Smoke Simulator Improvements & Fire". Documentation & Test blend files: ------------------ http://wiki.blender.org/index.php/User:MiikaH/GSoC-2012-Smoke-Simulator-Improvements Credits: ------------------ Miika Hamalainen (MiikaH): Student / Main programmer Daniel Genrich (Genscher): Mentor / Programmer of merged patches from Smoke2 branch Google: For Google Summer of Code 2012 --- release/datafiles/blender_icons.png | Bin 227018 -> 209196 bytes .../startup/bl_operators/object_quick_effects.py | 67 ++++---- .../scripts/startup/bl_ui/properties_particle.py | 2 +- .../startup/bl_ui/properties_physics_cloth.py | 2 +- .../startup/bl_ui/properties_physics_common.py | 4 +- .../bl_ui/properties_physics_dynamicpaint.py | 2 +- .../startup/bl_ui/properties_physics_field.py | 8 + .../startup/bl_ui/properties_physics_smoke.py | 175 ++++++++++++++++----- .../startup/bl_ui/properties_physics_softbody.py | 2 +- .../scripts/startup/bl_ui/properties_texture.py | 4 + 10 files changed, 187 insertions(+), 79 deletions(-) (limited to 'release') diff --git a/release/datafiles/blender_icons.png b/release/datafiles/blender_icons.png index a0d460b0153..09a63f4c47d 100644 Binary files a/release/datafiles/blender_icons.png and b/release/datafiles/blender_icons.png differ diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index 35b496b6dd0..cd0b63a6b78 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -299,7 +299,6 @@ class QuickSmoke(Operator): style = EnumProperty( name="Smoke Style", items=(('STREAM', "Stream", ""), - ('PUFF', "Puff", ""), ('FIRE', "Fire", ""), ), default='STREAM', @@ -328,20 +327,9 @@ class QuickSmoke(Operator): bpy.ops.object.modifier_add(fake_context, type='SMOKE') obj.modifiers[-1].smoke_type = 'FLOW' - psys = obj.particle_systems[-1] - if self.style == 'PUFF': - psys.settings.frame_end = psys.settings.frame_start - psys.settings.emit_from = 'VOLUME' - psys.settings.distribution = 'RAND' - elif self.style == 'FIRE': - psys.settings.effector_weights.gravity = -1 - psys.settings.lifetime = 5 - psys.settings.count = 100000 - - obj.modifiers[-2].flow_settings.initial_velocity = True - obj.modifiers[-2].flow_settings.temperature = 2 - - psys.settings.use_render_emitter = self.show_flows + if self.style == 'FIRE': + obj.modifiers[-1].flow_settings.smoke_flow_type = 'FIRE' + if not self.show_flows: obj.draw_type = 'WIRE' @@ -361,8 +349,6 @@ class QuickSmoke(Operator): bpy.ops.object.modifier_add(type='SMOKE') obj.modifiers[-1].smoke_type = 'DOMAIN' if self.style == 'FIRE': - obj.modifiers[-1].domain_settings.use_dissolve_smoke = True - obj.modifiers[-1].domain_settings.dissolve_speed = 20 obj.modifiers[-1].domain_settings.use_high_resolution = True # create a volume material with a voxel data texture for the domain @@ -373,6 +359,7 @@ class QuickSmoke(Operator): mat.type = 'VOLUME' mat.volume.density = 0 mat.volume.density_scale = 5 + mat.volume.step_size = 0.1 tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA') tex.voxel_data.domain_object = obj @@ -381,29 +368,35 @@ class QuickSmoke(Operator): tex_slot.texture = tex tex_slot.use_map_color_emission = False tex_slot.use_map_density = True + tex_slot.use_map_color_reflection = True - # for fire add a second texture for emission and emission color - if self.style == 'FIRE': - mat.volume.emission = 5 - tex = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA') - tex.voxel_data.domain_object = obj - tex.use_color_ramp = True - - tex_slot = mat.texture_slots.add() - tex_slot.texture = tex - - ramp = tex.color_ramp - - elem = ramp.elements.new(0.333) - elem.color[0] = elem.color[3] = 1 - elem.color[1] = elem.color[2] = 0 + # for fire add a second texture for flame emission + mat.volume.emission_color = Vector((0.0, 0.0, 0.0)) + tex = bpy.data.textures.new("Flame", 'VOXEL_DATA') + tex.voxel_data.domain_object = obj + tex.voxel_data.smoke_data_type = 'SMOKEFLAME' + tex.use_color_ramp = True - elem = ramp.elements.new(0.666) - elem.color[0] = elem.color[1] = elem.color[3] = 1 - elem.color[2] = 0 + tex_slot = mat.texture_slots.add() + tex_slot.texture = tex - mat.texture_slots[1].use_map_emission = True - mat.texture_slots[1].blend_type = 'MULTIPLY' + # add color ramp for flame color + ramp = tex.color_ramp + # dark orange + elem = ramp.elements.new(0.333) + elem.color[0] = 0.2 + elem.color[1] = 0.03 + elem.color[2] = 0 + elem.color[3] = 1 + # yellow glow + elem = ramp.elements.new(0.666) + elem.color[0] = elem.color[3] = 1 + elem.color[1] = 0.65 + elem.color[2] = 0.25 + + mat.texture_slots[1].use_map_density = True + mat.texture_slots[1].use_map_emission = True + mat.texture_slots[1].emission_factor = 5 return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index f29589faa2d..6fcd56fb99e 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -1124,7 +1124,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel): def draw(self, context): part = particle_get_settings(context) - effector_weights_ui(self, context, part.effector_weights) + effector_weights_ui(self, context, part.effector_weights, 'PSYS') if part.type == 'HAIR': row = self.layout.row() diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index e5db1eec37e..5a44294f0e0 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -197,7 +197,7 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel): def draw(self, context): cloth = context.cloth.settings - effector_weights_ui(self, context, cloth.effector_weights) + effector_weights_ui(self, context, cloth.effector_weights, 'CLOTH') if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index 00a35b233da..b94df3148a9 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -179,7 +179,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype): col.operator("ptcache.bake_all", text="Update All To Frame").bake = False -def effector_weights_ui(self, context, weights): +def effector_weights_ui(self, context, weights, weight_type): layout = self.layout layout.prop(weights, "group") @@ -200,6 +200,8 @@ def effector_weights_ui(self, context, weights): col.prop(weights, "wind", slider=True) col.prop(weights, "curve_guide", slider=True) col.prop(weights, "texture", slider=True) + if weight_type != 'SMOKE': + col.prop(weights, "smokeflow", slider=True) col = split.column() col.prop(weights, "harmonic", slider=True) diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py index fa37e9cd10f..1df2936b2d4 100644 --- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py +++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py @@ -349,7 +349,7 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel): col = layout.column() col.active = surface.use_drip - effector_weights_ui(self, context, surface.effector_weights) + effector_weights_ui(self, context, surface.effector_weights, 'DYNAMIC_PAINT') layout.label(text="Surface Movement:") row = layout.row() diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py index 6b5612d7836..933a9aa12a3 100644 --- a/release/scripts/startup/bl_ui/properties_physics_field.py +++ b/release/scripts/startup/bl_ui/properties_physics_field.py @@ -112,6 +112,14 @@ class PHYSICS_PT_field(PhysicButtonsPanel, Panel): col = split.column() col.prop(field, "use_object_coords") col.prop(field, "use_2d_force") + elif field.type == 'SMOKE_FLOW': + col = split.column() + col.prop(field, "strength") + col.prop(field, "flow") + col = split.column() + col.label(text="Domain Object:") + col.prop(field, "source_object", "") + col.prop(field, "use_smoke_density") else: basic_force_field_settings_ui(self, context, field) diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py index acbaad4f961..ce5053f0ecf 100644 --- a/release/scripts/startup/bl_ui/properties_physics_smoke.py +++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py @@ -76,28 +76,40 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel): elif md.smoke_type == 'FLOW': flow = md.flow_settings - - split = layout.split() - - col = split.column() - col.prop(flow, "use_outflow") - col.label(text="Particle System:") - col.prop_search(flow, "particle_system", ob, "particle_systems", text="") - - sub = col.column() - sub.active = not md.flow_settings.use_outflow - - sub.prop(flow, "initial_velocity", text="Initial Velocity") - sub = sub.column() - sub.active = flow.initial_velocity - sub.prop(flow, "velocity_factor", text="Multiplier") - - sub = split.column() - sub.active = not md.flow_settings.use_outflow - sub.label(text="Initial Values:") - sub.prop(flow, "use_absolute") - sub.prop(flow, "density") - sub.prop(flow, "temperature") + + layout.prop(flow, "smoke_flow_type", expand=False) + + if flow.smoke_flow_type != "OUTFLOW": + split = layout.split() + col = split.column() + col.label(text="Flow Source:") + col.prop(flow, "smoke_flow_source", expand=False, text="") + if flow.smoke_flow_source == "PARTICLES": + col.label(text="Particle System:") + col.prop_search(flow, "particle_system", ob, "particle_systems", text="") + else: + col.prop(flow, "surface_distance") + col.prop(flow, "volume_density") + + sub = col.column(align=True) + + sub.prop(flow, "initial_velocity") + sub = sub.column() + sub.active = flow.initial_velocity + sub.prop(flow, "velocity_factor") + if flow.smoke_flow_source == "MESH": + sub.prop(flow, "velocity_normal") + #sub.prop(flow, "velocity_random") + + sub = split.column() + sub.label(text="Initial Values:") + sub.prop(flow, "use_absolute") + if flow.smoke_flow_type in {'SMOKE', 'BOTH'}: + sub.prop(flow, "density") + sub.prop(flow, "temperature") + sub.prop(flow, "smoke_color") + if flow.smoke_flow_type in {'FIRE', 'BOTH'}: + sub.prop(flow, "fuel_amount") elif md.smoke_type == 'COLLISION': coll = md.coll_settings @@ -106,36 +118,99 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel): col = split.column() col.prop(coll, "collision_type") + +class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel): + bl_label = "Smoke Flow Advanced" + bl_options = {'DEFAULT_CLOSED'} + @classmethod + def poll(cls, context): + md = context.smoke + return md and (md.smoke_type == 'FLOW') and (md.flow_settings.smoke_flow_source == "MESH") -class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel): - bl_label = "Smoke Groups" + def draw(self, context): + layout = self.layout + ob = context.object + flow = context.smoke.flow_settings + + split = layout.split() + col = split.column() + + col.prop(flow, "use_texture") + sub = col.column() + sub.active = flow.use_texture + sub.prop(flow, "noise_texture", text="") + sub.label(text="Mapping:") + sub.prop(flow, "texture_map_type", expand=False, text="") + if flow.texture_map_type == "UV": + sub.prop_search(flow, "uv_layer", ob.data, "uv_textures", text="") + if flow.texture_map_type == "AUTO": + sub.prop(flow, "texture_size") + sub.prop(flow, "texture_offset") + + col = split.column() + col.label(text="Vertex Group:") + col.prop_search(flow, "density_vertex_group", ob, "vertex_groups", text="") + +class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel): + bl_label = "Smoke Flames" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): md = context.smoke - rd = context.scene.render - return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) + return md and (md.smoke_type == 'DOMAIN') def draw(self, context): layout = self.layout - - group = context.smoke.domain_settings + domain = context.smoke.domain_settings split = layout.split() + split.enabled = not domain.point_cache.is_baked + + col = split.column(align=True) + col.label(text="Reaction:") + col.prop(domain, "burning_rate") + col.prop(domain, "flame_smoke") + col.prop(domain, "flame_vorticity") + + col = split.column(align=True) + col.label(text="Temperatures:") + col.prop(domain, "flame_ignition") + col.prop(domain, "flame_max_temp") + col.prop(domain, "flame_smoke_color") + +class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel): + bl_label = "Smoke Adaptive Domain" + bl_options = {'DEFAULT_CLOSED'} - col = split.column() - col.label(text="Flow Group:") - col.prop(group, "fluid_group", text="") + @classmethod + def poll(cls, context): + md = context.smoke + return md and (md.smoke_type == 'DOMAIN') - #col.label(text="Effector Group:") - #col.prop(group, "effector_group", text="") + def draw_header(self, context): + md = context.smoke.domain_settings - col = split.column() - col.label(text="Collision Group:") - col.prop(group, "collision_group", text="") + self.layout.prop(md, "use_adaptive_domain", text="") + def draw(self, context): + layout = self.layout + + domain = context.smoke.domain_settings + layout.active = domain.use_adaptive_domain + + split = layout.split() + split.enabled = not domain.point_cache.is_baked + + col = split.column(align=True) + col.label(text="Resolution:") + col.prop(domain, "additional_res") + col.prop(domain, "adapt_margin") + + col = split.column(align=True) + col.label(text="Advanced:") + col.prop(domain, "adapt_threshold") class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel): bl_label = "Smoke High Resolution" @@ -174,6 +249,32 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel): layout.prop(md, "show_high_resolution") +class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel): + bl_label = "Smoke Groups" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + md = context.smoke + rd = context.scene.render + return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) + + def draw(self, context): + layout = self.layout + domain = context.smoke.domain_settings + + split = layout.split() + + col = split.column() + col.label(text="Flow Group:") + col.prop(domain, "fluid_group", text="") + + #col.label(text="Effector Group:") + #col.prop(domain, "effector_group", text="") + + col = split.column() + col.label(text="Collision Group:") + col.prop(domain, "collision_group", text="") class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel): bl_label = "Smoke Cache" @@ -209,7 +310,7 @@ class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel): def draw(self, context): domain = context.smoke.domain_settings - effector_weights_ui(self, context, domain.effector_weights) + effector_weights_ui(self, context, domain.effector_weights, 'SMOKE') if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py index a69e7955de5..79d676533a5 100644 --- a/release/scripts/startup/bl_ui/properties_physics_softbody.py +++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py @@ -231,7 +231,7 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel): md = context.soft_body softbody = md.settings - effector_weights_ui(self, context, softbody.effector_weights) + effector_weights_ui(self, context, softbody.effector_weights, 'SOFTBODY') if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index 9e6bfe6889e..d4752e4e7b5 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -887,8 +887,12 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel): col = split.column() if tex.texture_coords in {'ORCO', 'UV'}: col.prop(tex, "use_from_dupli") + if (idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO'): + col.prop(tex, "use_map_to_bounds") elif tex.texture_coords == 'OBJECT': col.prop(tex, "use_from_original") + if (idblock.type == 'VOLUME'): + col.prop(tex, "use_map_to_bounds") else: col.label() -- cgit v1.2.3