diff options
author | Janne Karhu <jhkarh@gmail.com> | 2011-02-12 17:38:34 +0300 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2011-02-12 17:38:34 +0300 |
commit | fafbd9d71b95776d1c7583476de74fccefab7f10 (patch) | |
tree | 838e0fbc2e53c0700a87ebc1fdf4798837ffda3e /source/blender/blenkernel | |
parent | c8c86aa6a12a253680aa266ce1c5d51b1b39005a (diff) |
Particles todo item: particle textures
* Effecting particle properties with textures was possible in 2.49,
but not in 2.5 anymore.
* Now particles have their own textures (available in texture panel
for objects with particle systems), which are totally separate from
the material textures.
* Currently a basic set of particle properties is available for
texture control. Some others could still be added, but the whole
system is not intended as an "change anything with a texture" as
this kind of functionality will be provided with node particles in
the future much better.
* Combined with the previously added "particle texture coordinates"
this new functionality also solves the problem of animating particle
properties through the particle lifetime nicely.
* Currently the textures only use the intensity of the texture in
"multiply" blending mode, so in order for the textures to effect
a particle parameter there has to be a non-zero value defined for
the parameter in the particle settings. Other blend modes can be
added later if they're considered useful enough.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_texture.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/depsgraph.c | 24 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 241 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 359 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/texture.c | 41 |
6 files changed, 322 insertions, 359 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 3f7523d5264..5c72973a0da 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -80,20 +80,10 @@ typedef struct ParticleSimulationData { struct ListBase *colliders; } ParticleSimulationData; -//typedef struct ParticleReactEvent { -// struct ParticleReactEvent *next, *prev; -// int event, pa_num; -// Object *ob; -// struct ParticleSystem *psys; -// struct ParticleKey state; -// -// float time, size; -//}ParticleReactEvent; - typedef struct ParticleTexture{ float ivel; /* used in reset */ float time, life, exist, size; /* used in init */ - float pvel[3]; /* used in physics */ + float damp, gravity, field; /* used in physics */ float length, clump, kink, effector;/* used in path caching */ float rough1, rough2, roughe; /* used in path caching */ } ParticleTexture; @@ -291,7 +281,7 @@ float psys_get_dietime_from_cache(struct PointCache *cache, int index); void psys_free_pdd(struct ParticleSystem *psys); float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); -void psys_get_texture(struct ParticleSimulationData *sim, struct Material *ma, struct ParticleData *pa, struct ParticleTexture *ptex, int event); +void psys_get_texture(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleTexture *ptex, int event, float cfra); void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float *uv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values); void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index cbae90f4c38..d559350a780 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -84,6 +84,7 @@ struct Tex *give_current_material_texture(struct Material *ma); struct Tex *give_current_lamp_texture(struct Lamp *la); struct Tex *give_current_world_texture(struct World *world); struct Tex *give_current_brush_texture(struct Brush *br); +struct Tex *give_current_particle_texture(struct ParticleSettings *part); struct bNode *give_current_material_texture_node(struct Material *ma); @@ -94,6 +95,7 @@ void set_current_brush_texture(struct Brush *br, struct Tex *tex); void set_current_world_texture(struct World *wo, struct Tex *tex); void set_current_material_texture(struct Material *ma, struct Tex *tex); void set_current_lamp_texture(struct Lamp *la, struct Tex *tex); +void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex); struct TexMapping *add_mapping(void); void init_mapping(struct TexMapping *texmap); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 6db4e0ac081..07a47f84af5 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -40,6 +40,7 @@ #include "DNA_group_types.h" #include "DNA_lattice_types.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" @@ -2375,6 +2376,29 @@ static void dag_id_flush_update(Scene *sce, ID *id) modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data); if (data.is_dependent) obt->recalc |= OB_RECALC_DATA; + + /* particle settings can use the texture as well */ + if(obt->particlesystem.first) { + ParticleSystem *psys = obt->particlesystem.first; + MTex **mtexp, *mtex; + int a; + for(; psys; psys=psys->next) { + mtexp = psys->part->mtex; + for(a=0; a<MAX_MTEX; a++, mtexp++) { + mtex = *mtexp; + if(mtex && mtex->tex == (Tex*)id) { + obt->recalc |= OB_RECALC_DATA; + + if(mtex->mapto & PAMAP_INIT) + psys->recalc |= PSYS_RECALC_RESET; + if(mtex->mapto & PAMAP_CHILD) + psys->recalc |= PSYS_RECALC_CHILD; + + BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); + } + } + } + } } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 5f45e06cfc4..38fd11b086f 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -77,8 +77,6 @@ #include "RE_render_ext.h" -static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, - float *fuv, float *orco, ParticleTexture *ptex, int event); static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); static void do_child_modifiers(ParticleSimulationData *sim, @@ -2860,6 +2858,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) Material *ma; ParticleInterpolationData pind; + ParticleTexture ptex; PARTICLE_P; @@ -2909,8 +2908,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) /*---first main loop: create all actual particles' paths---*/ LOOP_SHOWN_PARTICLES { if(!psys->totchild) { - BLI_srandom(psys->seed + p); - pa_length = 1.0f - part->randlength * BLI_frand(); + psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f); + pa_length = ptex.length * (1.0f - part->randlength * PSYS_FRAND(psys->seed + p)); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); } @@ -3674,82 +3673,128 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, fl return 1; } -static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float *fw, float *orco, ParticleTexture *ptex, int event) +#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) if((event & mtex->mapto) & type) {pvalue = texture_value_blend(def, pvalue, value, texfac, blend);} +#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) if(event & type) { if(pvalue < 0.f) pvalue = 1.f+pvalue; CLAMP(pvalue, 0.0, 1.0); } +#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) if(event & type) { CLAMP(pvalue, -1.0, 1.0); } + +static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, float *fw, float *orco, ParticleTexture *ptex, int event, float cfra) { - MTex *mtex; + MTex *mtex, **mtexp = part->mtex; int m,setvars=0; - float value, rgba[4], texco[3]; + float value, rgba[4], texvec[3]; - if(ma) for(m=0; m<MAX_MTEX; m++){ - mtex=ma->mtex[m]; - if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){ + ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = + ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + + ptex->length= 1.0f - part->randlength * PSYS_FRAND(child_index + 26); + ptex->length*= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; + + for(m=0; m<MAX_MTEX; m++, mtexp++){ + mtex = *mtexp; + if(mtex && mtex->mapto){ float def=mtex->def_var; short blend=mtex->blendtype; + short texco = mtex->texco; - if((mtex->texco & TEXCO_UV) && fw) { - if(!get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texco)) - VECCOPY(texco,orco); - } - else - VECCOPY(texco,orco); + if(ELEM(texco, TEXCO_UV, TEXCO_ORCO) && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID)) + texco = TEXCO_GLOB; - externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3, 0); - if((event & mtex->pmapto) & MAP_PA_TIME){ - if((setvars&MAP_PA_TIME)==0){ - ptex->time=0.0; - setvars|=MAP_PA_TIME; - } - ptex->time= texture_value_blend(mtex->def_var,ptex->time,value,mtex->timefac,blend); + switch(texco) { + case TEXCO_GLOB: + copy_v3_v3(texvec, par->state.co); + break; + case TEXCO_OBJECT: + copy_v3_v3(texvec, par->state.co); + if(mtex->object) + mul_m4_v3(mtex->object->imat, texvec); + break; + case TEXCO_UV: + if(fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec)) + break; + /* no break, failed to get uv's, so let's try orco's */ + case TEXCO_ORCO: + copy_v3_v3(texvec, orco); + break; + case TEXCO_PARTICLE: + /* texture coordinates in range [-1,1] */ + texvec[0] = 2.f * (cfra - par->time)/(par->dietime-par->time) - 1.f; + texvec[1] = 0.f; + texvec[2] = 0.f; + break; } - if((event & mtex->pmapto) & MAP_PA_LENGTH) - ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend); - if((event & mtex->pmapto) & MAP_PA_CLUMP) - ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend); - if((event & mtex->pmapto) & MAP_PA_KINK) - ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend); - if((event & mtex->pmapto) & MAP_PA_ROUGH) + + externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0); + + if((event & mtex->mapto) & PAMAP_ROUGH) ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,mtex->roughfac,blend); - if((event & mtex->pmapto) & MAP_PA_DENS) - ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend); + + SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac); + SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac); + SET_PARTICLE_TEXTURE(PAMAP_KINK, ptex->kink, mtex->kinkfac); + SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac); } } - if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } - if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } - if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } - if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } - if(event & MAP_PA_ROUGH) { - CLAMP(ptex->rough1,0.0,1.0); - CLAMP(ptex->rough2,0.0,1.0); - CLAMP(ptex->roughe,0.0,1.0); - } - if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } + + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_KINK, ptex->kink); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1); + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist); } -void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *pa, ParticleTexture *ptex, int event) +void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra) { + ParticleSettings *part = sim->psys->part; + MTex **mtexp = part->mtex; MTex *mtex; int m; - float value, rgba[4], co[3], texco[3]; + float value, rgba[4], co[3], texvec[3]; int setvars=0; - if(ma) for(m=0; m<MAX_MTEX; m++){ - mtex=ma->mtex[m]; - if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){ + /* initialize ptex */ + ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = + ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + + ptex->time = (float)(pa - sim->psys->particles)/(float)sim->psys->totpart; + + for(m=0; m<MAX_MTEX; m++, mtexp++){ + mtex = *mtexp; + if(mtex && mtex->mapto){ float def=mtex->def_var; short blend=mtex->blendtype; + short texco = mtex->texco; - if((mtex->texco & TEXCO_UV) && ELEM(sim->psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { - if(!get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { - /* failed to get uv's, let's try orco's */ - psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); - } - } - else { - psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + if(ELEM(texco, TEXCO_UV, TEXCO_ORCO) && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID)) + texco = TEXCO_GLOB; + + switch(texco) { + case TEXCO_GLOB: + copy_v3_v3(texvec, pa->state.co); + break; + case TEXCO_OBJECT: + copy_v3_v3(texvec, pa->state.co); + if(mtex->object) + mul_m4_v3(mtex->object->imat, texvec); + break; + case TEXCO_UV: + if(get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texvec)) + break; + /* no break, failed to get uv's, so let's try orco's */ + case TEXCO_ORCO: + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texvec, 0); + break; + case TEXCO_PARTICLE: + /* texture coordinates in range [-1,1] */ + texvec[0] = 2.f * (cfra - pa->time)/(pa->dietime-pa->time) - 1.f; + texvec[1] = 0.f; + texvec[2] = 0.f; + break; } - externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3, 0); + externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0); - if((event & mtex->pmapto) & MAP_PA_TIME){ + if((event & mtex->mapto) & PAMAP_TIME) { /* the first time has to set the base value for time regardless of blend mode */ if((setvars&MAP_PA_TIME)==0){ int flip= (mtex->timefac < 0.0f); @@ -3761,32 +3806,26 @@ void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *p else ptex->time= texture_value_blend(def,ptex->time,value,mtex->timefac,blend); } - if((event & mtex->pmapto) & MAP_PA_LIFE) - ptex->life= texture_value_blend(def,ptex->life,value,mtex->lifefac,blend); - if((event & mtex->pmapto) & MAP_PA_DENS) - ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend); - if((event & mtex->pmapto) & MAP_PA_SIZE) - ptex->size= texture_value_blend(def,ptex->size,value,mtex->sizefac,blend); - if((event & mtex->pmapto) & MAP_PA_IVEL) - ptex->ivel= texture_value_blend(def,ptex->ivel,value,mtex->ivelfac,blend); - if((event & mtex->pmapto) & MAP_PA_PVEL) - texture_rgb_blend(ptex->pvel,rgba,ptex->pvel,value,mtex->pvelfac,blend); - if((event & mtex->pmapto) & MAP_PA_LENGTH) - ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend); - if((event & mtex->pmapto) & MAP_PA_CLUMP) - ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend); - if((event & mtex->pmapto) & MAP_PA_KINK) - ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend); - } - } - if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } - if(event & MAP_PA_LIFE) { CLAMP(ptex->life,0.0,1.0); } - if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } - if(event & MAP_PA_SIZE) { CLAMP(ptex->size,0.0,1.0); } - if(event & MAP_PA_IVEL) { CLAMP(ptex->ivel,0.0,1.0); } - if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); } - if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } - if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } + SET_PARTICLE_TEXTURE(PAMAP_LIFE, ptex->life, mtex->lifefac) + SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac) + SET_PARTICLE_TEXTURE(PAMAP_SIZE, ptex->size, mtex->sizefac) + SET_PARTICLE_TEXTURE(PAMAP_IVEL, ptex->ivel, mtex->ivelfac) + SET_PARTICLE_TEXTURE(PAMAP_FIELD, ptex->field, mtex->fieldfac) + SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac) + SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac) + SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac) + } + } + + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_TIME, ptex->time) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LIFE, ptex->life) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_SIZE, ptex->size) + CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_IVEL, ptex->ivel) + CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_FIELD, ptex->field) + CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_GRAVITY, ptex->gravity) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp) + CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length) } /************************************************/ /* Particle State */ @@ -3829,28 +3868,8 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED ParticleSettings *part = psys->part; float size; // time XXX - if(part->childtype==PART_CHILD_FACES){ + if(part->childtype==PART_CHILD_FACES) size=part->size; - -#if 0 // XXX old animation system - if((part->flag&PART_ABS_TIME)==0 && part->ipo){ - IpoCurve *icu; - - if(pa_time) - time=*pa_time; - else - time=psys_get_child_time(psys,cpa,cfra,NULL,NULL); - - /* correction for lifetime */ - calc_ipo(part->ipo, 100*time); - - for(icu = part->ipo->curve.first; icu; icu=icu->next) { - if(icu->adrcode == PART_SIZE) - size = icu->curval; - } - } -#endif // XXX old animation system - } else size=psys->particles[cpa->parent].size; @@ -3866,19 +3885,7 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread ParticleSystem *psys = ctx->sim.psys; int i = cpa - psys->child; - ptex->length= 1.0f - part->randlength * PSYS_FRAND(i + 26); - ptex->clump=1.0; - ptex->kink=1.0; - ptex->rough1= 1.0; - ptex->rough2= 1.0; - ptex->roughe= 1.0; - ptex->exist= 1.0; - ptex->effector= 1.0; - - ptex->length*= part->clength_thres < PSYS_FRAND(i + 27) ? part->clength : 1.0f; - - get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex, - MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); + get_cpa_texture(ctx->dm, psys, part, psys->particles + cpa->pa[0], i, cpa_num, cpa_fuv, orco, ptex, PAMAP_DENS|PAMAP_CHILD, psys->cfra); if(ptex->exist < PSYS_FRAND(i + 24)) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2e2decdf84d..409e9876599 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1519,62 +1519,37 @@ void psys_threads_free(ParticleThread *threads) /* set particle parameters that don't change during particle's life */ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) { - ParticleSettings *part = sim->psys->part; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; ParticleTexture ptex; - Material *ma=0; - //IpoCurve *icu=0; // XXX old animation system - int totpart; - - totpart=sim->psys->totpart; - - ptex.life=ptex.size=ptex.exist=ptex.length=1.0; - ptex.time=(float)p/(float)totpart; - - BLI_srandom(sim->psys->seed + p + 125); - - if(part->from!=PART_FROM_PARTICLE && part->type!=PART_FLUID){ - ma=give_current_material(sim->ob,part->omat); - - /* TODO: needs some work to make most blendtypes generally usefull */ - psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT); - } - - if(part->type==PART_HAIR) - pa->time= 0.0f; - //else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) - // pa->time= 300000.0f; /* max frame */ - else{ - //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME); - //if(icu){ - // calc_icu(icu,100*ptex.time); - // ptex.time=icu->curval; - //} - pa->time= part->sta + (part->end - part->sta)*ptex.time; - } + pa->flag &= ~PARS_UNEXIST; - if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){ - if(ptex.exist < BLI_frand()) + if(part->from != PART_FROM_PARTICLE && part->type != PART_FLUID) { + psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); + + if(ptex.exist < PSYS_FRAND(p+125)) pa->flag |= PARS_UNEXIST; - else - pa->flag &= ~PARS_UNEXIST; + + pa->time = (part->type == PART_HAIR) ? 0.f : part->sta + (part->end - part->sta)*ptex.time; } - pa->hair_index=0; + pa->hair_index = 0; /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */ /* usage other than straight after distribute has to handle this index by itself - jahka*/ //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */ } static void initialize_all_particles(ParticleSimulationData *sim) { - //IpoCurve *icu=0; // XXX old animation system ParticleSystem *psys = sim->psys; PARTICLE_P; psys->totunexist = 0; LOOP_PARTICLES { - initialize_particle(sim, pa, p); + if((pa->flag & PARS_UNEXIST)==0) + initialize_particle(sim, pa, p); + if(pa->flag & PARS_UNEXIST) psys->totunexist++; } @@ -1616,60 +1591,6 @@ static void initialize_all_particles(ParticleSimulationData *sim) } } - - if(psys->part->type != PART_FLUID) { -#if 0 // XXX old animation system - icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ); - if(icu){ - float time=psys->part->sta, end=psys->part->end; - float v1, v2, a=0.0f, t1,t2, d; - - p=0; - pa=psys->particles; - - - calc_icu(icu,time); - v1=icu->curval; - if(v1<0.0f) v1=0.0f; - - calc_icu(icu,time+1.0f); - v2=icu->curval; - if(v2<0.0f) v2=0.0f; - - for(p=0, pa=psys->particles; p<totpart && time<end; p++, pa++){ - while(a+0.5f*(v1+v2) < (float)(p+1) && time<end){ - a+=0.5f*(v1+v2); - v1=v2; - time++; - calc_icu(icu,time+1.0f); - v2=icu->curval; - } - if(time<end){ - if(v1==v2){ - pa->time=time+((float)(p+1)-a)/v1; - } - else{ - d=(float)sqrt(v1*v1-2.0f*(v2-v1)*(a-(float)(p+1))); - t1=(-v1+d)/(v2-v1); - t2=(-v1-d)/(v2-v1); - - /* the root between 0-1 is the correct one */ - if(t1>0.0f && t1<=1.0f) - pa->time=time+t1; - else - pa->time=time+t2; - } - } - - pa->dietime = pa->time+pa->lifetime; - pa->flag &= ~PARS_UNEXIST; - } - for(; p<totpart; p++, pa++){ - pa->flag |= PARS_UNEXIST; - } - } -#endif // XXX old animation system - } } /* sets particle to the emitter surface with initial velocity & rotation */ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra) @@ -1678,35 +1599,14 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, ParticleSystem *psys = sim->psys; ParticleSettings *part; ParticleTexture ptex; - ParticleKey state; - //IpoCurve *icu=0; // XXX old animation system float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; - float q_phase[4], r_phase; + float q_phase[4]; int p = pa - psys->particles; part=psys->part; - - ptex.ivel=1.0; - ptex.life=1.0; - - /* we need to get every random even if they're not used so that they don't effect eachother */ - r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); - r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); - r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); - - r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); - r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); - r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); - - r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); - r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); - r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); - r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); - normalize_qt(r_rot); - - r_phase = PSYS_FRAND(p + 20); +#if 0 /* deprecated code */ if(part->from==PART_FROM_PARTICLE){ float speed; ParticleSimulationData tsim= {0}; @@ -1733,79 +1633,93 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */ } else{ - /* get precise emitter matrix if particle is born */ - if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) { - /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ - BKE_animsys_evaluate_animdata(&sim->ob->id, sim->ob->adt, pa->time, ADT_RECALC_ANIM); - where_is_object_time(sim->scene, sim->ob, pa->time); - } +#endif + /* get precise emitter matrix if particle is born */ + if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) { + /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ + BKE_animsys_evaluate_animdata(&sim->ob->id, sim->ob->adt, pa->time, ADT_RECALC_ANIM); + where_is_object_time(sim->scene, sim->ob, pa->time); + } - /* get birth location from object */ - if(part->tanfac!=0.0) - psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); - else - psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); + /* get birth location from object */ + if(part->tanfac != 0.f) + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + else + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); - /* get possible textural influence */ - psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL|MAP_PA_LIFE); + /* get possible textural influence */ + psys_get_texture(sim, pa, &ptex, PAMAP_IVEL|PAMAP_LIFE, cfra); - //if(vg_vel && pa->num != -1) - // ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel); - - /* particles live in global space so */ - /* let's convert: */ - /* -location */ - mul_m4_v3(ob->obmat,loc); + /* particles live in global space so */ + /* let's convert: */ + /* -location */ + mul_m4_v3(ob->obmat, loc); - /* -normal */ - mul_mat3_m4_v3(ob->obmat,nor); - normalize_v3(nor); - - /* -tangent */ - if(part->tanfac!=0.0){ - //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; - float phase=0.0f; - mul_v3_fl(vtan,-(float)cos(M_PI*(part->tanphase+phase))); - fac=-(float)sin(M_PI*(part->tanphase+phase)); - VECADDFAC(vtan,vtan,utan,fac); - - mul_mat3_m4_v3(ob->obmat,vtan); - - VECCOPY(utan,nor); - mul_v3_fl(utan,dot_v3v3(vtan,nor)); - VECSUB(vtan,vtan,utan); + /* -normal */ + mul_mat3_m4_v3(ob->obmat, nor); + normalize_v3(nor); + + /* -tangent */ + if(part->tanfac!=0.0){ + //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + float phase=0.0f; + mul_v3_fl(vtan,-(float)cos(M_PI*(part->tanphase+phase))); + fac=-(float)sin(M_PI*(part->tanphase+phase)); + VECADDFAC(vtan,vtan,utan,fac); + + mul_mat3_m4_v3(ob->obmat,vtan); + + VECCOPY(utan,nor); + mul_v3_fl(utan,dot_v3v3(vtan,nor)); + VECSUB(vtan,vtan,utan); - normalize_v3(vtan); - } + normalize_v3(vtan); + } - /* -velocity */ - if(part->randfac!=0.0){ - mul_mat3_m4_v3(ob->obmat,r_vel); - normalize_v3(r_vel); - } + /* -velocity */ + if(part->randfac!=0.0){ + r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); + r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); + r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); - /* -angular velocity */ - if(part->avemode==PART_AVE_RAND){ - mul_mat3_m4_v3(ob->obmat,r_ave); - normalize_v3(r_ave); - } + mul_mat3_m4_v3(ob->obmat, r_vel); + normalize_v3(r_vel); + } + + /* -angular velocity */ + if(part->avemode==PART_AVE_RAND){ + r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); + r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); + r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); + + mul_mat3_m4_v3(ob->obmat,r_ave); + normalize_v3(r_ave); + } - /* -rotation */ - if(part->randrotfac != 0.0f){ - mat4_to_quat(rot,ob->obmat); - mul_qt_qtqt(r_rot,r_rot,rot); - } + /* -rotation */ + if(part->randrotfac != 0.0f){ + r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); + r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); + r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); + r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); + normalize_qt(r_rot); + + mat4_to_quat(rot,ob->obmat); + mul_qt_qtqt(r_rot,r_rot,rot); + } +#if 0 } +#endif if(part->phystype==PART_PHYS_BOIDS && pa->boid) { BoidParticle *bpa = pa->boid; float dvec[3], q[4], mat[3][3]; - VECCOPY(pa->state.co,loc); + copy_v3_v3(pa->state.co,loc); /* boids don't get any initial velocity */ - pa->state.vel[0]=pa->state.vel[1]=pa->state.vel[2]=0.0f; + zero_v3(pa->state.vel); /* boids store direction in ave */ if(fabs(nor[2])==1.0f) { @@ -1844,66 +1758,56 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* -velocity from: */ /* *reactions */ - if(dtime>0.0f){ - VECSUB(vel,pa->state.vel,pa->prev_state.vel); + if(dtime > 0.f){ + sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel); } /* *emitter velocity */ - if(dtime!=0.0 && part->obfac!=0.0){ - VECSUB(vel,loc,pa->state.co); - mul_v3_fl(vel,part->obfac/dtime); + if(dtime != 0.f && part->obfac != 0.f){ + sub_v3_v3v3(vel, loc, pa->state.co); + mul_v3_fl(vel, part->obfac/dtime); } /* *emitter normal */ - if(part->normfac!=0.0) - VECADDFAC(vel,vel,nor,part->normfac); + if(part->normfac != 0.f) + madd_v3_v3fl(vel, nor, part->normfac); /* *emitter tangent */ - if(sim->psmd && part->tanfac!=0.0) - VECADDFAC(vel,vel,vtan,part->tanfac); - //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f)); + if(sim->psmd && part->tanfac != 0.f) + madd_v3_v3fl(vel, vtan, part->tanfac); /* *emitter object orientation */ - if(part->ob_vel[0]!=0.0) { + if(part->ob_vel[0] != 0.f) { normalize_v3_v3(vec, ob->obmat[0]); - VECADDFAC(vel, vel, vec, part->ob_vel[0]); + madd_v3_v3fl(vel, vec, part->ob_vel[0]); } - if(part->ob_vel[1]!=0.0) { + if(part->ob_vel[1] != 0.f) { normalize_v3_v3(vec, ob->obmat[1]); - VECADDFAC(vel, vel, vec, part->ob_vel[1]); + madd_v3_v3fl(vel, vec, part->ob_vel[1]); } - if(part->ob_vel[2]!=0.0) { + if(part->ob_vel[2] != 0.f) { normalize_v3_v3(vec, ob->obmat[2]); - VECADDFAC(vel, vel, vec, part->ob_vel[2]); + madd_v3_v3fl(vel, vec, part->ob_vel[2]); } /* *texture */ /* TODO */ /* *random */ - if(part->randfac!=0.0) - VECADDFAC(vel,vel,r_vel,part->randfac); + if(part->randfac != 0.f) + madd_v3_v3fl(vel, r_vel, part->randfac); /* *particle */ - if(part->partfac!=0.0) - VECADDFAC(vel,vel,p_vel,part->partfac); - - //icu=find_ipocurve(psys->part->ipo,PART_EMIT_VEL); - //if(icu){ - // calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta))); - // ptex.ivel*=icu->curval; - //} - - mul_v3_fl(vel,ptex.ivel); + if(part->partfac != 0.f) + madd_v3_v3fl(vel, p_vel, part->partfac); - VECCOPY(pa->state.vel,vel); + mul_v3_v3fl(pa->state.vel, vel, ptex.ivel); /* -location from emitter */ - VECCOPY(pa->state.co,loc); + copy_v3_v3(pa->state.co,loc); /* -rotation */ - pa->state.rot[0]=1.0; - pa->state.rot[1]=pa->state.rot[2]=pa->state.rot[3]=0.0; + unit_qt(pa->state.rot); if(part->rotmode){ /* create vector into which rotation is aligned */ @@ -1939,7 +1843,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* rotation phase */ phasefac = part->phasefac; if(part->randphasefac != 0.0f) - phasefac += part->randphasefac * r_phase; + phasefac += part->randphasefac * PSYS_FRAND(p + 20); axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI); /* combine base rotation & phase */ @@ -1948,25 +1852,19 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* -angular velocity */ - pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0; + zero_v3(pa->state.ave); if(part->avemode){ switch(part->avemode){ case PART_AVE_SPIN: - VECCOPY(pa->state.ave,vel); + copy_v3_v3(pa->state.ave, vel); break; case PART_AVE_RAND: - VECCOPY(pa->state.ave,r_ave); + copy_v3_v3(pa->state.ave, r_ave); break; } normalize_v3(pa->state.ave); mul_v3_fl(pa->state.ave,part->avefac); - - //icu=find_ipocurve(psys->part->ipo,PART_EMIT_AVE); - //if(icu){ - // calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta))); - // mul_v3_fl(pa->state.ave,icu->curval); - //} } } @@ -1975,7 +1873,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, pa->lifetime = 100.0f; } else{ - pa->lifetime = part->lifetime*ptex.life; + pa->lifetime = part->lifetime * ptex.life; if(part->randlife != 0.0) pa->lifetime *= 1.0f - part->randlife * PSYS_FRAND(p + 21); @@ -2002,15 +1900,9 @@ static void reset_all_particles(ParticleSimulationData *sim, float dtime, float { ParticleData *pa; int p, totpart=sim->psys->totpart; - //float *vg_vel=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_VEL); - //float *vg_tan=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_TAN); - //float *vg_rot=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_ROT); for(p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++) reset_particle(sim, pa, dtime, cfra); - - //if(vg_vel) - // MEM_freeN(vg_vel); } /************************************************/ /* Particle targets */ @@ -2542,6 +2434,9 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra float force[3],impulse[3],dx[4][3],dv[4][3],oldpos[3]; float dtime=dfra*timestep, time, pa_mass=part->mass, fac /*, fra=sim->psys->cfra*/; int i, steps=1; + ParticleTexture ptex; + + psys_get_texture(sim, pa, &ptex, PAMAP_PHYSICS, cfra); /* maintain angular velocity */ VECCOPY(pa->state.ave,pa->prev_state.ave); @@ -2575,6 +2470,9 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra if(part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR) pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse); + mul_v3_fl(force, ptex.field); + mul_v3_fl(impulse, ptex.field); + /* calculate air-particle interaction */ if(part->dragfac!=0.0f){ fac=-part->dragfac*pa->size*pa->size*len_v3(states[i].vel); @@ -2595,10 +2493,7 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra if(psys_uses_gravity(sim) /* normal gravity is too strong for hair so it's disabled by default */ && (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) { - float gravity[3]; - VECCOPY(gravity, sim->scene->physics_settings.gravity); - mul_v3_fl(gravity, part->effector_weights->global_gravity); - VECADD(force,force,gravity); + madd_v3_v3fl(force, sim->scene->physics_settings.gravity, part->effector_weights->global_gravity * ptex.gravity); } /* calculate next state */ @@ -2679,8 +2574,8 @@ static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra } /* damp affects final velocity */ - if(part->dampfac!=0.0) - mul_v3_fl(pa->state.vel,1.0f-part->dampfac); + if(part->dampfac != 0.f) + mul_v3_fl(pa->state.vel, 1.f - part->dampfac * ptex.damp); VECCOPY(pa->state.ave, states->ave); @@ -3471,6 +3366,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) ParticleSystem *psys = sim->psys; ParticleSettings *part=psys->part; BoidBrainData bbd; + ParticleTexture ptex; PARTICLE_P; float timestep; /* frame & time changes */ @@ -3485,7 +3381,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) if(dfra<0.0){ LOOP_EXISTING_PARTICLES { - pa->size = part->size; + psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); + pa->size = part->size*ptex.size; if(part->randsize > 0.0) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); @@ -3538,7 +3435,9 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) LOOP_SHOWN_PARTICLES { copy_particle_key(&pa->prev_state,&pa->state,1); - pa->size = part->size; + psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); + + pa->size = part->size*ptex.size; if(part->randsize > 0.0) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); @@ -3685,6 +3584,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra) { ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; + ParticleTexture ptex; PARTICLE_P; float disp, dietime; @@ -3695,7 +3595,8 @@ static void cached_step(ParticleSimulationData *sim, float cfra) disp= (float)psys_get_current_display_percentage(psys)/100.0f; LOOP_PARTICLES { - pa->size = part->size; + psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); + pa->size = part->size*ptex.size; if(part->randsize > 0.0) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 57c629d5544..0129e709505 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -51,6 +51,7 @@ #include "DNA_brush_types.h" #include "DNA_node_types.h" #include "DNA_color_types.h" +#include "DNA_particle_types.h" #include "IMB_imbuf.h" @@ -671,7 +672,9 @@ void default_mtex(MTex *mtex) mtex->lifefac= 1.0f; mtex->sizefac= 1.0f; mtex->ivelfac= 1.0f; - mtex->pvelfac= 1.0f; + mtex->dampfac= 1.0f; + mtex->gravityfac= 1.0f; + mtex->fieldfac= 1.0f; mtex->normapspace= MTEX_NSPACE_TANGENT; } @@ -1167,6 +1170,42 @@ void set_current_brush_texture(Brush *br, Tex *newtex) } } +Tex *give_current_particle_texture(ParticleSettings *part) +{ + MTex *mtex= NULL; + Tex *tex= NULL; + + if(!part) return 0; + + mtex= part->mtex[(int)(part->texact)]; + if(mtex) tex= mtex->tex; + + return tex; +} + +void set_current_particle_texture(ParticleSettings *part, Tex *newtex) +{ + int act= part->texact; + + if(part->mtex[act] && part->mtex[act]->tex) + id_us_min(&part->mtex[act]->tex->id); + + if(newtex) { + if(!part->mtex[act]) { + part->mtex[act]= add_mtex(); + part->mtex[act]->texco= TEXCO_ORCO; + part->mtex[act]->blendtype= MTEX_MUL; + } + + part->mtex[act]->tex= newtex; + id_us_plus(&newtex->id); + } + else if(part->mtex[act]) { + MEM_freeN(part->mtex[act]); + part->mtex[act]= NULL; + } +} + /* ------------------------------------------------------------------------- */ EnvMap *BKE_add_envmap(void) |