diff options
author | Janne Karhu <jhkarh@gmail.com> | 2011-02-04 18:48:13 +0300 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2011-02-04 18:48:13 +0300 |
commit | 4e8a8d1e8f59c2b97ce064d52fdab290ca8b2f3d (patch) | |
tree | 49b40239e1b676aa27415db051bc71e1f115e406 /source | |
parent | b407702c5f13a0d2cf77d6728722d6f909e4d19e (diff) |
Improvements for particle grid distribution:
* Particles that aren't shown are now actually deleted (huge memory savings for flat objects).
* Grid distribution for flat objects is now done on the surface object surface without offset.
* Invert grid option wasn't in ui and it didn't work for non-volume grids.
* New parameter to randomize the grid point locations.
* Resolution soft/hard limits changed to even 50/250.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 77 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_particle_types.h | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_particle.c | 12 |
3 files changed, 82 insertions, 13 deletions
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index a0948e61708..4d3a908edb0 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -137,9 +137,9 @@ static int tot_particles(ParticleSystem *psys, PTCacheID *pid) if(pid && psys->pointcache->flag & PTCACHE_EXTERNAL) return pid->cache->totpoint; else if(psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) - return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res; + return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist; else - return psys->part->totpart; + return psys->part->totpart - psys->totunexist; } void psys_reset(ParticleSystem *psys, int mode) @@ -439,9 +439,14 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) size[(axis+1)%3] = MIN2(size[(axis+1)%3],res); size[(axis+2)%3] = MIN2(size[(axis+2)%3],res); - min[0]+=d/2.0f; - min[1]+=d/2.0f; - min[2]+=d/2.0f; + size[0] = MAX2(size[0], 1); + size[1] = MAX2(size[1], 1); + size[2] = MAX2(size[2], 1); + + /* no full offset for flat/thin objects */ + min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f; + min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f; + min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f; for(i=0,p=0,pa=psys->particles; i<res; i++){ for(j=0; j<res; j++){ @@ -497,7 +502,7 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) pa=psys->particles + a1*a1mul + a2*a2mul; VECCOPY(co1,pa->fuv); - co1[a]-=d/2.0f; + co1[a]-= d < delta[a] ? d/2.f : delta[a]/2.f; VECCOPY(co2,co1); co2[a]+=delta[a] + 0.001f*d; co1[a]-=0.001f*d; @@ -553,6 +558,18 @@ static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys) } } } + + if(psys->part->grid_rand > 0.f) { + float rfac = d * psys->part->grid_rand; + for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){ + if(pa->flag & PARS_UNEXIST) + continue; + + pa->fuv[0] += rfac * (PSYS_FRAND(p + 31) - 0.5f); + pa->fuv[1] += rfac * (PSYS_FRAND(p + 32) - 0.5f); + pa->fuv[2] += rfac * (PSYS_FRAND(p + 33) - 0.5f); + } + } } /* modified copy from rayshade.c */ @@ -1554,8 +1571,51 @@ static void initialize_all_particles(ParticleSimulationData *sim) ParticleSystem *psys = sim->psys; PARTICLE_P; - LOOP_PARTICLES + psys->totunexist = 0; + + LOOP_PARTICLES { initialize_particle(sim, pa, p); + if(pa->flag & PARS_UNEXIST) + psys->totunexist++; + } + + /* Free unexisting particles. */ + if(psys->totpart && psys->totunexist == psys->totpart) { + if(psys->particles->boid) + MEM_freeN(psys->particles->boid); + + MEM_freeN(psys->particles); + psys->particles = NULL; + psys->totpart = psys->totunexist = 0; + } + + if(psys->totunexist) { + int newtotpart = psys->totpart - psys->totunexist; + ParticleData *npa, *newpars; + + npa = newpars = MEM_callocN(newtotpart * sizeof(ParticleData), "particles"); + + for(p=0, pa=psys->particles; p<newtotpart; p++, pa++, npa++) { + while(pa->flag & PARS_UNEXIST) + pa++; + + memcpy(npa, pa, sizeof(ParticleData)); + } + + if(psys->particles->boid) + MEM_freeN(psys->particles->boid); + MEM_freeN(psys->particles); + psys->particles = newpars; + psys->totpart -= psys->totunexist; + + if(psys->particles->boid) { + BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles"); + + LOOP_PARTICLES + pa->boid = newboids++; + + } + } if(psys->part->type != PART_FLUID) { #if 0 // XXX old animation system @@ -4091,6 +4151,9 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) if(psys->recalc & PSYS_RECALC_TYPE) psys_changed_type(&sim); + if(psys->recalc & PSYS_RECALC_RESET) + psys->totunexist = 0; + /* setup necessary physics type dependent additional data if it doesn't yet exist */ psys_prepare_physics(&sim); diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index f009f3a9eb0..9ead2a3f572 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -168,8 +168,8 @@ typedef struct ParticleSettings { /* general values */ float sta, end, lifetime, randlife; - float timetweak, jitfac, eff_hair; - int totpart, userjit, grid_res; + float timetweak, jitfac, eff_hair, grid_rand; + int totpart, userjit, grid_res, rt; /* initial velocity factors */ float normfac, obfac, randfac, partfac, tanfac, tanphase, reactfac; @@ -247,7 +247,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in float imat[4][4]; /* used for duplicators */ float cfra, tree_frame; int seed, child_seed; - int flag, totpart, totchild, totcached, totchildcache; + int flag, totpart, totunexist, totchild, totcached, totchildcache, rt; short recalc, target_psys, totkeyed, bakespace; char bb_uvname[3][32]; /* billboard uv name */ diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index cbf8c7093d7..82e2eb96002 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1289,7 +1289,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop= RNA_def_property(srna, "invert_grid", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_GRID_INVERT); - RNA_def_property_ui_text(prop, "Invert", "Invert what is considered object and what is not"); + RNA_def_property_ui_text(prop, "Invert Grid", "Invert what is considered object and what is not"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); prop= RNA_def_property(srna, "apply_effector_to_children", PROP_BOOLEAN, PROP_NONE); @@ -1684,11 +1684,17 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop= RNA_def_property(srna, "grid_resolution", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "grid_res"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_range(prop, 1, 215); /* ~10M particles in a cube */ - RNA_def_property_ui_range(prop, 1, 46, 1, 0); /* ~100k particles in a cube */ + RNA_def_property_range(prop, 1, 250); /* ~15M particles in a cube (ouch!), but could be very usable in a plane */ + RNA_def_property_ui_range(prop, 1, 50, 1, 0); /* ~100k particles in a cube */ RNA_def_property_ui_text(prop, "Resolution", "The resolution of the particle grid"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); + prop= RNA_def_property(srna, "grid_random", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "grid_rand"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Grid Randomness", "Add random offset to the grid locations"); + RNA_def_property_update(prop, 0, "rna_Particle_reset"); + /* initial velocity factors */ prop= RNA_def_property(srna, "normal_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "normfac");//optional if prop names are the same |