diff options
Diffstat (limited to 'source/blender/blenkernel/intern/particle.c')
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 708 |
1 files changed, 546 insertions, 162 deletions
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index e837c57400a..0b331fb88d2 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -21,12 +21,18 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <math.h> #include <stdlib.h> #include <string.h> #include "MEM_guardedalloc.h" +#include "DNA_defaults.h" + +#include "DNA_cloth_types.h" #include "DNA_collection_types.h" #include "DNA_curve_types.h" #include "DNA_dynamicpaint_types.h" @@ -50,6 +56,7 @@ #include "BLT_translation.h" +#include "BKE_anim_data.h" #include "BKE_anim_path.h" #include "BKE_boids.h" #include "BKE_cloth.h" @@ -76,12 +83,24 @@ #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_query.h" -#include "RE_render_ext.h" +#include "RE_texture.h" + +#include "BLO_read_write.h" #include "particle_private.h" static void fluid_free_settings(SPHFluidSettings *fluid); +static void particle_settings_init(ID *id) +{ + ParticleSettings *particle_settings = (ParticleSettings *)id; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(particle_settings, id)); + + MEMCPY_STRUCT_AFTER(particle_settings, DNA_struct_default_get(ParticleSettings), id); + + particle_settings->effector_weights = BKE_effector_add_weights(NULL); +} + static void particle_settings_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, @@ -194,6 +213,279 @@ static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void write_boid_state(BlendWriter *writer, BoidState *state) +{ + BLO_write_struct(writer, BoidState, state); + + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: + BLO_write_struct(writer, BoidRuleGoalAvoid, rule); + break; + case eBoidRuleType_AvoidCollision: + BLO_write_struct(writer, BoidRuleAvoidCollision, rule); + break; + case eBoidRuleType_FollowLeader: + BLO_write_struct(writer, BoidRuleFollowLeader, rule); + break; + case eBoidRuleType_AverageSpeed: + BLO_write_struct(writer, BoidRuleAverageSpeed, rule); + break; + case eBoidRuleType_Fight: + BLO_write_struct(writer, BoidRuleFight, rule); + break; + default: + BLO_write_struct(writer, BoidRule, rule); + break; + } + } +#if 0 + BoidCondition *cond = state->conditions.first; + for (; cond; cond = cond->next) { + BLO_write_struct(writer, BoidCondition, cond); + } +#endif +} + +static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + ParticleSettings *part = (ParticleSettings *)id; + if (part->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id); + BKE_id_blend_write(writer, &part->id); + + if (part->adt) { + BKE_animdata_blend_write(writer, part->adt); + } + BLO_write_struct(writer, PartDeflect, part->pd); + BLO_write_struct(writer, PartDeflect, part->pd2); + BLO_write_struct(writer, EffectorWeights, part->effector_weights); + + if (part->clumpcurve) { + BKE_curvemapping_blend_write(writer, part->clumpcurve); + } + if (part->roughcurve) { + BKE_curvemapping_blend_write(writer, part->roughcurve); + } + if (part->twistcurve) { + BKE_curvemapping_blend_write(writer, part->twistcurve); + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ + if (dw->ob != NULL) { + dw->index = 0; + if (part->instance_collection) { /* can be NULL if lining fails or set to None */ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) { + if (object == dw->ob) { + break; + } + dw->index++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } + } + BLO_write_struct(writer, ParticleDupliWeight, dw); + } + + if (part->boids && part->phystype == PART_PHYS_BOIDS) { + BLO_write_struct(writer, BoidSettings, part->boids); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + write_boid_state(writer, state); + } + } + if (part->fluid && part->phystype == PART_PHYS_FLUID) { + BLO_write_struct(writer, SPHFluidSettings, part->fluid); + } + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_write_struct(writer, MTex, part->mtex[a]); + } + } + } +} + +void BKE_particle_partdeflect_blend_read_data(BlendDataReader *UNUSED(reader), PartDeflect *pd) +{ + if (pd) { + pd->rng = NULL; + } +} + +static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_data_address(reader, &part->adt); + BLO_read_data_address(reader, &part->pd); + BLO_read_data_address(reader, &part->pd2); + + BKE_animdata_blend_read_data(reader, part->adt); + BKE_particle_partdeflect_blend_read_data(reader, part->pd); + BKE_particle_partdeflect_blend_read_data(reader, part->pd2); + + BLO_read_data_address(reader, &part->clumpcurve); + if (part->clumpcurve) { + BKE_curvemapping_blend_read(reader, part->clumpcurve); + } + BLO_read_data_address(reader, &part->roughcurve); + if (part->roughcurve) { + BKE_curvemapping_blend_read(reader, part->roughcurve); + } + BLO_read_data_address(reader, &part->twistcurve); + if (part->twistcurve) { + BKE_curvemapping_blend_read(reader, part->twistcurve); + } + + BLO_read_data_address(reader, &part->effector_weights); + if (!part->effector_weights) { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + BLO_read_list(reader, &part->instance_weights); + + BLO_read_data_address(reader, &part->boids); + BLO_read_data_address(reader, &part->fluid); + + if (part->boids) { + BLO_read_list(reader, &part->boids->states); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + BLO_read_list(reader, &state->rules); + BLO_read_list(reader, &state->conditions); + BLO_read_list(reader, &state->actions); + } + } + for (int a = 0; a < MAX_MTEX; a++) { + BLO_read_data_address(reader, &part->mtex[a]); + } + + /* Protect against integer overflow vulnerability. */ + CLAMP(part->trail_count, 1, 100000); +} + +void BKE_particle_partdeflect_blend_read_lib(BlendLibReader *reader, ID *id, PartDeflect *pd) +{ + if (pd && pd->tex) { + BLO_read_id_address(reader, id->lib, &pd->tex); + } + if (pd && pd->f_source) { + BLO_read_id_address(reader, id->lib, &pd->f_source); + } +} + +static void particle_settings_blend_read_lib(BlendLibReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_id_address( + reader, part->id.lib, &part->ipo); /* XXX deprecated - old animation system */ + + BLO_read_id_address(reader, part->id.lib, &part->instance_object); + BLO_read_id_address(reader, part->id.lib, &part->instance_collection); + BLO_read_id_address(reader, part->id.lib, &part->force_group); + BLO_read_id_address(reader, part->id.lib, &part->bb_ob); + BLO_read_id_address(reader, part->id.lib, &part->collision_group); + + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd); + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd2); + + if (part->effector_weights) { + BLO_read_id_address(reader, part->id.lib, &part->effector_weights->group); + } + else { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + if (part->instance_weights.first && part->instance_collection) { + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_read_id_address(reader, part->id.lib, &dw->ob); + } + } + else { + BLI_listbase_clear(&part->instance_weights); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: { + BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid *)rule; + BLO_read_id_address(reader, part->id.lib, &brga->ob); + break; + } + case eBoidRuleType_FollowLeader: { + BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader *)rule; + BLO_read_id_address(reader, part->id.lib, &brfl->ob); + break; + } + } + } + } + } + + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = part->mtex[a]; + if (mtex) { + BLO_read_id_address(reader, part->id.lib, &mtex->tex); + BLO_read_id_address(reader, part->id.lib, &mtex->object); + } + } +} + +static void particle_settings_blend_read_expand(BlendExpander *expander, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_expand(expander, part->instance_object); + BLO_expand(expander, part->instance_collection); + BLO_expand(expander, part->force_group); + BLO_expand(expander, part->bb_ob); + BLO_expand(expander, part->collision_group); + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_expand(expander, part->mtex[a]->tex); + BLO_expand(expander, part->mtex[a]->object); + } + } + + if (part->effector_weights) { + BLO_expand(expander, part->effector_weights->group); + } + + if (part->pd) { + BLO_expand(expander, part->pd->tex); + BLO_expand(expander, part->pd->f_source); + } + if (part->pd2) { + BLO_expand(expander, part->pd2->tex); + BLO_expand(expander, part->pd2->f_source); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + if (rule->type == eBoidRuleType_Avoid) { + BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; + BLO_expand(expander, gabr->ob); + } + else if (rule->type == eBoidRuleType_FollowLeader) { + BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; + BLO_expand(expander, flbr->ob); + } + } + } + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_expand(expander, dw->ob); + } +} + IDTypeInfo IDType_ID_PA = { .id_code = ID_PA, .id_filter = FILTER_ID_PA, @@ -204,24 +496,26 @@ IDTypeInfo IDType_ID_PA = { .translation_context = BLT_I18NCONTEXT_ID_PARTICLESETTINGS, .flags = 0, - .init_data = NULL, + .init_data = particle_settings_init, .copy_data = particle_settings_copy_data, .free_data = particle_settings_free_data, .make_local = NULL, .foreach_id = particle_settings_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = particle_settings_blend_write, + .blend_read_data = particle_settings_blend_read_data, + .blend_read_lib = particle_settings_blend_read_lib, + .blend_read_expand = particle_settings_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT]; float PSYS_FRAND_BASE[PSYS_FRAND_COUNT]; -void psys_init_rng(void) +void BKE_particle_init_rng(void) { RNG *rng = BLI_rng_new_srandom(5831); /* arbitrary */ for (int i = 0; i < PSYS_FRAND_COUNT; i++) { @@ -905,7 +1199,7 @@ static float interpolate_particle_value( value += w[3] * v4; } - CLAMP(value, 0.f, 1.f); + CLAMP(value, 0.0f, 1.0f); return value; } @@ -1134,7 +1428,7 @@ static void do_particle_interpolation(ParticleSystem *psys, PTCacheEditPoint *point = pind->epoint; ParticleKey keys[4]; int point_vel = (point && point->keys->vel); - float real_t, dfra, keytime, invdt = 1.f; + float real_t, dfra, keytime, invdt = 1.0f; /* billboards wont fill in all of these, so start cleared */ memset(keys, 0, sizeof(keys)); @@ -1304,7 +1598,7 @@ static void do_particle_interpolation(ParticleSystem *psys, /* Convert velocity to time-step size. */ if (pind->keyed || pind->cache || point_vel) { - invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f); + invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.0f); mul_v3_fl(keys[1].vel, invdt); mul_v3_fl(keys[2].vel, invdt); interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime); @@ -1323,7 +1617,7 @@ static void do_particle_interpolation(ParticleSystem *psys, /* the velocity needs to be converted back from cubic interpolation */ if (pind->keyed || pind->cache || point_vel) { - mul_v3_fl(result->vel, 1.f / invdt); + mul_v3_fl(result->vel, 1.0f / invdt); } } @@ -2188,7 +2482,7 @@ int do_guides(Depsgraph *depsgraph, pd->kink_freq, pd->kink_shape, pd->kink_amp, - 0.f, + 0.0f, pd->kink, pd->kink_axis, 0, @@ -2538,12 +2832,12 @@ static void psys_thread_create_path(ParticleTask *task, if (ctx->between) { ParticleData *pa = psys->particles + cpa->pa[0]; int w, needupdate; - float foffset, wsum = 0.f; + float foffset, wsum = 0.0f; float co[3]; float p_min = part->parting_min; float p_max = part->parting_max; /* Virtual parents don't work nicely with parting. */ - float p_fac = part->parents > 0.f ? 0.f : part->parting_fac; + float p_fac = part->parents > 0.0f ? 0.0f : part->parting_fac; if (ctx->editupdate) { needupdate = 0; @@ -2571,15 +2865,15 @@ static void psys_thread_create_path(ParticleTask *task, } else { key[w] = pcache[0]; - weight[w] = 0.f; + weight[w] = 0.0f; } } /* modify weights to create parting */ - if (p_fac > 0.f) { + if (p_fac > 0.0f) { const ParticleCacheKey *key_0_last = pcache_key_segment_endpoint_safe(key[0]); for (w = 0; w < 4; w++) { - if (w && (weight[w] > 0.f)) { + if (w && (weight[w] > 0.0f)) { const ParticleCacheKey *key_w_last = pcache_key_segment_endpoint_safe(key[w]); float d; if (part->flag & PART_CHILD_LONG_HAIR) { @@ -2588,7 +2882,7 @@ static void psys_thread_create_path(ParticleTask *task, float d1 = len_v3v3(key[0]->co, key[w]->co); float d2 = len_v3v3(key_0_last->co, key_w_last->co); - d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f; + d = d1 > 0.0f ? d2 / d1 - 1.0f : 10000.0f; } else { float v1[3], v2[3]; @@ -2604,13 +2898,13 @@ static void psys_thread_create_path(ParticleTask *task, d = (d - p_min) / (p_max - p_min); } else { - d = (d - p_min) <= 0.f ? 0.f : 1.f; + d = (d - p_min) <= 0.0f ? 0.0f : 1.0f; } - CLAMP(d, 0.f, 1.f); + CLAMP(d, 0.0f, 1.0f); - if (d > 0.f) { - weight[w] *= (1.f - d); + if (d > 0.0f) { + weight[w] *= (1.0f - d); } } wsum += weight[w]; @@ -2668,7 +2962,7 @@ static void psys_thread_create_path(ParticleTask *task, cpa_num = (ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? pa->num : pa->num_dmcache; - /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */ + /* XXX hack to avoid messed up particle num and subsequent crash (T40733) */ if (cpa_num > ctx->sim.psmd->mesh_final->totface) { cpa_num = 0; } @@ -3047,7 +3341,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re LOOP_PARTICLES { if (!psys->totchild) { - psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f); + psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.0f); pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p)); if (vg_length) { pa_length *= psys_particle_value_from_verts(psmd->mesh_final, part->from, pa, vg_length); @@ -3704,19 +3998,25 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob if (psys->part->type == PART_FLUID_FLIP) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP; } - if (psys->part->type == PART_FLUID_SPRAY || psys->part->type == PART_FLUID_SPRAYFOAM || - psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_SPRAY, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_SPRAY; } - if (psys->part->type == PART_FLUID_FOAM || psys->part->type == PART_FLUID_SPRAYFOAM || - psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_FOAM, + PART_FLUID_SPRAYFOAM, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FOAM; } - if (psys->part->type == PART_FLUID_BUBBLE || psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_BUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_BUBBLE; } if (psys->part->type == PART_FLUID_TRACER) { @@ -3724,9 +4024,11 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } /* Disable combined export if combined particle system was deleted. */ - if (psys->part->type == PART_FLUID_SPRAYFOAM || psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->sndparticle_combined_export = SNDPARTICLE_COMBINED_EXPORT_OFF; } } @@ -3769,98 +4071,11 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); } -static void default_particle_settings(ParticleSettings *part) -{ - part->type = PART_EMITTER; - part->distr = PART_DISTR_JIT; - part->draw_as = PART_DRAW_REND; - part->ren_as = PART_DRAW_HALO; - part->bb_uv_split = 1; - part->flag = PART_EDISTR | PART_TRAND | PART_HIDE_ADVANCED_HAIR; - - part->sta = 1.0; - part->end = 200.0; - part->lifetime = 50.0; - part->jitfac = 1.0; - part->totpart = 1000; - part->grid_res = 10; - part->timetweak = 1.0; - part->courant_target = 0.2; - - part->integrator = PART_INT_MIDPOINT; - part->phystype = PART_PHYS_NEWTON; - part->hair_step = 5; - part->keys_step = 5; - part->draw_step = 2; - part->ren_step = 3; - part->adapt_angle = 5; - part->adapt_pix = 3; - part->kink_axis = 2; - part->kink_amp_clump = 1.f; - part->kink_extra_steps = 4; - part->clump_noise_size = 1.0f; - part->reactevent = PART_EVENT_DEATH; - part->disp = 100; - part->from = PART_FROM_FACE; - - part->normfac = 1.0f; - - part->mass = 1.0; - part->size = 0.05; - part->childsize = 1.0; - - part->rotmode = PART_ROT_VEL; - part->avemode = PART_AVE_VELOCITY; - - part->child_nbr = 10; - part->ren_child_nbr = 100; - part->childrad = 0.2f; - part->childflat = 0.0f; - part->clumppow = 0.0f; - part->kink_amp = 0.2f; - part->kink_freq = 2.0; - - part->rough1_size = 1.0; - part->rough2_size = 1.0; - part->rough_end_shape = 1.0; - - part->clength = 1.0f; - part->clength_thres = 0.0f; - - part->draw = 0; - part->draw_line[0] = 0.5; - part->path_start = 0.0f; - part->path_end = 1.0f; - - part->bb_size[0] = part->bb_size[1] = 1.0f; - - part->keyed_loops = 1; - - part->color_vec_max = 1.f; - part->draw_col = PART_DRAW_COL_MAT; - - if (!part->effector_weights) { - part->effector_weights = BKE_effector_add_weights(NULL); - } - - part->omat = 1; - part->use_modifier_stack = false; - part->draw_size = 0.1f; - - part->shape_flag = PART_SHAPE_CLOSE_TIP; - part->shape = 0.0f; - part->rad_root = 1.0f; - part->rad_tip = 0.0f; - part->rad_scale = 0.01f; -} - ParticleSettings *BKE_particlesettings_add(Main *bmain, const char *name) { ParticleSettings *part; - part = BKE_libblock_alloc(bmain, ID_PA, name, 0); - - default_particle_settings(part); + part = BKE_id_new(bmain, ID_PA, name); return part; } @@ -3907,13 +4122,6 @@ void BKE_particlesettings_twist_curve_init(ParticleSettings *part) part->twistcurve = cumap; } -ParticleSettings *BKE_particlesettings_copy(Main *bmain, const ParticleSettings *part) -{ - ParticleSettings *part_copy; - BKE_id_copy(bmain, &part->id, (ID **)&part_copy); - return part_copy; -} - /************************************************/ /* Textures */ /************************************************/ @@ -3997,8 +4205,9 @@ static int get_particle_uv(Mesh *mesh, #define CLAMP_WARP_PARTICLE_TEXTURE_POS(type, pvalue) \ if (event & type) { \ - if (pvalue < 0.0f) \ + if (pvalue < 0.0f) { \ pvalue = 1.0f + pvalue; \ + } \ CLAMP(pvalue, 0.0f, 1.0f); \ } \ (void)0 @@ -4073,9 +4282,9 @@ static void get_cpa_texture(Mesh *mesh, 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; + texvec[0] = 2.0f * (cfra - par->time) / (par->dietime - par->time) - 1.0f; + texvec[1] = 0.0f; + texvec[2] = 0.0f; break; } @@ -4183,14 +4392,15 @@ void psys_get_texture( break; case TEXCO_PARTICLE: /* texture coordinates in range [-1, 1] */ - texvec[0] = 2.f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.f; + texvec[0] = 2.0f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.0f; if (sim->psys->totpart > 0) { - texvec[1] = 2.f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - 1.f; + texvec[1] = 2.0f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - + 1.0f; } else { texvec[1] = 0.0f; } - texvec[2] = 0.f; + texvec[2] = 0.0f; break; } @@ -4276,7 +4486,7 @@ float psys_get_child_size(ParticleSystem *psys, float *UNUSED(pa_time)) { ParticleSettings *part = psys->part; - float size; // time XXX + float size; /* time XXX */ if (part->childtype == PART_CHILD_FACES) { int w = 0; @@ -4465,7 +4675,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL); } - if (totchild && part->childtype == PART_CHILD_FACES) { + if (part->childtype == PART_CHILD_FACES) { /* part->parents could still be 0 so we can't test with totparent */ between = 1; } @@ -4735,8 +4945,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta else { float dfra, frs_sec = sim->scene->r.frs_sec; /* let's interpolate to try to be as accurate as possible */ - if (pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) { - if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) { + if (pa->state.time + 2.0f >= state->time && pa->prev_state.time - 2.0f <= state->time) { + if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.0f) { /* prev_state is wrong so let's not use it, * this can happen at frames 1, 0 or particle birth. */ dfra = state->time - pa->state.time; @@ -4763,13 +4973,13 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ - mul_v3_fl(state->vel, 1.f / (dfra * timestep)); + mul_v3_fl(state->vel, 1.0f / (dfra * timestep)); interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime); interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime); } } - else if (pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) { + else if (pa->state.time + 1.0f >= state->time && pa->state.time - 1.0f <= state->time) { /* linear interpolation using only pa->state */ dfra = state->time - pa->state.time; @@ -4803,7 +5013,6 @@ void psys_get_dupli_texture(ParticleSystem *psys, float orco[3]) { MFace *mface; - MTFace *mtface; float loc[3]; int num; @@ -4815,21 +5024,25 @@ void psys_get_dupli_texture(ParticleSystem *psys, * For now just include this workaround as an alternative to crashing, * but longer term meta-balls should behave in a more manageable way, see: T46622. */ - uv[0] = uv[1] = 0.f; + uv[0] = uv[1] = 0.0f; /* Grid distribution doesn't support UV or emit from vertex mode */ bool is_grid = (part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT); if (cpa) { if ((part->childtype == PART_CHILD_FACES) && (psmd->mesh_final != NULL)) { - CustomData *mtf_data = &psmd->mesh_final->fdata; - const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE); - mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx); - - if (mtface && !is_grid) { - mface = CustomData_get(&psmd->mesh_final->fdata, cpa->num, CD_MFACE); - mtface += cpa->num; - psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv); + if (!is_grid) { + CustomData *mtf_data = &psmd->mesh_final->fdata; + const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE); + + if (uv_idx >= 0) { + MTFace *mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx); + if (mtface != NULL) { + mface = CustomData_get(&psmd->mesh_final->fdata, cpa->num, CD_MFACE); + mtface += cpa->num; + psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv); + } + } } psys_particle_on_emitter(psmd, @@ -4850,10 +5063,6 @@ void psys_get_dupli_texture(ParticleSystem *psys, } if ((part->from == PART_FROM_FACE) && (psmd->mesh_final != NULL) && !is_grid) { - CustomData *mtf_data = &psmd->mesh_final->fdata; - const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE); - mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx); - num = pa->num_dmcache; if (num == DMCACHE_NOTFOUND) { @@ -4866,10 +5075,16 @@ void psys_get_dupli_texture(ParticleSystem *psys, num = DMCACHE_NOTFOUND; } - if (mtface && !ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) { - mface = CustomData_get(&psmd->mesh_final->fdata, num, CD_MFACE); - mtface += num; - psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv); + if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) { + CustomData *mtf_data = &psmd->mesh_final->fdata; + const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE); + + if (uv_idx >= 0) { + MTFace *mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx); + mface = CustomData_get(&psmd->mesh_final->fdata, num, CD_MFACE); + mtface += num; + psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv); + } } } @@ -5025,3 +5240,172 @@ void BKE_particle_batch_cache_free(ParticleSystem *psys) BKE_particle_batch_cache_free_cb(psys); } } + +void BKE_particle_system_blend_write(BlendWriter *writer, ListBase *particles) +{ + LISTBASE_FOREACH (ParticleSystem *, psys, particles) { + BLO_write_struct(writer, ParticleSystem, psys); + + if (psys->particles) { + BLO_write_struct_array(writer, ParticleData, psys->totpart, psys->particles); + + if (psys->particles->hair) { + ParticleData *pa = psys->particles; + + for (int a = 0; a < psys->totpart; a++, pa++) { + BLO_write_struct_array(writer, HairKey, pa->totkey, pa->hair); + } + } + + if (psys->particles->boid && (psys->part->phystype == PART_PHYS_BOIDS)) { + BLO_write_struct_array(writer, BoidParticle, psys->totpart, psys->particles->boid); + } + + if (psys->part->fluid && (psys->part->phystype == PART_PHYS_FLUID) && + (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS)) { + BLO_write_struct_array( + writer, ParticleSpring, psys->tot_fluidsprings, psys->fluid_springs); + } + } + LISTBASE_FOREACH (ParticleTarget *, pt, &psys->targets) { + BLO_write_struct(writer, ParticleTarget, pt); + } + + if (psys->child) { + BLO_write_struct_array(writer, ChildParticle, psys->totchild, psys->child); + } + + if (psys->clmd) { + BLO_write_struct(writer, ClothModifierData, psys->clmd); + BLO_write_struct(writer, ClothSimSettings, psys->clmd->sim_parms); + BLO_write_struct(writer, ClothCollSettings, psys->clmd->coll_parms); + } + + BKE_ptcache_blend_write(writer, &psys->ptcaches); + } +} + +void BKE_particle_system_blend_read_data(BlendDataReader *reader, ListBase *particles) +{ + ParticleData *pa; + int a; + + LISTBASE_FOREACH (ParticleSystem *, psys, particles) { + BLO_read_data_address(reader, &psys->particles); + + if (psys->particles && psys->particles->hair) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + BLO_read_data_address(reader, &pa->hair); + } + } + + if (psys->particles && psys->particles->keys) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + pa->keys = NULL; + pa->totkey = 0; + } + + psys->flag &= ~PSYS_KEYED; + } + + if (psys->particles && psys->particles->boid) { + pa = psys->particles; + BLO_read_data_address(reader, &pa->boid); + + /* This is purely runtime data, but still can be an issue if left dangling. */ + pa->boid->ground = NULL; + + for (a = 1, pa++; a < psys->totpart; a++, pa++) { + pa->boid = (pa - 1)->boid + 1; + pa->boid->ground = NULL; + } + } + else if (psys->particles) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + pa->boid = NULL; + } + } + + BLO_read_data_address(reader, &psys->fluid_springs); + + BLO_read_data_address(reader, &psys->child); + psys->effectors = NULL; + + BLO_read_list(reader, &psys->targets); + + psys->edit = NULL; + psys->free_edit = NULL; + psys->pathcache = NULL; + psys->childcache = NULL; + BLI_listbase_clear(&psys->pathcachebufs); + BLI_listbase_clear(&psys->childcachebufs); + psys->pdd = NULL; + + if (psys->clmd) { + BLO_read_data_address(reader, &psys->clmd); + psys->clmd->clothObject = NULL; + psys->clmd->hairdata = NULL; + + BLO_read_data_address(reader, &psys->clmd->sim_parms); + BLO_read_data_address(reader, &psys->clmd->coll_parms); + + if (psys->clmd->sim_parms) { + psys->clmd->sim_parms->effector_weights = NULL; + if (psys->clmd->sim_parms->presets > 10) { + psys->clmd->sim_parms->presets = 0; + } + } + + psys->hair_in_mesh = psys->hair_out_mesh = NULL; + psys->clmd->solver_result = NULL; + } + + BKE_ptcache_blend_read_data(reader, &psys->ptcaches, &psys->pointcache, 0); + if (psys->clmd) { + psys->clmd->point_cache = psys->pointcache; + } + + psys->tree = NULL; + psys->bvhtree = NULL; + + psys->orig_psys = NULL; + psys->batch_cache = NULL; + } +} + +void BKE_particle_system_blend_read_lib(BlendLibReader *reader, + Object *ob, + ID *id, + ListBase *particles) +{ + LISTBASE_FOREACH_MUTABLE (ParticleSystem *, psys, particles) { + + BLO_read_id_address(reader, id->lib, &psys->part); + if (psys->part) { + LISTBASE_FOREACH (ParticleTarget *, pt, &psys->targets) { + BLO_read_id_address(reader, id->lib, &pt->ob); + } + + BLO_read_id_address(reader, id->lib, &psys->parent); + BLO_read_id_address(reader, id->lib, &psys->target_ob); + + if (psys->clmd) { + /* XXX - from reading existing code this seems correct but intended usage of + * pointcache /w cloth should be added in 'ParticleSystem' - campbell */ + psys->clmd->point_cache = psys->pointcache; + psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = NULL; + BLO_read_id_address(reader, id->lib, &psys->clmd->coll_parms->group); + psys->clmd->modifier.error = NULL; + } + } + else { + /* particle modifier must be removed before particle system */ + ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + BLI_remlink(&ob->modifiers, psmd); + BKE_modifier_free((ModifierData *)psmd); + + BLI_remlink(particles, psys); + MEM_freeN(psys); + } + } +} |