From 709ca0ece9b28858cea8084f8040ce0b7455958a Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sun, 18 Mar 2012 21:33:00 +0000 Subject: [PATCH] "Fix" for [#30098] Particle rotation wrong / explode modifier - The main problem was that in order to be accurate all particle rotations have to be calculated incrementally so the only working solution is to store rotations to the point cache (previously this was only done for dynamic rotations). This can nearly double the point cache size so it's not ideal to have this as a default as in many cases you don't care about particle rotations. - Particle rotation panel now has a new "enable" checkbox that enables rotation calculations and the storing of rotations to point cache. - Old files will have rotations enabled via do_versions so that in the worst case old files will only get bigger point caches, but no sudden loss of particle rotations. --- .../scripts/startup/bl_ui/properties_particle.py | 12 +++++++++++- .../blender/blenkernel/intern/particle_system.c | 6 ++++++ source/blender/blenkernel/intern/pointcache.c | 16 +++++++++------- source/blender/blenloader/intern/readfile.c | 7 +++++++ source/blender/makesdna/DNA_particle_types.h | 2 +- source/blender/makesrna/intern/rna_particle.c | 6 ++++++ 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 4e511f18cd4..c987ceb2562 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -380,6 +380,7 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel): class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): bl_label = "Rotation" + bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER'} @classmethod @@ -394,6 +395,15 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): else: return False + def draw_header(self, context): + psys = context.particle_system + if psys: + part = psys.settings + else: + part = context.space_data.pin_id + + self.layout.prop(part, "use_rotations", text="") + def draw(self, context): layout = self.layout @@ -403,7 +413,7 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): else: part = context.space_data.pin_id - layout.enabled = particle_panel_enabled(context, psys) + layout.enabled = particle_panel_enabled(context, psys) and part.use_rotations layout.prop(part, "use_dynamic_rotation") diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 8b34bafc417..c3e7e4531b9 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2684,6 +2684,12 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f { float rotfac, rot1[4], rot2[4]={1.0,0.0,0.0,0.0}, dtime=dfra*timestep; + if((part->flag & PART_ROTATIONS)==0) { + pa->state.rot[0]=1.0f; + pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0; + return; + } + if((part->flag & PART_ROT_DYN)==0) { if(part->avemode==PART_AVE_SPIN) { float angle; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index b3c242178f1..622c3ebe119 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -315,9 +315,10 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float cf } } - /* determine rotation from velocity */ + /* default to no rotation */ if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { - vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ); + pa->state.rot[0]=1.0f; + pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0; } } static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) @@ -815,13 +816,14 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p pid->read_extra_data = ptcache_particle_extra_read; } - if(psys->part->rotmode!=PART_ROT_VEL - || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) - pid->data_types|= (1<part->flag & PART_ROT_DYN) + if(psys->part->flag & PART_ROTATIONS) { pid->data_types|= (1<part->rotmode!=PART_ROT_VEL + || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) + pid->data_types|= (1<info_types= (1<default_step = 10; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6dc2dea44f0..95a76dac616 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -13292,6 +13292,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + { + /* Default for old files is to save particle rotations to pointcache */ + ParticleSettings *part; + for (part = main->particle.first; part; part = part->id.next) + part->flag |= PART_ROTATIONS; + } + /* put compatibility code here until next subversion bump */ { diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 220ee69b442..5bb4d1009e9 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -321,7 +321,7 @@ typedef struct ParticleSystem #define PART_TRAND 128 #define PART_EDISTR 256 /* particle/face from face areas */ -//#define PART_STICKY 512 /*collided particles can stick to collider*/ +#define PART_ROTATIONS 512 /* calculate particle rotations (and store them in pointcache) */ #define PART_DIE_ON_COL (1<<12) #define PART_SIZE_DEFL (1<<13) /* swept sphere deflections */ #define PART_ROT_DYN (1<<14) /* dynamic rotation */ diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index a83195acfe7..35b5ca571cb 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1661,6 +1661,12 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Size Deflect", "Use particle's size in deflection"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); + prop = RNA_def_property(srna, "use_rotations", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ROTATIONS); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Rotations", "Calculate particle rotations"); + RNA_def_property_update(prop, 0, "rna_Particle_reset"); + prop = RNA_def_property(srna, "use_dynamic_rotation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ROT_DYN); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);