int from, cfrom, distr;
+ struct ParticleData *tpars;
+
/* path caching */
int editupdate, between, steps;
int totchild, totparent;
void psys_enable_all(struct Object *ob);
int psys_ob_has_hair(struct Object *ob);
int psys_in_edit_mode(struct ParticleSystem *psys);
+int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
void psys_free_settings(struct ParticleSettings *part);
void free_child_path_cache(struct ParticleSystem *psys);
void psys_free_path_cache(struct ParticleSystem *psys);
-void psys_free_render_memory(struct Object *ob, struct ParticleSystem *psys);
void free_hair(struct ParticleSystem *psys);
void free_keyed_keys(struct ParticleSystem *psys);
void psys_free(struct Object * ob, struct ParticleSystem * psys);
+void psys_particles_to_render_backup(struct Object *ob, struct ParticleSystem *psys);
+void psys_render_backup_to_particles(struct Object *ob, struct ParticleSystem *psys);
+
void clear_particles_from_cache(struct Object *ob, struct ParticleSystem *psys, int cfra);
//void psys_remove_from_particle_list(struct Object *ob, short nbr, struct ParticleSystem *psys);
void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd);
void reset_particle(struct ParticleData *pa, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct Object *ob, float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot);
+void psys_calc_dmfaces(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);
int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node);
/* ParticleEffectorCache->type */
ParticleSystem *psys= ob->particlesystem.first;
for(; psys; psys=psys->next) {
- if(psys->flag & PSYS_ENABLED) {
+ if(psys_check_enabled(ob, psys)) {
ob->recalc |= OB_RECALC_DATA;
break;
}
else
return;
- if((psys->flag&PSYS_ENABLED)==0)
+ if(!psys_check_enabled(ob, psys))
return;
if(dm==0){
psys= ob->particlesystem.first;
while(psys) {
- if(psys->flag & PSYS_ENABLED) {
+ if(psys_check_enabled(ob, psys)) {
particle_system_update(ob, psys);
psys= psys->next;
}
#include "BKE_bad_level_calls.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
+#include "BKE_cdderivedmesh.h"
#include "blendef.h"
#include "RE_render_ext.h"
{
return ((G.f & G_PARTICLEEDIT) && psys==psys_get_current(OBACT) && psys->edit);
}
+int psys_check_enabled(Object *ob, ParticleSystem *psys)
+{
+ ParticleSystemModifierData *psmd;
+
+ if(!(psys->flag & PSYS_ENABLED))
+ return 0;
+
+ psmd= psys_get_modifier(ob, psys);
+ if(G.rendering) {
+ if(!psys->renderdata || !(psmd->modifier.mode & eModifierMode_Render))
+ return 0;
+ }
+ else if(!(psmd->modifier.mode & eModifierMode_Realtime))
+ return 0;
+
+ return 1;
+}
/************************************************/
/* Freeing stuff */
}
free_child_path_cache(psys);
}
-void psys_free_render_memory(Object *ob, ParticleSystem *psys)
-{
- ParticleSystemModifierData *psmd;
-
- /* this is a bad function, but saves a lot of memory rendering.
- * particles should really be generated on the fly with render
- * settings! */
- psys_free_path_cache(psys);
-
- if(psys->child){
- MEM_freeN(psys->child);
- psys->child=0;
- psys->totchild=0;
- }
-
- psmd= psys_get_modifier(ob, psys);
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
-
- psys->recalc |= PSYS_ALLOC|PSYS_DISTR;
- //DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
-}
/* free everything */
void psys_free(Object *ob, ParticleSystem * psys)
{
}
}
+/* these two functions move away particle data and bring it back after
+ * rendering, to make different render settings possible without
+ * removing the previous data. this should be solved properly once */
+
+typedef struct ParticleRenderDataup {
+ ChildParticle *child;
+ ParticleCacheKey **pathcache;
+ ParticleCacheKey **childcache;
+ int totchild, totcached, totchildcache;
+ DerivedMesh *dm;
+ int totdmvert, totdmedge, totdmface;
+} ParticleRenderDataup;
+
+void psys_particles_to_render_backup(Object *ob, ParticleSystem *psys)
+{
+ ParticleRenderDataup *data;
+ ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
+
+ if(!G.rendering)
+ return;
+
+ data= MEM_callocN(sizeof(ParticleRenderDataup), "ParticleRenderDataup");
+
+ data->child= psys->child;
+ data->totchild= psys->totchild;
+ data->pathcache= psys->pathcache;
+ data->totcached= psys->totcached;
+ data->childcache= psys->childcache;
+ data->totchildcache= psys->totchildcache;
+
+ if(psmd->dm)
+ data->dm= CDDM_copy(psmd->dm);
+ data->totdmvert= psmd->totdmvert;
+ data->totdmedge= psmd->totdmedge;
+ data->totdmface= psmd->totdmface;
+
+ psys->child= NULL;
+ psys->pathcache= NULL;
+ psys->childcache= NULL;
+ psys->totchild= psys->totcached= psys->totchildcache= 0;
+
+ psys->renderdata= data;
+}
+
+void psys_render_backup_to_particles(Object *ob, ParticleSystem *psys)
+{
+ ParticleRenderDataup *data;
+ ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
+
+ data= psys->renderdata;
+ if(!data)
+ return;
+
+ if(psmd->dm) {
+ psmd->dm->needsFree= 1;
+ psmd->dm->release(psmd->dm);
+ }
+
+ psys_free_path_cache(psys);
+
+ if(psys->child){
+ MEM_freeN(psys->child);
+ psys->child= 0;
+ psys->totchild= 0;
+ }
+
+ psys->child= data->child;
+ psys->totchild= data->totchild;
+ psys->pathcache= data->pathcache;
+ psys->totcached= data->totcached;
+ psys->childcache= data->childcache;
+ psys->totchildcache= data->totchildcache;
+
+ psmd->dm= data->dm;
+ psmd->totdmvert= data->totdmvert;
+ psmd->totdmedge= data->totdmedge;
+ psmd->totdmface= data->totdmface;
+ psmd->flag &= ~eParticleSystemFlag_psys_updated;
+
+ if(psys->part->from==PART_FROM_FACE && psmd->dm)
+ psys_calc_dmfaces(ob, psmd->dm, psys);
+
+ MEM_freeN(data);
+ psys->renderdata= NULL;
+}
+
/************************************************/
/* Interpolated Particles */
/************************************************/
/*---start figuring out what is actually wanted---*/
if(psys_in_edit_mode(psys))
- if(G.rendering==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0)
+ if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0)
totchild=0;
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
between=1;
}
- if(G.rendering)
+ if(psys->renderdata)
steps=(int)pow(2.0,(double)part->ren_step);
else{
totchild=(int)((float)totchild*(float)part->disp/100.0f);
if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0)
return;
- if(G.rendering)
+ if(psys->renderdata)
steps = (int)pow(2.0, (double)psys->part->ren_step);
else if(psys_in_edit_mode(psys)){
edit=psys->edit;
{
ParticleSettings *part=psys->part;
- if(G.rendering || (part->child_nbr && part->childtype))
+ if(psys->renderdata || (part->child_nbr && part->childtype))
return 100;
if(part->phystype==PART_PHYS_KEYED){
}
psys->particles=newpars;
- child_nbr= (G.rendering)? psys->part->ren_child_nbr: psys->part->child_nbr;
+ child_nbr= (psys->renderdata)? psys->part->ren_child_nbr: psys->part->child_nbr;
if(child_nbr && psys->part->childtype){
if(psys->child)
MEM_freeN(psys->child);
}
/* only run this if from == PART_FROM_FACE */
-static void psys_calc_dmfaces(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
+void psys_calc_dmfaces(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
{
/* use for building derived mesh face-origin info,
node - the allocated links - total derived mesh face count
ParticleThreadContext *ctx= thread->ctx;
Object *ob= ctx->ob;
DerivedMesh *dm= ctx->dm;
- ParticleData *tpars=0, *tpa;
+ ParticleData *tpa;
ParticleSettings *part= ctx->psys->part;
float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3];
float cur_d, min_d;
//pa->verts[1]=0;
//pa->verts[2]=0;
- tpa=tpars+ctx->index[p];
+ tpa=ctx->tpars+ctx->index[p];
pa->num=ctx->index[p];
pa->fuv[0]=tpa->fuv[0];
pa->fuv[1]=tpa->fuv[1];
Object *ob= ctx->ob;
ParticleSystem *psys= ctx->psys;
Object *tob;
- ParticleData *pa=0, *tpars;
+ ParticleData *pa=0, *tpars= 0;
ParticleSettings *part;
ParticleSystem *tpsys;
ParticleSeam *seams= 0;
}
else{
/* no need to figure out distribution */
- int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr;
+ int child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr;
for(i=0; i<child_nbr; i++){
for(p=0; p<psys->totpart; p++,cpa++){
ctx->cfrom= cfrom;
ctx->distr= distr;
ctx->dm= dm;
+ ctx->tpars= tpars;
seed= 31415926 + ctx->psys->seed;
initialize_particle(pa,p,ob,psys,psmd);
/* store the derived mesh face index for each particle */
- //if(psys->part->from==PART_FROM_FACE)
- // psys_calc_dmfaces(ob, psmd->dm, psys);
-
icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ);
if(icu){
float time=psys->part->sta, end=psys->part->end;
float *vg_tan=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN);
float *vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT);
- //if (psys->part->from == PART_FROM_FACE)
- // psys_calc_dmfaces(ob, psmd->dm, psys);
-
for(p=from, pa=psys->particles+from; p<totpart; p++, pa++)
reset_particle(pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot);
ParticleSettings *part=psys->part;
ParticleEditSettings *pset=&G.scene->toolsettings->particle;
int distr=0,alloc=0;
- int child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr;
+ int child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr;
if((psys->part->childtype && psys->totchild != psys->totpart*child_nbr) || psys->recalc&PSYS_ALLOC)
alloc=1;
{
ParticleSettings *part = psys->part;
- if(psys->recalc & PSYS_DISTR) {
+ if(psys->recalc & PSYS_DISTR)
/* need this for changing subsurf levels */
psys_calc_dmfaces(ob, psmd->dm, psys);
- }
-
+
if(psys->effectors.first)
psys_end_effectors(psys);
else
totpart = psys->part->totpart;
- child_nbr= (G.rendering)? part->ren_child_nbr: part->child_nbr;
+ child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr;
if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != psys->totpart*child_nbr))
alloc = 1;
}
/* ok now we're all set so let's go */
- if(psys->totpart) {
- //if(psys->part->from==PART_FROM_FACE) {
- // psys_calc_dmfaces(ob, psmd->dm, psys);
- //}
+ if(psys->totpart)
dynamics_step(ob,psys,psmd,cfra,vg_vel,vg_tan,vg_rot,vg_size);
- }
+
psys->recalc = 0;
psys->cfra=cfra;
ParticleSystemModifierData *psmd=0;
float cfra;
-
- if((psys->flag & PSYS_ENABLED)==0) return;
- psmd=psys_get_modifier(ob,psys);
+ if(!psys_check_enabled(ob, psys))
+ return;
cfra=bsystem_time(ob,(float)CFRA,0.0);
+ psmd= psys_get_modifier(ob, psys);
/* system was already updated from modifier stack */
- if(psmd->flag&eParticleSystemFlag_psys_updated){
+ if(psmd->flag&eParticleSystemFlag_psys_updated) {
psmd->flag &= ~eParticleSystemFlag_psys_updated;
/* make sure it really was updated to cfra */
if(psys->cfra==cfra)
return;
}
+ if(!psmd->dm)
+ return;
+
/* baked path softbody */
if(psys->part->type==PART_HAIR && psys->soft)
psys_to_softbody(ob, psys, 0);
oldnewmap_insert(fd->libmap, psys->part, psys->part, 0);
part->id.us--;
+ part->id.flag |= (ob->id.flag & LIB_NEEDLINK);
psys->totpart=0;
psys->flag=PSYS_ENABLED|PSYS_CURRENT;
/* if you change these remember to update array lengths to PSYS_TOT_VG! */
short vgroup[11], vg_neg, rt3[2];
+
+ /* temporary storage during render */
+ void *renderdata;
}ParticleSystem;
/* general particle maximums */
part=psys->part;
pars=psys->particles;
- if(part==NULL || pars==NULL || (psys->flag & PSYS_ENABLED)==0)
+ if(part==NULL || pars==NULL || !psys_check_enabled(ob, psys))
return 0;
-
+
if(part->draw_as==PART_DRAW_OB || part->draw_as==PART_DRAW_GR || part->draw_as==PART_DRAW_NOT)
return 1;
psys= psys->next;
render_new_particle_system(re, obr, psys);
- psys_free_render_memory(ob, psys);
}
else {
if ELEM(ob->type, OB_FONT, OB_CURVE)
/* so here we only check if the emitter should be rendered */
if(ob->particlesystem.first) {
show_emitter= 0;
- for(psys=ob->particlesystem.first; psys; psys=psys->next)
+ for(psys=ob->particlesystem.first; psys; psys=psys->next) {
show_emitter += psys->part->draw & PART_DRAW_EMITTER;
+ psys_particles_to_render_backup(ob, psys);
+ }
/* if no psys has "show emitter" selected don't render emitter */
if(show_emitter == 0)
for(psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) {
obr= RE_addRenderObject(re, ob, par, index, psysindex);
init_render_object_data(re, obr, only_verts);
+ psys_render_backup_to_particles(ob, psys);
/* only add instance for objects that have not been used for dupli */
if(!(ob->transflag & OB_RENDER_DUPLI))
else if(hoco[1] > bounds[3]*hoco[3]) clipflag |= 4;
else if(hoco[1]< bounds[2]*hoco[3]) clipflag |= 8;
+ clipflag |= testclip(hoco);
+
return clipflag;
}
emd->flag |= eExplodeFlag_CalcFaces;
}
-void modifiers_psysEnable(void *ob_v, void *md_v)
-{
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData*) md_v;
-
- if(psmd->modifier.mode & eModifierMode_Realtime) {
- psmd->psys->flag |= PSYS_ENABLED;
- }
- else {
- psmd->psys->flag &= ~PSYS_ENABLED;
- PE_free_particle_edit(psmd->psys);
- }
-}
-
static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
- if (md->type==eModifierType_ParticleSystem)
- uiButSetFunc(but, modifiers_psysEnable, ob, md);
if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
uiDefIconButBitI(block, TOG, eModifierMode_Editmode, B_MODIFIER_RECALC, VICON_EDIT, x+10+buttonWidth-20, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
}
break;
case B_PART_ENABLE:
if(psys) {
- ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
- if(psys->flag & PSYS_ENABLED) {
- psmd->modifier.mode |= eModifierMode_Realtime;
- }
- else {
- psmd->modifier.mode &= ~eModifierMode_Realtime;
- PE_free_particle_edit(psys);
- }
-
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSOBJECT, 0);
part=psys->part;
pars=psys->particles;
- if(part==0 || (psys->flag & PSYS_ENABLED)==0)
+ if(part==0 || !psys_check_enabled(ob, psys))
return;
if(pars==0) return;
static void object_flip_subdivison_particles(Object *ob, int *set, int level, int mode, int particles, int depth)
{
- void modifiers_psysEnable(void *ob_v, void *md_v);
ModifierData *md;
if(ob->type==OB_MESH) {
psmd->modifier.mode &= ~(mode);
else
psmd->modifier.mode |= (mode);
-
- modifiers_psysEnable(ob, md);
}
}
}
if((psys=BLI_findlink(&ob->particlesystem,act))) {
psys->flag |= PSYS_CURRENT;
- if(psys->flag & PSYS_ENABLED) {
+ if(psys_check_enabled(ob, psys)) {
if(G.f & G_PARTICLEEDIT && !psys->edit)
PE_create_particle_edit(ob, psys);
PE_recalc_world_cos(ob, psys);
psys->flag |= PSYS_CURRENT;
}
- if(psys && (psys->flag & PSYS_ENABLED) && ob == OBACT && (G.f & G_PARTICLEEDIT))
+ if(psys && psys_check_enabled(ob, psys) && ob == OBACT && (G.f & G_PARTICLEEDIT))
if(psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED)
if(psys->edit == NULL)
PE_create_particle_edit(ob, psys);
if((G.f & G_PARTICLEEDIT)==0){
if(psys && psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) {
- if(psys->flag & PSYS_ENABLED) {
+ if(psys_check_enabled(ob, psys)) {
if(psys->edit==0)
PE_create_particle_edit(ob, psys);
PE_recalc_world_cos(ob, psys);
if(k==0 && pset->flag & PE_LOCK_FIRST)
td->protectflag |= OB_LOCK_LOC;
+ td->ob = ob;
td->ext = tx;
td->tdi = NULL;
if(t->mode == TFM_BAKE_TIME) {