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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/CMakeLists.txt1
-rw-r--r--intern/cycles/blender/addon/properties.py45
-rw-r--r--intern/cycles/blender/addon/ui.py68
-rw-r--r--intern/cycles/blender/blender_curves.cpp245
-rw-r--r--intern/cycles/blender/blender_object.cpp60
-rw-r--r--intern/cycles/blender/blender_particles.cpp92
-rw-r--r--intern/cycles/blender/blender_sync.cpp8
-rw-r--r--intern/cycles/blender/blender_sync.h6
-rw-r--r--intern/cycles/blender/blender_util.h27
-rw-r--r--intern/elbeem/extern/elbeem.h2
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