diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 45 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 68 | ||||
-rw-r--r-- | intern/cycles/blender/blender_curves.cpp | 245 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 60 | ||||
-rw-r--r-- | intern/cycles/blender/blender_particles.cpp | 92 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.h | 6 | ||||
-rw-r--r-- | intern/cycles/blender/blender_util.h | 27 | ||||
-rw-r--r-- | intern/elbeem/extern/elbeem.h | 2 |
10 files changed, 541 insertions, 13 deletions
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index f964f2d1f9e..b57502b3b14 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -26,6 +26,7 @@ set(SRC blender_mesh.cpp blender_object.cpp blender_object_cull.cpp + blender_particles.cpp blender_curves.cpp blender_logging.cpp blender_python.cpp diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index cbff5a537dc..3616b13e751 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1137,6 +1137,49 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup): del bpy.types.Scene.cycles_curves +class CyclesCurveSettings(bpy.types.PropertyGroup): + @classmethod + def register(cls): + bpy.types.ParticleSettings.cycles = PointerProperty( + name="Cycles Hair Settings", + description="Cycles hair settings", + type=cls, + ) + cls.radius_scale = FloatProperty( + name="Radius Scaling", + description="Multiplier of width properties", + min=0.0, max=1000.0, + default=0.01, + ) + cls.root_width = FloatProperty( + name="Root Size", + description="Strand's width at root", + min=0.0, max=1000.0, + default=1.0, + ) + cls.tip_width = FloatProperty( + name="Tip Multiplier", + description="Strand's width at tip", + min=0.0, max=1000.0, + default=0.0, + ) + cls.shape = FloatProperty( + name="Strand Shape", + description="Strand shape parameter", + min=-1.0, max=1.0, + default=0.0, + ) + cls.use_closetip = BoolProperty( + name="Close tip", + description="Set tip radius to zero", + default=True, + ) + + @classmethod + def unregister(cls): + del bpy.types.ParticleSettings.cycles + + class CyclesDeviceSettings(bpy.types.PropertyGroup): @classmethod def register(cls): @@ -1248,6 +1291,7 @@ def register(): bpy.utils.register_class(CyclesMeshSettings) bpy.utils.register_class(CyclesObjectSettings) bpy.utils.register_class(CyclesCurveRenderSettings) + bpy.utils.register_class(CyclesCurveSettings) bpy.utils.register_class(CyclesDeviceSettings) bpy.utils.register_class(CyclesPreferences) @@ -1262,5 +1306,6 @@ def unregister(): bpy.utils.unregister_class(CyclesObjectSettings) bpy.utils.unregister_class(CyclesVisibilitySettings) bpy.utils.unregister_class(CyclesCurveRenderSettings) + bpy.utils.unregister_class(CyclesCurveSettings) bpy.utils.unregister_class(CyclesDeviceSettings) bpy.utils.unregister_class(CyclesPreferences) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 95731562c79..acca6414852 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1360,6 +1360,37 @@ class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel): layout.template_color_ramp(mapping, "color_ramp", expand=True) +class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel): + bl_label = "Textures" + bl_context = "particle" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + psys = context.particle_system + return psys and CyclesButtonsPanel.poll(context) + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + part = psys.settings + + row = layout.row() + row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2) + + col = row.column(align=True) + col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP' + col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN' + col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="") + + if not part.active_texture: + layout.template_ID(part, "active_texture", new="texture.new") + else: + slot = part.texture_slots[part.active_texture_index] + layout.template_ID(slot, "texture", new="texture.new") + + class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel): bl_label = "Cycles Hair Rendering" bl_context = "particle" @@ -1508,6 +1539,37 @@ class CyclesRender_PT_debug(CyclesButtonsPanel, Panel): col.prop(cscene, "debug_use_opencl_debug", text="Debug") +class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel): + bl_label = "Cycles Hair Settings" + bl_context = "particle" + + @classmethod + def poll(cls, context): + scene = context.scene + ccscene = scene.cycles_curves + psys = context.particle_system + use_curves = ccscene.use_curves and psys + return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR' + + def draw(self, context): + layout = self.layout + + psys = context.particle_settings + cpsys = psys.cycles + + row = layout.row() + row.prop(cpsys, "shape", text="Shape") + + layout.label(text="Thickness:") + row = layout.row() + row.prop(cpsys, "root_width", text="Root") + row.prop(cpsys, "tip_width", text="Tip") + + row = layout.row() + row.prop(cpsys, "radius_scale", text="Scaling") + row.prop(cpsys, "use_closetip", text="Close tip") + + class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel): bl_label = "Simplify" bl_context = "scene" @@ -1534,6 +1596,12 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel): col = layout.column(align=True) + col.label(text="Child Particles") + row = col.row(align=True) + row.prop(rd, "simplify_child_particles", text="Viewport") + row.prop(rd, "simplify_child_particles_render", text="Render") + + col = layout.column(align=True) split = col.split() sub = split.column() sub.label(text="Texture Limit Viewport") diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 7b9d4f2ecdf..378ae67f0c7 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -37,6 +37,9 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa void interp_weights(float t, float data[4]); float shaperadius(float shape, float root, float tip, float time); void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData); +bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num); +bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num); +bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background); void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData); void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam, bool is_ortho); @@ -116,6 +119,220 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t); } +bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background) +{ + int curvenum = 0; + int keyno = 0; + + if(!(mesh && b_mesh && b_ob && CData)) + return false; + + Transform tfm = get_transform(b_ob->matrix_world()); + Transform itfm = transform_quick_inverse(tfm); + + BL::Object::modifiers_iterator b_mod; + for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { + if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + + if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { + int shader = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1); + int draw_step = background ? b_part.render_step() : b_part.draw_step(); + int totparts = b_psys.particles.length(); + int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); + int totcurves = totchild; + + if(b_part.child_type() == 0 || totchild == 0) + totcurves += totparts; + + if(totcurves == 0) + continue; + + int ren_step = (1 << draw_step) + 1; + if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL) + ren_step += b_part.kink_extra_steps(); + + PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles"); + + CData->psys_firstcurve.push_back_slow(curvenum); + CData->psys_curvenum.push_back_slow(totcurves); + CData->psys_shader.push_back_slow(shader); + + float radius = get_float(cpsys, "radius_scale") * 0.5f; + + CData->psys_rootradius.push_back_slow(radius * get_float(cpsys, "root_width")); + CData->psys_tipradius.push_back_slow(radius * get_float(cpsys, "tip_width")); + CData->psys_shape.push_back_slow(get_float(cpsys, "shape")); + CData->psys_closetip.push_back_slow(get_boolean(cpsys, "use_closetip")); + + int pa_no = 0; + if(!(b_part.child_type() == 0) && totchild != 0) + pa_no = totparts; + + int num_add = (totparts+totchild - pa_no); + CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add); + CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add); + CData->curve_length.reserve(CData->curve_length.size() + num_add); + CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step); + CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step); + + for(; pa_no < totparts+totchild; pa_no++) { + int keynum = 0; + CData->curve_firstkey.push_back_slow(keyno); + + float curve_length = 0.0f; + float3 pcKey; + for(int step_no = 0; step_no < ren_step; step_no++) { + float nco[3]; + b_psys.co_hair(*b_ob, pa_no, step_no, nco); + float3 cKey = make_float3(nco[0], nco[1], nco[2]); + cKey = transform_point(&itfm, cKey); + if(step_no > 0) { + float step_length = len(cKey - pcKey); + if(step_length == 0.0f) + continue; + curve_length += step_length; + } + CData->curvekey_co.push_back_slow(cKey); + CData->curvekey_time.push_back_slow(curve_length); + pcKey = cKey; + keynum++; + } + keyno += keynum; + + CData->curve_keynum.push_back_slow(keynum); + CData->curve_length.push_back_slow(curve_length); + curvenum++; + } + } + } + } + + return true; +} + +bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num) +{ + if(!(mesh && b_mesh && b_ob && CData)) + return false; + + CData->curve_uv.clear(); + + BL::Object::modifiers_iterator b_mod; + for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { + if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + + if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { + int totparts = b_psys.particles.length(); + int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); + int totcurves = totchild; + + if(b_part.child_type() == 0 || totchild == 0) + totcurves += totparts; + + if(totcurves == 0) + continue; + + int pa_no = 0; + if(!(b_part.child_type() == 0) && totchild != 0) + pa_no = totparts; + + int num_add = (totparts+totchild - pa_no); + CData->curve_uv.reserve(CData->curve_uv.size() + num_add); + + BL::ParticleSystem::particles_iterator b_pa; + b_psys.particles.begin(b_pa); + for(; pa_no < totparts+totchild; pa_no++) { + /* Add UVs */ + BL::Mesh::tessface_uv_textures_iterator l; + b_mesh->tessface_uv_textures.begin(l); + + float3 uv = make_float3(0.0f, 0.0f, 0.0f); + if(b_mesh->tessface_uv_textures.length()) + b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x); + CData->curve_uv.push_back_slow(uv); + + if(pa_no < totparts && b_pa != b_psys.particles.end()) + ++b_pa; + } + } + } + } + + return true; +} + +bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num) +{ + if(!(mesh && b_mesh && b_ob && CData)) + return false; + + CData->curve_vcol.clear(); + + BL::Object::modifiers_iterator b_mod; + for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { + if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + + if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { + int totparts = b_psys.particles.length(); + int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); + int totcurves = totchild; + + if(b_part.child_type() == 0 || totchild == 0) + totcurves += totparts; + + if(totcurves == 0) + continue; + + int pa_no = 0; + if(!(b_part.child_type() == 0) && totchild != 0) + pa_no = totparts; + + int num_add = (totparts+totchild - pa_no); + CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add); + + BL::ParticleSystem::particles_iterator b_pa; + b_psys.particles.begin(b_pa); + for(; pa_no < totparts+totchild; pa_no++) { + /* Add vertex colors */ + BL::Mesh::tessface_vertex_colors_iterator l; + b_mesh->tessface_vertex_colors.begin(l); + + float3 vcol = make_float3(0.0f, 0.0f, 0.0f); + if(b_mesh->tessface_vertex_colors.length()) + b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x); + CData->curve_vcol.push_back_slow(vcol); + + if(pa_no < totparts && b_pa != b_psys.particles.end()) + ++b_pa; + } + } + } + } + + return true; +} + +static void set_resolution(BL::Object *b_ob, BL::Scene *scene, bool render) +{ + BL::Object::modifiers_iterator b_mod; + for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { + if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && ((b_mod->show_viewport()) || (b_mod->show_render()))) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); + b_psys.set_resolution(*scene, *b_ob, (render)? 2: 1); + } + } +} + void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam, bool is_ortho) { @@ -620,6 +837,20 @@ void BlenderSync::sync_curve_settings() } if(curve_system_manager->modified_mesh(prev_curve_system_manager)) { + BL::BlendData::objects_iterator b_ob; + + for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) { + if(object_is_mesh(*b_ob)) { + BL::Object::particle_systems_iterator b_psys; + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { + if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) { + BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data(); + mesh_map.set_recalc(key); + object_map.set_recalc(*b_ob); + } + } + } + } } if(curve_system_manager->modified(prev_curve_system_manager)) @@ -644,7 +875,7 @@ void BlenderSync::sync_curves(Mesh *mesh, /* obtain general settings */ bool use_curves = scene->curve_system_manager->use_curves; - if(!use_curves) { + if(!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT)) { if(!motion) mesh->compute_bounds(); return; @@ -661,6 +892,11 @@ void BlenderSync::sync_curves(Mesh *mesh, ParticleCurveData CData; + if(!preview) + set_resolution(&b_ob, &b_scene, true); + + ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview); + /* add hair geometry to mesh */ if(primitive == CURVE_TRIANGLES) { if(triangle_method == CURVE_CAMERA_TRIANGLES) { @@ -728,6 +964,8 @@ void BlenderSync::sync_curves(Mesh *mesh, if(!mesh->need_attribute(scene, ustring(l->name().c_str()))) continue; + ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num); + if(primitive == CURVE_TRIANGLES) { Attribute *attr_vcol = mesh->attributes.add( ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); @@ -767,6 +1005,8 @@ void BlenderSync::sync_curves(Mesh *mesh, if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { Attribute *attr_uv; + ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num); + if(primitive == CURVE_TRIANGLES) { if(active_render) attr_uv = mesh->attributes.add(std, name); @@ -797,6 +1037,9 @@ void BlenderSync::sync_curves(Mesh *mesh, } } + if(!preview) + set_resolution(&b_ob, &b_scene, false); + mesh->compute_bounds(); } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 5133134a6c5..637cf7abda8 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -418,9 +418,29 @@ static bool object_render_hide(BL::Object& b_ob, bool parent_hide, bool& hide_triangles) { + /* check if we should render or hide particle emitter */ + BL::Object::particle_systems_iterator b_psys; + + bool hair_present = false; + bool show_emitter = false; + bool hide_emitter = false; bool hide_as_dupli_parent = false; bool hide_as_dupli_child_original = false; + for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { + if((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) && + (b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) + hair_present = true; + + if(b_psys->settings().use_render_emitter()) + show_emitter = true; + else + hide_emitter = true; + } + + if(show_emitter) + hide_emitter = false; + /* duplicators hidden by default, except dupliframes which duplicate self */ if(b_ob.is_duplicator()) if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES) @@ -440,9 +460,17 @@ static bool object_render_hide(BL::Object& b_ob, parent = parent.parent(); } - hide_triangles = false; + hide_triangles = hide_emitter; - return (hide_as_dupli_parent || hide_as_dupli_child_original); + if(show_emitter) { + return false; + } + else if(hair_present) { + return hide_as_dupli_child_original; + } + else { + return (hide_as_dupli_parent || hide_as_dupli_child_original); + } } static bool object_render_hide_duplis(BL::Object& b_ob) @@ -465,6 +493,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time) light_map.pre_sync(); mesh_map.pre_sync(); object_map.pre_sync(); + particle_system_map.pre_sync(); motion_times.clear(); } else { @@ -526,15 +555,22 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time) BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id(); /* sync object and mesh or light data */ - sync_object(b_ob, - persistent_id.data, - *b_dup, - tfm, - ob_layer, - motion_time, - hide_tris, - culling, - &use_portal); + Object *object = sync_object(b_ob, + persistent_id.data, + *b_dup, + tfm, + ob_layer, + motion_time, + hide_tris, + culling, + &use_portal); + + /* sync possible particle data, note particle_id + * starts counting at 1, first is dummy particle */ + if(!motion && object) { + sync_dupli_particle(b_ob, *b_dup, object); + } + } } @@ -576,6 +612,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time) scene->mesh_manager->tag_update(scene); if(object_map.post_sync()) scene->object_manager->tag_update(scene); + if(particle_system_map.post_sync()) + scene->particle_system_manager->tag_update(scene); } if(motion) diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp new file mode 100644 index 00000000000..dd2900a8d5b --- /dev/null +++ b/intern/cycles/blender/blender_particles.cpp @@ -0,0 +1,92 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mesh.h" +#include "object.h" +#include "particles.h" + +#include "blender_sync.h" +#include "blender_util.h" + +#include "util_foreach.h" + +CCL_NAMESPACE_BEGIN + +/* Utilities */ + +bool BlenderSync::sync_dupli_particle(BL::Object& b_ob, + BL::DupliObject& b_dup, + Object *object) +{ + /* test if this dupli was generated from a particle sytem */ + BL::ParticleSystem b_psys = b_dup.particle_system(); + if(!b_psys) + return false; + + object->hide_on_missing_motion = true; + + /* test if we need particle data */ + if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE)) + return false; + + /* don't handle child particles yet */ + BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup.persistent_id(); + + if(persistent_id[0] >= b_psys.particles.length()) + return false; + + /* find particle system */ + ParticleSystemKey key(b_ob, persistent_id); + ParticleSystem *psys; + + bool first_use = !particle_system_map.is_used(key); + bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key); + + /* no update needed? */ + if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update) + return true; + + /* first time used in this sync loop? clear and tag update */ + if(first_use) { + psys->particles.clear(); + psys->tag_update(scene); + } + + /* add particle */ + BL::Particle b_pa = b_psys.particles[persistent_id[0]]; + Particle pa; + + pa.index = persistent_id[0]; + pa.age = b_scene.frame_current() - b_pa.birth_time(); + pa.lifetime = b_pa.lifetime(); + pa.location = get_float3(b_pa.location()); + pa.rotation = get_float4(b_pa.rotation()); + pa.size = b_pa.size(); + pa.velocity = get_float3(b_pa.velocity()); + pa.angular_velocity = get_float3(b_pa.angular_velocity()); + + psys->particles.push_back_slow(pa); + + if(object->particle_index != psys->particles.size() - 1) + scene->object_manager->tag_update(scene); + object->particle_system = psys; + object->particle_index = psys->particles.size() - 1; + + /* return that this object has particle data */ + return true; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index cfb32651c50..38b2ce19e8a 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -56,6 +56,7 @@ BlenderSync::BlenderSync(BL::RenderEngine& b_engine, object_map(&scene->objects), mesh_map(&scene->meshes), light_map(&scene->lights), + particle_system_map(&scene->particle_systems), world_map(NULL), world_recalc(false), scene(scene), @@ -143,6 +144,12 @@ bool BlenderSync::sync_recalc() if(b_ob->is_updated_data() || b_ob->data().is_updated()) light_map.set_recalc(*b_ob); } + + if(b_ob->is_updated_data()) { + BL::Object::particle_systems_iterator b_psys; + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) + particle_system_map.set_recalc(*b_ob); + } } BL::BlendData::meshes_iterator b_mesh; @@ -176,6 +183,7 @@ bool BlenderSync::sync_recalc() object_map.has_recalc() || light_map.has_recalc() || mesh_map.has_recalc() || + particle_system_map.has_recalc() || BlendDataObjects_is_updated_get(&b_data.ptr) || world_recalc; diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 08e0a9bd82f..6984cbda259 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -139,6 +139,11 @@ private: int width, int height, float motion_time); + /* particles */ + bool sync_dupli_particle(BL::Object& b_ob, + BL::DupliObject& b_dup, + Object *object); + /* Images. */ void sync_images(); @@ -157,6 +162,7 @@ private: id_map<ObjectKey, Object> object_map; id_map<void*, Mesh> mesh_map; id_map<ObjectKey, Light> light_map; + id_map<ParticleSystemKey, ParticleSystem> particle_system_map; set<Mesh*> mesh_synced; set<Mesh*> mesh_motion_synced; set<float> motion_times; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index ba696a83867..f17a61f0ac8 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -754,6 +754,33 @@ struct ObjectKey { } }; +/* Particle System Key */ + +struct ParticleSystemKey { + void *ob; + int id[OBJECT_PERSISTENT_ID_SIZE]; + + ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) + : ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } + + bool operator<(const ParticleSystemKey& k) const + { + /* first id is particle index, we don't compare that */ + if(ob < k.ob) + return true; + else if(ob == k.ob) + return memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0; + + return false; + } +}; + CCL_NAMESPACE_END #endif /* __BLENDER_UTIL_H__ */ diff --git a/intern/elbeem/extern/elbeem.h b/intern/elbeem/extern/elbeem.h index 3a4c18ab189..bd50b6f08dc 100644 --- a/intern/elbeem/extern/elbeem.h +++ b/intern/elbeem/extern/elbeem.h @@ -111,7 +111,7 @@ typedef struct elbeemSimulationSettings { #define OB_FLUIDSIM_OBSTACLE 8 #define OB_FLUIDSIM_INFLOW 16 #define OB_FLUIDSIM_OUTFLOW 32 -#define OB_FLUIDSIM_PARTICLE 64 /* DEPRECATED */ +#define OB_FLUIDSIM_PARTICLE 64 #define OB_FLUIDSIM_CONTROL 128 // defines for elbeemMesh->obstacleType below (low bits) high bits (>=64) are reserved for mFsSurfGenSetting flags which are defined in solver_class.h |