diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_particle.py | 34 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim.c | 12 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 65 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 14 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_particle_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_particle.c | 11 |
6 files changed, 99 insertions, 40 deletions
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index eceefc70b5c..d24aef56a8b 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -404,10 +404,13 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): part = context.space_data.pin_id layout.enabled = particle_panel_enabled(context, psys) + + layout.prop(part, "use_dynamic_rotation") - row = layout.row() - row.label(text="Initial Rotation:") - row.prop(part, "use_dynamic_rotation") + if part.use_dynamic_rotation: + layout.label(text="Initial Rotation Axis:") + else: + layout.label(text="Rotation Axis:") split = layout.split() @@ -419,12 +422,18 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): col.prop(part, "phase_factor", slider=True) col.prop(part, "phase_factor_random", text="Random", slider=True) - col = layout.column() - col.label(text="Angular Velocity:") - col.row().prop(part, "angular_velocity_mode", expand=True) - - if part.angular_velocity_mode != 'NONE': - col.prop(part, "angular_velocity_factor", text="") + if part.type != 'HAIR': + col = layout.column() + if part.use_dynamic_rotation: + col.label(text="Initial Angular Velocity:") + else: + col.label(text="Angular Velocity:") + sub = col.row(align=True) + sub.prop(part, "angular_velocity_mode", text="") + subsub = sub.column() + subsub.active = part.angular_velocity_mode != 'NONE' + subsub.prop(part, "angular_velocity_factor", text="") + class PARTICLE_PT_physics(ParticleButtonsPanel, Panel): @@ -832,7 +841,9 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): elif part.render_type == 'OBJECT': col.prop(part, "dupli_object") - col.prop(part, "use_global_dupli") + sub = col.row() + sub.prop(part, "use_global_dupli") + sub.prop(part, "use_rotation_dupli") elif part.render_type == 'GROUP': col.prop(part, "dupli_group") split = layout.split() @@ -841,13 +852,14 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): col.prop(part, "use_whole_group") sub = col.column() sub.active = (part.use_whole_group is False) + sub.prop(part, "use_group_pick_random") sub.prop(part, "use_group_count") col = split.column() sub = col.column() sub.active = (part.use_whole_group is False) sub.prop(part, "use_global_dupli") - sub.prop(part, "use_group_pick_random") + sub.prop(part, "use_rotation_dupli") if part.use_group_count and not part.use_whole_group: row = layout.row() diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index cd2c272a1c2..da6dd5bd39d 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -1430,6 +1430,16 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p VECCOPY(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; + + /* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */ + if((part->draw & PART_DRAW_ROTATE_OB) == 0) { + float xvec[3], q[4]; + xvec[0] = -1.f; + xvec[1] = xvec[2] = 0; + vec_to_quat(q, xvec, ob->trackflag, ob->upflag); + quat_to_mat4(obmat, q); + obmat[3][3]= 1.0f; + } /* Normal particles and cached hair live in global space so we need to * remove the real emitter's transformation before 2nd order duplication. @@ -1448,7 +1458,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p copy_m4_m4(mat, tmat); if(part->draw & PART_DRAW_GLOBAL_OB) - VECADD(mat[3], mat[3], vec); + add_v3_v3v3(mat[3], mat[3], vec); dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); copy_m4_m4(dob->omat, oldobmat); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 806a7871948..8669c4e0efd 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4384,33 +4384,50 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); else psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0); - - copy_m3_m4(nmat, ob->imat); - transpose_m3(nmat); - mul_m3_v3(nmat, nor); - normalize_v3(nor); - - /* make sure that we get a proper side vector */ - if(fabs(dot_v3v3(nor,vec))>0.999999) { - if(fabs(dot_v3v3(nor,xvec))>0.999999) { - nor[0] = 0.0f; - nor[1] = 1.0f; - nor[2] = 0.0f; + + if(psys->part->rotmode == PART_ROT_VEL) { + copy_m3_m4(nmat, ob->imat); + transpose_m3(nmat); + mul_m3_v3(nmat, nor); + normalize_v3(nor); + + /* make sure that we get a proper side vector */ + if(fabs(dot_v3v3(nor,vec))>0.999999) { + if(fabs(dot_v3v3(nor,xvec))>0.999999) { + nor[0] = 0.0f; + nor[1] = 1.0f; + nor[2] = 0.0f; + } + else { + nor[0] = 1.0f; + nor[1] = 0.0f; + nor[2] = 0.0f; + } } - else { - nor[0] = 1.0f; - nor[1] = 0.0f; - nor[2] = 0.0f; + cross_v3_v3v3(side, nor, vec); + normalize_v3(side); + + /* rotate side vector around vec */ + if(psys->part->phasefac != 0) { + float q_phase[4]; + float phasefac = psys->part->phasefac; + if(psys->part->randphasefac != 0.0f) + phasefac += psys->part->randphasefac * PSYS_FRAND((pa-psys->particles) + 20); + axis_angle_to_quat( q_phase, vec, phasefac*(float)M_PI); + + mul_qt_v3(q_phase, side); } - } - cross_v3_v3v3(side, nor, vec); - normalize_v3(side); - cross_v3_v3v3(nor, vec, side); - unit_m4(mat); - VECCOPY(mat[0], vec); - VECCOPY(mat[1], side); - VECCOPY(mat[2], nor); + cross_v3_v3v3(nor, vec, side); + + unit_m4(mat); + VECCOPY(mat[0], vec); + VECCOPY(mat[1], side); + VECCOPY(mat[2], nor); + } + else { + quat_to_mat4(mat, pa->state.rot); + } *scale= len; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 76070e42f29..84b9021d080 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -12176,6 +12176,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) do_versions_nodetree_image_default_alpha_output(ntree); } + + { + /* support old particle dupliobject rotation settings */ + ParticleSettings *part; + + for (part=main->particle.first; part; part=part->id.next) { + if(ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { + part->draw |= PART_DRAW_ROTATE_OB; + + if(part->rotmode == 0) + part->rotmode = PART_ROT_VEL; + } + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 9fec5207dbb..da2fce4da82 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -386,7 +386,8 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PART_DRAW_HEALTH 16 #define PART_ABS_PATH_TIME 32 #define PART_DRAW_COUNT_GR 64 -#define PART_DRAW_BB_LOCK 128 +#define PART_DRAW_BB_LOCK 128 /* used with billboards */ +#define PART_DRAW_ROTATE_OB 128 /* used with dupliobjects/groups */ #define PART_DRAW_PARENT 256 #define PART_DRAW_NUM 512 #define PART_DRAW_RAND_GR 1024 diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 49005e56367..43d5f87f0d5 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1478,7 +1478,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) static EnumPropertyItem rot_mode_items[] = { {0, "NONE", 0, "None", ""}, {PART_ROT_NOR, "NOR", 0, "Normal", ""}, - {PART_ROT_VEL, "VEL", 0, "Velocity", ""}, + {PART_ROT_VEL, "VEL", 0, "Velocity / Hair", ""}, {PART_ROT_GLOB_X, "GLOB_X", 0, "Global X", ""}, {PART_ROT_GLOB_Y, "GLOB_Y", 0, "Global Y", ""}, {PART_ROT_GLOB_Z, "GLOB_Z", 0, "Global Z", ""}, @@ -1733,7 +1733,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "rotmode"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_enum_items(prop, rot_mode_items); - RNA_def_property_ui_text(prop, "Rotation", "Particles initial rotation"); + RNA_def_property_ui_text(prop, "Rotation", "Particle rotation axis"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); prop= RNA_def_property(srna, "angular_velocity_mode", PROP_ENUM, PROP_NONE); @@ -1798,7 +1798,12 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop= RNA_def_property(srna, "use_global_dupli", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GLOBAL_OB); - RNA_def_property_ui_text(prop, "Use Global", "Use object's global coordinates for duplication"); + RNA_def_property_ui_text(prop, "Global", "Use object's global coordinates for duplication"); + RNA_def_property_update(prop, 0, "rna_Particle_redo"); + + prop= RNA_def_property(srna, "use_rotation_dupli", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_ROTATE_OB); + RNA_def_property_ui_text(prop, "Rotation", "Use object's rotation for duplication (global x-axis is aligned particle rotation axis)"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); prop= RNA_def_property(srna, "use_render_adaptive", PROP_BOOLEAN, PROP_NONE); |