Changeset View
Standalone View
source/blender/blenkernel/intern/particle_system.c
| Show First 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | |||||
| #ifdef WITH_MOD_FLUID | #ifdef WITH_MOD_FLUID | ||||
| #include "DNA_object_fluidsim_types.h" | #include "DNA_object_fluidsim_types.h" | ||||
| #include "LBM_fluidsim.h" | #include "LBM_fluidsim.h" | ||||
| #include <zlib.h> | #include <zlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #endif // WITH_MOD_FLUID | #endif // WITH_MOD_FLUID | ||||
| /* manta sim particle import */ | |||||
| #ifdef WITH_MANTA | |||||
| # include "DNA_smoke_types.h" | |||||
| # include "manta_fluid_API.h" | |||||
| #endif // WITH_MANTA | |||||
| static ThreadRWMutex psys_bvhtree_rwlock = BLI_RWLOCK_INITIALIZER; | static ThreadRWMutex psys_bvhtree_rwlock = BLI_RWLOCK_INITIALIZER; | ||||
| /************************************************/ | /************************************************/ | ||||
| /* Reacting to system events */ | /* Reacting to system events */ | ||||
| /************************************************/ | /************************************************/ | ||||
| static int particles_are_dynamic(ParticleSystem *psys) | static int particles_are_dynamic(ParticleSystem *psys) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 409 Lines • ▼ Show 20 Lines | if (ctx->roughcurve != NULL) { | ||||
| curvemapping_free(ctx->roughcurve); | curvemapping_free(ctx->roughcurve); | ||||
| } | } | ||||
| if (ctx->twistcurve != NULL) { | if (ctx->twistcurve != NULL) { | ||||
| curvemapping_free(ctx->twistcurve); | curvemapping_free(ctx->twistcurve); | ||||
| } | } | ||||
| } | } | ||||
| static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p) | static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p) | ||||
| { | { | ||||
| ParticleSystem *psys = sim->psys; | ParticleSystem *psys = sim->psys; | ||||
| ParticleSettings *part = psys->part; | ParticleSettings *part = psys->part; | ||||
| ParticleTexture ptex; | ParticleTexture ptex; | ||||
| psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); | psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); | ||||
| switch (part->type) { | if (part->type & PART_EMITTER) { | ||||
| case PART_EMITTER: | |||||
| if (ptex.exist < psys_frand(psys, p + 125)) { | if (ptex.exist < psys_frand(psys, p + 125)) { | ||||
| pa->flag |= PARS_UNEXIST; | pa->flag |= PARS_UNEXIST; | ||||
| } | } | ||||
| pa->time = part->sta + (part->end - part->sta)*ptex.time; | pa->time = part->sta + (part->end - part->sta)*ptex.time; | ||||
| break; | } | ||||
| case PART_HAIR: | if (part->type & PART_HAIR) { | ||||
| if (ptex.exist < psys_frand(psys, p + 125)) { | if (ptex.exist < psys_frand(psys, p + 125)) { | ||||
| pa->flag |= PARS_UNEXIST; | pa->flag |= PARS_UNEXIST; | ||||
| } | } | ||||
| pa->time = 0.f; | pa->time = 0.f; | ||||
| break; | |||||
| case PART_FLUID: | |||||
| break; | |||||
| } | } | ||||
sergey: I don't understand it. Particle system can not be emitter and hair at the same time and type… | |||||
Done Inline ActionsI agree. This doesn't make any sense. Changed it. sebbas: I agree. This doesn't make any sense. Changed it. | |||||
Done Inline ActionsWhy not to keep it as a switch statement? sergey: Why not to keep it as a switch statement? | |||||
Done Inline ActionsYes, let's do that. I don't really have an opinion on this. The whole change probably just came from me not liking case statement so much. sebbas: Yes, let's do that. I don't really have an opinion on this. The whole change probably just came… | |||||
| } | } | ||||
| /* set particle parameters that don't change during particle's life */ | /* set particle parameters that don't change during particle's life */ | ||||
| void initialize_particle(ParticleSimulationData *sim, ParticleData *pa) | void initialize_particle(ParticleSimulationData *sim, ParticleData *pa) | ||||
| { | { | ||||
| ParticleSettings *part = sim->psys->part; | ParticleSettings *part = sim->psys->part; | ||||
| float birth_time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart; | float birth_time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart; | ||||
| ▲ Show 20 Lines • Show All 3,241 Lines • ▼ Show 20 Lines | LOOP_PARTICLES { | ||||
| if (psys_frand(psys, p) > disp) | if (psys_frand(psys, p) > disp) | ||||
| pa->flag |= PARS_NO_DISP; | pa->flag |= PARS_NO_DISP; | ||||
| else | else | ||||
| pa->flag &= ~PARS_NO_DISP; | pa->flag &= ~PARS_NO_DISP; | ||||
| } | } | ||||
| } | } | ||||
| static void particles_manta_step( | |||||
| ParticleSimulationData *sim, int UNUSED(cfra), const bool use_render_params) | |||||
| { | |||||
| ParticleSystem *psys = sim->psys; | |||||
| if (psys->particles) { | |||||
| MEM_freeN(psys->particles); | |||||
| psys->particles = 0; | |||||
| psys->totpart = 0; | |||||
| } | |||||
| if (psys->part) { | |||||
| psys->part->totpart = 0; | |||||
| psys->part->sta = 0; | |||||
| psys->part->lifetime = 0; | |||||
| } | |||||
| /* manta sim particle import handling, actual loading of particles from file happens in FLUID helper. Here just pointer exchange */ | |||||
| #ifdef WITH_MANTA | |||||
| { | |||||
| Object *ob = sim->ob; | |||||
| SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke); | |||||
| if (smd && smd->domain && smd->domain->fluid) { | |||||
| SmokeDomainSettings *sds= smd->domain; | |||||
| ParticleSettings *part = psys->part; | |||||
| ParticleData *pa=NULL; | |||||
| int p, totpart, tottypepart = 0; | |||||
| int flagActivePart, activeParts = 0; | |||||
| float posX, posY, posZ, velX, velY, velZ; | |||||
| float resX, resY, resZ; | |||||
| int upres[3] = {1}; | |||||
| char debugStrBuffer[256]; | |||||
| // Helper for scaling | |||||
| float min[3], max[3], size[3], cell_size_scaled[3], max_size; | |||||
| // Sanity check: parts also enabled in fluid domain? | |||||
| if ((part->type & PART_MANTA_FLIP && (sds->particle_type & FLUID_DOMAIN_PARTICLE_FLIP)==0) || | |||||
| (part->type & PART_MANTA_SPRAY && (sds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY)==0) || | |||||
| (part->type & PART_MANTA_BUBBLE && (sds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE)==0) || | |||||
| (part->type & PART_MANTA_FOAM && (sds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM)==0) || | |||||
| (part->type & PART_MANTA_TRACER && (sds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)==0) ) | |||||
| { | |||||
| BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "particles_manta_step::error - found particle system that is not enabled in fluid domain\n"); | |||||
| return; | |||||
| } | |||||
| // Count particle amount. tottypepart only important for snd particles | |||||
| if (part->type & PART_MANTA_FLIP) { | |||||
| tottypepart = totpart = liquid_get_num_flip_particles(sds->fluid); | |||||
| } | |||||
| if (part->type & (PART_MANTA_SPRAY | PART_MANTA_BUBBLE | PART_MANTA_FOAM | PART_MANTA_TRACER)) { | |||||
| totpart = liquid_get_num_snd_particles(sds->fluid); | |||||
| // tottypepart is the amount of particles of a snd particle type | |||||
| for (p=0; p<totpart; p++) { | |||||
| flagActivePart = liquid_get_snd_particle_flag_at(sds->fluid, p); | |||||
| if ((part->type & PART_MANTA_SPRAY) && (flagActivePart & PSPRAY)) tottypepart++; | |||||
| if ((part->type & PART_MANTA_BUBBLE) && (flagActivePart & PBUBBLE)) tottypepart++; | |||||
| if ((part->type & PART_MANTA_FOAM) && (flagActivePart & PFOAM)) tottypepart++; | |||||
| if ((part->type & PART_MANTA_TRACER) && (flagActivePart & PTRACER)) tottypepart++; | |||||
| } | |||||
| } | |||||
| // Sanity check: no particle files present yet | |||||
| if (!tottypepart) | |||||
| return; | |||||
| tottypepart = (use_render_params) ? tottypepart : (part->disp*tottypepart) / 100; | |||||
| part->totpart = tottypepart; | |||||
| part->sta = part->end = 1.0f; | |||||
| part->lifetime = sim->scene->r.efra + 1; | |||||
| /* allocate particles */ | |||||
| realloc_particles(sim, part->totpart); | |||||
| for (p=0, pa=psys->particles; p<totpart; p++) { | |||||
| if (part->type & PART_MANTA_FLIP) { | |||||
| flagActivePart = liquid_get_flip_particle_flag_at(sds->fluid, p); | |||||
| // // Upres FLIP have custom (upscaled) res values | |||||
| // TODO (sebbas): Future option might load highres FLIP particle system | |||||
| // if (sds->flags & FLUID_DOMAIN_USE_MESH) { | |||||
| // resX = (float) fluid_get_mesh_res_x(sds->fluid); | |||||
| // resY = (float) fluid_get_mesh_res_y(sds->fluid); | |||||
| // resZ = (float) fluid_get_mesh_res_z(sds->fluid); | |||||
| // | |||||
| // upres[0] = upres[1] = upres[2] = fluid_get_mesh_upres(sds->fluid); | |||||
| // } | |||||
| // else | |||||
| { | |||||
| resX = (float) fluid_get_res_x(sds->fluid); | |||||
| resY = (float) fluid_get_res_y(sds->fluid); | |||||
| resZ = (float) fluid_get_res_z(sds->fluid); | |||||
| upres[0] = upres[1] = upres[2] = 1; | |||||
| } | |||||
| } | |||||
| else if (part->type & (PART_MANTA_SPRAY | PART_MANTA_BUBBLE | PART_MANTA_FOAM | PART_MANTA_TRACER)) { | |||||
| flagActivePart = liquid_get_snd_particle_flag_at(sds->fluid, p); | |||||
| resX = (float) liquid_get_particle_res_x(sds->fluid); | |||||
| resY = (float) liquid_get_particle_res_y(sds->fluid); | |||||
| resZ = (float) liquid_get_particle_res_z(sds->fluid); | |||||
| upres[0] = upres[1] = upres[2] = liquid_get_particle_upres(sds->fluid); | |||||
| } | |||||
| else { | |||||
| BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "particles_manta_step::error - unknown particle system type\n"); | |||||
| return; | |||||
| } | |||||
| // printf("part->type: %d, flagActivePart: %d\n", part->type, flagActivePart); | |||||
| // check if type of particle type matches current particle system type (only important for snd particles) | |||||
| // if ((part->type & PART_MANTA_SPRAY) && (flagActivePart & PSPRAY)==0) continue; | |||||
| // if ((part->type & PART_MANTA_BUBBLE) && (flagActivePart & PBUBBLE)==0) continue; | |||||
| // if ((part->type & PART_MANTA_FOAM) && (flagActivePart & PFOAM)==0) continue; | |||||
| // if ((part->type & PART_MANTA_TRACER) && (flagActivePart & PTRACER)==0) continue; | |||||
| if ((flagActivePart & PSPRAY) && (part->type & PART_MANTA_SPRAY)==0) continue; | |||||
| if ((flagActivePart & PBUBBLE) && (part->type & PART_MANTA_BUBBLE)==0) continue; | |||||
| if ((flagActivePart & PFOAM) && (part->type & PART_MANTA_FOAM)==0) continue; | |||||
| if ((flagActivePart & PTRACER) && (part->type & PART_MANTA_TRACER)==0) continue; | |||||
| // printf("system type is %d and particle type is %d\n", part->type, flagActivePart); | |||||
| if (part->type & PART_MANTA_FLIP) { | |||||
| posX = liquid_get_flip_particle_position_x_at(sds->fluid, p); | |||||
| posY = liquid_get_flip_particle_position_y_at(sds->fluid, p); | |||||
| posZ = liquid_get_flip_particle_position_z_at(sds->fluid, p); | |||||
| velX = liquid_get_flip_particle_velocity_x_at(sds->fluid, p); | |||||
| velY = liquid_get_flip_particle_velocity_y_at(sds->fluid, p); | |||||
| velZ = liquid_get_flip_particle_velocity_z_at(sds->fluid, p); | |||||
| } | |||||
| else if (part->type & (PART_MANTA_SPRAY | PART_MANTA_BUBBLE | PART_MANTA_FOAM | PART_MANTA_TRACER)) { | |||||
| posX = liquid_get_snd_particle_position_x_at(sds->fluid, p); | |||||
| posY = liquid_get_snd_particle_position_y_at(sds->fluid, p); | |||||
| posZ = liquid_get_snd_particle_position_z_at(sds->fluid, p); | |||||
| velX = liquid_get_snd_particle_velocity_x_at(sds->fluid, p); | |||||
| velY = liquid_get_snd_particle_velocity_y_at(sds->fluid, p); | |||||
| velZ = liquid_get_snd_particle_velocity_z_at(sds->fluid, p); | |||||
| } | |||||
| // Only show active particles, i.e. filter out dead particles that just Mantaflow needs | |||||
| if ((flagActivePart & PDELETE)==0) { // mantaflow convention: PDELETE == inactive particle | |||||
| activeParts++; | |||||
| // Use particle system settings for particle size | |||||
| pa->size = part->size; | |||||
| if (part->randsize > 0.0f) | |||||
| pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1); | |||||
| // Get size (dimension) but considering scaling | |||||
| copy_v3_v3(cell_size_scaled, sds->cell_size); | |||||
| mul_v3_v3(cell_size_scaled, ob->size); | |||||
| VECMADD(min, sds->p0, cell_size_scaled, sds->res_min); | |||||
| VECMADD(max, sds->p0, cell_size_scaled, sds->res_max); | |||||
| sub_v3_v3v3(size, max, min); | |||||
| // Biggest dimension will be used for upscaling | |||||
| max_size = MAX3(size[0] / (float) upres[0], size[1] / (float) upres[1], size[2] / (float) upres[2]); | |||||
| // set particle position | |||||
| pa->state.co[0] = posX; | |||||
| pa->state.co[1] = posY; | |||||
| pa->state.co[2] = posZ; | |||||
| // normalize to unit cube around 0 | |||||
| pa->state.co[0] -= resX * 0.5f; | |||||
| pa->state.co[1] -= resY * 0.5f; | |||||
| pa->state.co[2] -= resZ * 0.5f; | |||||
| mul_v3_fl(pa->state.co, sds->dx); | |||||
| // match domain dimension / size | |||||
| pa->state.co[0] *= max_size / fabsf(ob->size[0]); | |||||
| pa->state.co[1] *= max_size / fabsf(ob->size[1]); | |||||
| pa->state.co[2] *= max_size / fabsf(ob->size[2]); | |||||
| // match domain scale | |||||
| mul_m4_v3(ob->obmat, pa->state.co); | |||||
| // printf("pa->state.co[0]: %f, pa->state.co[1]: %f, pa->state.co[2]: %f\n", pa->state.co[0], pa->state.co[1], pa->state.co[2]); | |||||
| // set particle velocity | |||||
| pa->state.vel[0] = velX; | |||||
| pa->state.vel[1] = velY; | |||||
| pa->state.vel[2] = velZ; | |||||
| mul_v3_fl(pa->state.vel, sds->dx); | |||||
| // printf("pa->state.vel[0]: %f, pa->state.vel[1]: %f, pa->state.vel[2]: %f\n", pa->state.vel[0], pa->state.vel[1], pa->state.vel[2]); | |||||
| // set default angular velocity and particle rotation | |||||
| zero_v3(pa->state.ave); | |||||
| unit_qt(pa->state.rot); | |||||
| pa->time = 1.f; | |||||
| pa->dietime = sim->scene->r.efra + 1; | |||||
| pa->lifetime = sim->scene->r.efra; | |||||
| pa->alive = PARS_ALIVE; | |||||
| } | |||||
| // Increase particle setting here. totpart may be larger (snd parts) | |||||
| pa++; | |||||
| } | |||||
| // printf("active parts: %d\n", activeParts); | |||||
| totpart = psys->totpart = part->totpart = activeParts; | |||||
| } // manta sim particles done | |||||
| } | |||||
| #else | |||||
| UNUSED_VARS(use_render_params); | |||||
| #endif // WITH_MANTA | |||||
| } | |||||
| static void particles_fluid_step( | static void particles_fluid_step( | ||||
| ParticleSimulationData *sim, int UNUSED(cfra), const bool use_render_params) | ParticleSimulationData *sim, int UNUSED(cfra), const bool use_render_params) | ||||
| { | { | ||||
| ParticleSystem *psys = sim->psys; | ParticleSystem *psys = sim->psys; | ||||
| if (psys->particles) { | if (psys->particles) { | ||||
| MEM_freeN(psys->particles); | MEM_freeN(psys->particles); | ||||
| psys->particles = 0; | psys->particles = 0; | ||||
| psys->totpart = 0; | psys->totpart = 0; | ||||
| } | } | ||||
| /* fluid sim particle import handling, actual loading of particles from file */ | /* fluid sim particle import handling, actual loading of particles from file */ | ||||
| #ifdef WITH_MOD_FLUID | #ifdef WITH_MOD_FLUID | ||||
| { | { | ||||
Not Done Inline ActionsShouldn't this be using seed from settings? But it also seems you've got way bigger design violation here. srand()modifies global state, so you can not use it from a function which runs in threads. You should be using reentrant variant of rand() instead. sergey: Shouldn't this be using seed from settings?
But it also seems you've got way bigger design… | |||||
Done Inline ActionsI see. I figured that this is how other particle steps set the seed: c54fd66c0a17 Would this work? sebbas: I see. I figured that this is how other particle steps set the seed: c54fd66c0a17
Would this… | |||||
Done Inline Actions
That would only mean that the other step functions are wrong. As for c54fd66c0a17: sim->rng the idea is correct. Just watch out for where rng is being allocated. Code is a bit hairy, so not sure if particles_manta_step ever called from dynamics_step. Also keep in mind that to access random numbers you are to use BLI_rng_get() (and not rand()). So depending on where the random values are accessed from you might need to go deeper. sergey: > I figured that this is how other particle steps set the seed
That would only mean that the… | |||||
Done Inline ActionsOkay, good to know. I am using now BLI_rng_get_double() to get the random value. sebbas: Okay, good to know. I am using now `BLI_rng_get_double()` to get the random value. | |||||
| FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim); | FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim); | ||||
| if ( fluidmd && fluidmd->fss) { | if ( fluidmd && fluidmd->fss) { | ||||
| FluidsimSettings *fss= fluidmd->fss; | FluidsimSettings *fss= fluidmd->fss; | ||||
| ParticleSettings *part = psys->part; | ParticleSettings *part = psys->part; | ||||
| ParticleData *pa=NULL; | ParticleData *pa=NULL; | ||||
| char filename[256]; | char filename[256]; | ||||
| char debugStrBuffer[256]; | char debugStrBuffer[256]; | ||||
| int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading | int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading | ||||
| int p, j, totpart; | int p, j, totpart; | ||||
| int readMask, activeParts = 0, fileParts = 0; | int readMask, activeParts = 0, fileParts = 0; | ||||
| gzFile gzf; | gzFile gzf; | ||||
| // XXX if (ob==G.obedit) // off... | // XXX if (ob==G.obedit) // off... | ||||
| // return; | // return; | ||||
| // ok, start loading | // ok, start loading | ||||
| BLI_join_dirfile(filename, sizeof(filename), fss->surfdataPath, OB_FLUIDSIM_SURF_PARTICLES_FNAME); | BLI_join_dirfile(filename, sizeof(filename), fss->surfdataPath, OB_FLUIDSIM_SURF_PARTICLES_FNAME); | ||||
| BLI_path_abs(filename, modifier_path_relbase_from_global(sim->ob)); | BLI_path_abs(filename, modifier_path_relbase_from_global(sim->ob)); | ||||
| BLI_path_frame(filename, curFrame, 0); // fixed #frame-no | BLI_path_frame(filename, curFrame, 0); // fixed #frame-no | ||||
Done Inline ActionsMerge pos{X,Y,Z} into a float[3] and use vector math. Sane for velocity. sergey: Merge `pos{X,Y,Z}` into a `float[3]` and use vector math.
Sane for velocity. | |||||
| gzf = BLI_gzopen(filename, "rb"); | gzf = BLI_gzopen(filename, "rb"); | ||||
| if (!gzf) { | if (!gzf) { | ||||
| BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer),"readFsPartData::error - Unable to open file for reading '%s'\n", filename); | BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer),"readFsPartData::error - Unable to open file for reading '%s'\n", filename); | ||||
| // XXX bad level call elbeemDebugOut(debugStrBuffer); | // XXX bad level call elbeemDebugOut(debugStrBuffer); | ||||
| return; | return; | ||||
| } | } | ||||
| gzread(gzf, &totpart, sizeof(totpart)); | gzread(gzf, &totpart, sizeof(totpart)); | ||||
| totpart = (use_render_params) ? totpart:(part->disp*totpart) / 100; | totpart = (use_render_params) ? totpart:(part->disp*totpart) / 100; | ||||
| part->totpart= totpart; | part->totpart= totpart; | ||||
| part->sta=part->end = 1.0f; | part->sta=part->end = 1.0f; | ||||
| part->lifetime = sim->scene->r.efra + 1; | part->lifetime = sim->scene->r.efra + 1; | ||||
| /* allocate particles */ | /* allocate particles */ | ||||
| realloc_particles(sim, part->totpart); | realloc_particles(sim, part->totpart); | ||||
| // set up reading mask | // set up reading mask | ||||
| readMask = fss->typeFlags; | readMask = fss->typeFlags; | ||||
| for (p=0, pa=psys->particles; p<totpart; p++, pa++) { | for (p=0, pa=psys->particles; p<totpart; p++, pa++) { | ||||
| int ptype=0; | int ptype=0; | ||||
Done Inline ActionsDead code is discouraged. sergey: Dead code is discouraged. | |||||
| gzread(gzf, &ptype, sizeof( ptype )); | gzread(gzf, &ptype, sizeof( ptype )); | ||||
| if (ptype & readMask) { | if (ptype & readMask) { | ||||
| activeParts++; | activeParts++; | ||||
| gzread(gzf, &(pa->size), sizeof(float)); | gzread(gzf, &(pa->size), sizeof(float)); | ||||
| pa->size /= 10.0f; | pa->size /= 10.0f; | ||||
| ▲ Show 20 Lines • Show All 372 Lines • ▼ Show 20 Lines | void particle_system_update(struct Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params) | ||||
| psys->flag &= ~PSYS_OB_ANIM_RESTORE; | psys->flag &= ~PSYS_OB_ANIM_RESTORE; | ||||
| if (psys->recalc & PSYS_RECALC_RESET) | if (psys->recalc & PSYS_RECALC_RESET) | ||||
| psys->totunexist = 0; | psys->totunexist = 0; | ||||
| /* setup necessary physics type dependent additional data if it doesn't yet exist */ | /* setup necessary physics type dependent additional data if it doesn't yet exist */ | ||||
| psys_prepare_physics(&sim); | psys_prepare_physics(&sim); | ||||
| switch (part->type) { | if (part->type & PART_HAIR) | ||||
| case PART_HAIR: | |||||
| { | { | ||||
| /* nothing to do so bail out early */ | /* nothing to do so bail out early */ | ||||
| if (psys->totpart == 0 && part->totpart == 0) { | if (psys->totpart == 0 && part->totpart == 0) { | ||||
| psys_free_path_cache(psys, NULL); | psys_free_path_cache(psys, NULL); | ||||
| free_hair(ob, psys, 0); | free_hair(ob, psys, 0); | ||||
| psys->flag |= PSYS_HAIR_DONE; | psys->flag |= PSYS_HAIR_DONE; | ||||
| } | } | ||||
| /* (re-)create hair */ | /* (re-)create hair */ | ||||
| else if (hair_needs_recalc(psys)) { | else if (hair_needs_recalc(psys)) { | ||||
| float hcfra=0.0f; | float hcfra=0.0f; | ||||
| int i, recalc = psys->recalc; | int i, recalc = psys->recalc; | ||||
| free_hair(ob, psys, 0); | free_hair(ob, psys, 0); | ||||
| if (psys_orig->edit && psys_orig->free_edit) { | if (psys_orig->edit && psys_orig->free_edit) { | ||||
| psys_orig->free_edit(psys_orig->edit); | psys_orig->free_edit(psys_orig->edit); | ||||
| psys_orig->edit = NULL; | psys_orig->edit = NULL; | ||||
| psys_orig->free_edit = NULL; | psys_orig->free_edit = NULL; | ||||
| } | } | ||||
| /* first step is negative so particles get killed and reset */ | /* first step is negative so particles get killed and reset */ | ||||
| psys->cfra= 1.0f; | psys->cfra= 1.0f; | ||||
| for (i=0; i<=part->hair_step; i++) { | for (i=0; i<=part->hair_step; i++) { | ||||
| hcfra=100.0f*(float)i/(float)psys->part->hair_step; | hcfra=100.0f*(float)i/(float)psys->part->hair_step; | ||||
| if ((part->flag & PART_HAIR_REGROW)==0) | if ((part->flag & PART_HAIR_REGROW)==0) | ||||
| BKE_animsys_evaluate_animdata(depsgraph, scene, &part->id, part->adt, hcfra, ADT_RECALC_ANIM); | BKE_animsys_evaluate_animdata(depsgraph, scene, &part->id, part->adt, hcfra, ADT_RECALC_ANIM); | ||||
| system_step(&sim, hcfra, use_render_params); | system_step(&sim, hcfra, use_render_params); | ||||
| psys->cfra = hcfra; | psys->cfra = hcfra; | ||||
| psys->recalc = 0; | psys->recalc = 0; | ||||
| save_hair(&sim, hcfra); | save_hair(&sim, hcfra); | ||||
| } | } | ||||
| psys->flag |= PSYS_HAIR_DONE; | psys->flag |= PSYS_HAIR_DONE; | ||||
| psys->recalc = recalc; | psys->recalc = recalc; | ||||
| } | } | ||||
| else if (psys->flag & PSYS_EDITED) | else if (psys->flag & PSYS_EDITED) | ||||
| psys->flag |= PSYS_HAIR_DONE; | psys->flag |= PSYS_HAIR_DONE; | ||||
| if (psys->flag & PSYS_HAIR_DONE) | if (psys->flag & PSYS_HAIR_DONE) | ||||
| hair_step(&sim, cfra, use_render_params); | hair_step(&sim, cfra, use_render_params); | ||||
| break; | |||||
| } | } | ||||
| case PART_FLUID: | else if (part->type & PART_FLUID) | ||||
| { | { | ||||
| particles_fluid_step(&sim, (int)cfra, use_render_params); | particles_fluid_step(&sim, (int)cfra, use_render_params); | ||||
| break; | |||||
| } | } | ||||
| default: | else if (part->type & (PART_MANTA_FLIP | PART_MANTA_BUBBLE | PART_MANTA_BUBBLE | PART_MANTA_FOAM | PART_MANTA_TRACER)) | ||||
| { | |||||
| particles_manta_step(&sim, (int)cfra, use_render_params); | |||||
| } | |||||
| else | |||||
| { | { | ||||
| switch (part->phystype) { | switch (part->phystype) { | ||||
| case PART_PHYS_NO: | case PART_PHYS_NO: | ||||
| case PART_PHYS_KEYED: | case PART_PHYS_KEYED: | ||||
| { | { | ||||
| PARTICLE_P; | PARTICLE_P; | ||||
| float disp = psys_get_current_display_percentage(psys, use_render_params); | float disp = psys_get_current_display_percentage(psys, use_render_params); | ||||
| bool free_unexisting = false; | bool free_unexisting = false; | ||||
| /* Particles without dynamics haven't been reset yet because they don't use pointcache */ | /* Particles without dynamics haven't been reset yet because they don't use pointcache */ | ||||
| if (psys->recalc & PSYS_RECALC_RESET) | if (psys->recalc & PSYS_RECALC_RESET) | ||||
| psys_reset(psys, PSYS_RESET_ALL); | psys_reset(psys, PSYS_RESET_ALL); | ||||
| if (emit_particles(&sim, NULL, cfra) || (psys->recalc & PSYS_RECALC_RESET)) { | if (emit_particles(&sim, NULL, cfra) || (psys->recalc & PSYS_RECALC_RESET)) { | ||||
| free_keyed_keys(psys); | free_keyed_keys(psys); | ||||
| distribute_particles(&sim, part->from); | distribute_particles(&sim, part->from); | ||||
| initialize_all_particles(&sim); | initialize_all_particles(&sim); | ||||
| free_unexisting = true; | free_unexisting = true; | ||||
| /* flag for possible explode modifiers after this system */ | /* flag for possible explode modifiers after this system */ | ||||
| sim.psmd->flag |= eParticleSystemFlag_Pars; | sim.psmd->flag |= eParticleSystemFlag_Pars; | ||||
| } | } | ||||
| LOOP_EXISTING_PARTICLES { | LOOP_EXISTING_PARTICLES { | ||||
| pa->size = part->size; | pa->size = part->size; | ||||
| if (part->randsize > 0.0f) | if (part->randsize > 0.0f) | ||||
| pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1); | pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1); | ||||
| reset_particle(&sim, pa, 0.0, cfra); | /* free unexisting after resetting particles */ | ||||
| if (free_unexisting) | |||||
| free_unexisting_particles(&sim); | |||||
| if (psys_frand(psys, p) > disp) | if (psys_frand(psys, p) > disp) | ||||
| pa->flag |= PARS_NO_DISP; | pa->flag |= PARS_NO_DISP; | ||||
| else | else | ||||
| pa->flag &= ~PARS_NO_DISP; | pa->flag &= ~PARS_NO_DISP; | ||||
| } | } | ||||
| /* free unexisting after resetting particles */ | /* free unexisting after reseting particles */ | ||||
| if (free_unexisting) | if (free_unexisting) | ||||
| free_unexisting_particles(&sim); | free_unexisting_particles(&sim); | ||||
| if (part->phystype == PART_PHYS_KEYED) { | if (part->phystype == PART_PHYS_KEYED) { | ||||
| psys_count_keyed_targets(&sim); | psys_count_keyed_targets(&sim); | ||||
| set_keyed_keys(&sim); | set_keyed_keys(&sim); | ||||
| psys_update_path_cache(&sim, (int)cfra, use_render_params); | psys_update_path_cache(&sim, (int)cfra, use_render_params); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| default: | default: | ||||
| { | { | ||||
| /* the main dynamic particle system step */ | /* the main dynamic particle system step */ | ||||
| system_step(&sim, cfra, use_render_params); | system_step(&sim, cfra, use_render_params); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| break; | |||||
| } | |||||
| } | } | ||||
| /* make sure emitter is left at correct time (particle emission can change this) */ | /* make sure emitter is left at correct time (particle emission can change this) */ | ||||
| if (psys->flag & PSYS_OB_ANIM_RESTORE) { | if (psys->flag & PSYS_OB_ANIM_RESTORE) { | ||||
| evaluate_emitter_anim(depsgraph, scene, ob, cfra); | evaluate_emitter_anim(depsgraph, scene, ob, cfra); | ||||
| psys->flag &= ~PSYS_OB_ANIM_RESTORE; | psys->flag &= ~PSYS_OB_ANIM_RESTORE; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines | |||||
I don't understand it. Particle system can not be emitter and hair at the same time and type can not be a bitfield.