diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-02-15 14:33:44 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-02-15 14:33:44 +0300 |
commit | 2589f55a55bc9682111ab266bb89d8f08713f374 (patch) | |
tree | 6634689ec50057bc782a2c9430ae1059712b0254 /source/blender | |
parent | 9d2a699a90d5ce7b976e76f6e1b5c260306b5218 (diff) | |
parent | 6d4022f61980ba46efd391dcfe96dd88a8db8deb (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 72 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_child.c | 177 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/smoke.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/texture.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/particle_private.h | 18 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_vector.c | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 3 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_particle_types.h | 15 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_texture_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_particle.c | 57 |
14 files changed, 334 insertions, 29 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 9492f7e32fa..2db4126057a 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -115,6 +115,7 @@ typedef struct ParticleTexture { float damp, gravity, field; /* used in physics */ float length, clump, kink_freq, kink_amp, effector; /* used in path caching */ float rough1, rough2, roughe; /* used in path caching */ + float twist; /* used in path caching */ } ParticleTexture; typedef struct ParticleSeam { @@ -162,9 +163,11 @@ typedef struct ParticleThreadContext { float *vg_length, *vg_clump, *vg_kink; float *vg_rough1, *vg_rough2, *vg_roughe; float *vg_effector; + float *vg_twist; struct CurveMapping *clumpcurve; struct CurveMapping *roughcurve; + struct CurveMapping *twistcurve; } ParticleThreadContext; typedef struct ParticleTask { @@ -353,6 +356,7 @@ int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct Pa /* child paths */ void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part); void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part); +void BKE_particlesettings_twist_curve_init(struct ParticleSettings *part); void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers, struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4], struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys, const float parent_orco[3]); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index ef2ed9e2b65..ff70e71edd4 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -413,6 +413,8 @@ void BKE_particlesettings_free(ParticleSettings *part) curvemapping_free(part->clumpcurve); if (part->roughcurve) curvemapping_free(part->roughcurve); + if (part->twistcurve) + curvemapping_free(part->twistcurve); free_partdeflect(part->pd); free_partdeflect(part->pd2); @@ -2144,6 +2146,7 @@ static bool psys_thread_context_init_path( ctx->vg_rough1 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH1); ctx->vg_rough2 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH2); ctx->vg_roughe = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGHE); + ctx->vg_twist = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_TWIST); if (psys->part->flag & PART_CHILD_EFFECT) ctx->vg_effector = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_EFFECTOR); @@ -2162,6 +2165,13 @@ static bool psys_thread_context_init_path( else { ctx->roughcurve = NULL; } + if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) { + ctx->twistcurve = curvemapping_copy(part->twistcurve); + curvemapping_changed_all(ctx->twistcurve); + } + else { + ctx->twistcurve = NULL; + } return true; } @@ -2306,7 +2316,19 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp /* get the original coordinates (orco) for texture usage */ cpa_from = part->from; - cpa_num = pa->num; + + /* + * NOTE: Should in theory be the same as: + cpa_num = psys_particle_dm_face_lookup( + ctx->sim.psmd->dm_final, + ctx->sim.psmd->dm_deformed, + pa->num, pa->fuv, + NULL); + */ + 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) */ if (cpa_num > ctx->sim.psmd->dm_final->getNumTessFaces(ctx->sim.psmd->dm_final)) cpa_num = 0; @@ -3349,6 +3371,18 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part) part->roughcurve = cumap; } +void BKE_particlesettings_twist_curve_init(ParticleSettings *part) +{ + CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + + cumap->cm[0].curve[0].x = 0.0f; + cumap->cm[0].curve[0].y = 1.0f; + cumap->cm[0].curve[1].x = 1.0f; + cumap->cm[0].curve[1].y = 1.0f; + + part->twistcurve = cumap; +} + /** * Only copy internal data of ParticleSettings ID from source to already allocated/initialized destination. * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. @@ -3371,6 +3405,9 @@ void BKE_particlesettings_copy_data( if (part_src->roughcurve) { part_dst->roughcurve = curvemapping_copy(part_src->roughcurve); } + if (part_src->twistcurve) { + part_dst->twistcurve = curvemapping_copy(part_src->twistcurve); + } part_dst->boids = boid_copy_settings(part_src->boids); @@ -3490,6 +3527,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp = ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f; + ptex->twist = 1.0f; ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26); ptex->length *= part->clength_thres < psys_frand(psys, child_index + 27) ? part->clength : 1.0f; @@ -3542,6 +3580,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti SET_PARTICLE_TEXTURE(PAMAP_KINK_AMP, ptex->kink_amp, mtex->kinkampfac); SET_PARTICLE_TEXTURE(PAMAP_KINK_FREQ, ptex->kink_freq, mtex->kinkfac); SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac); + SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac); } } @@ -3567,6 +3606,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp = ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f; + ptex->twist = 1.0f; ptex->time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart; @@ -3641,6 +3681,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex 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); + SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac); } } @@ -3732,6 +3773,8 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread ptex->roughe *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_roughe); if (ctx->vg_effector) ptex->effector *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector); + if (ctx->vg_twist) + ptex->twist *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_twist); } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, const bool vel) @@ -3937,7 +3980,18 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * copy_particle_key(&tstate, state, 1); /* apply different deformations to the child path */ - do_child_modifiers(NULL, sim, &ptex, par->co, par->vel, par->rot, par_orco, cpa, orco, hairmat, state, t); + ParticleChildModifierContext modifier_ctx = {NULL}; + modifier_ctx.thread_ctx = NULL; + modifier_ctx.sim = sim; + modifier_ctx.ptex = &ptex; + modifier_ctx.cpa = cpa; + modifier_ctx.orco = orco; + modifier_ctx.par_co = par->co; + modifier_ctx.par_vel = par->vel; + modifier_ctx.par_rot = par->rot; + modifier_ctx.par_orco = par_orco; + modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL; + do_child_modifiers(&modifier_ctx, hairmat, state, t); /* try to estimate correct velocity */ if (vel) { @@ -4040,7 +4094,19 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta CLAMP(t, 0.0f, 1.0f); unit_m4(mat); - do_child_modifiers(NULL, sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t); + ParticleChildModifierContext modifier_ctx = {NULL}; + modifier_ctx.thread_ctx = NULL; + modifier_ctx.sim = sim; + modifier_ctx.ptex = NULL; + modifier_ctx.cpa = cpa; + modifier_ctx.orco = cpa->fuv; + modifier_ctx.par_co = key1->co; + modifier_ctx.par_vel = key1->vel; + modifier_ctx.par_rot = key1->rot; + modifier_ctx.par_orco = par_orco; + modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL; + + do_child_modifiers(&modifier_ctx, mat, state, t); if (psys->lattice_deform_data) calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength); diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index bc4c32f5805..8cdd668b7e7 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -235,6 +235,15 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co kink_base[part->kink_axis] = 1.0f; mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base); + /* Fill in invariant part of modifier context. */ + ParticleChildModifierContext modifier_ctx = {NULL}; + modifier_ctx.thread_ctx = ctx; + modifier_ctx.sim = &ctx->sim; + modifier_ctx.ptex = ptex; + modifier_ctx.cpa = cpa; + modifier_ctx.orco = orco; + modifier_ctx.parent_keys = parent_keys; + for (k = 0, key = keys; k < end_index; k++, key++) { float par_time; float *par_co, *par_vel, *par_rot; @@ -274,8 +283,14 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co do_kink_spiral_deform((ParticleKey *)key, dir, kink, spiral_time, kink_freq, kink_shape, kink_amp, spiral_start); } - /* apply different deformations to the child path */ - do_child_modifiers(ctx, &ctx->sim, ptex, par_co, par_vel, par_rot, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, par_time); + /* Fill in variant part of modifier context. */ + modifier_ctx.par_co = par_co; + modifier_ctx.par_vel = par_vel; + modifier_ctx.par_rot = par_rot; + modifier_ctx.par_orco = parent_orco; + + /* Apply different deformations to the child path/ */ + do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, par_time); } totlen = 0.0f; @@ -331,19 +346,33 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod keys->segments = totkeys - 1; } else { - ParticlePathIterator iter; + /* Fill in invariant part of modifier context. */ + ParticleChildModifierContext modifier_ctx = {NULL}; + modifier_ctx.thread_ctx = ctx; + modifier_ctx.sim = &ctx->sim; + modifier_ctx.ptex = ptex; + modifier_ctx.cpa = cpa; + modifier_ctx.orco = orco; + modifier_ctx.parent_keys = parent_keys; totkeys = ctx->segments + 1; max_length = ptex->length; + printf("%f\n", ptex->twist); for (k = 0, key = keys; k < totkeys; k++, key++) { - ParticleKey *par; - + ParticlePathIterator iter; psys_path_iter_get(&iter, keys, totkeys, parent_keys, k); - par = (ParticleKey *)iter.parent_key; - /* apply different deformations to the child path */ - do_child_modifiers(ctx, &ctx->sim, ptex, par->co, par->vel, iter.parent_rotation, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, iter.time); + ParticleKey *par = (ParticleKey *)iter.parent_key; + + /* Fill in variant part of modifier context. */ + modifier_ctx.par_co = par->co; + modifier_ctx.par_vel = par->vel; + modifier_ctx.par_rot = iter.parent_rotation; + modifier_ctx.par_orco = parent_orco; + + /* Apply different deformations to the child path. */ + do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, iter.time); } } @@ -662,10 +691,100 @@ static void do_rough_curve(const float loc[3], float mat[4][4], float time, floa madd_v3_v3fl(state->co, mat[2], fac * rough[2]); } -void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, ParticleTexture *ptex, - const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3], - ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t) +static int twist_num_segments(const ParticleChildModifierContext *modifier_ctx) +{ + ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx; + return (thread_ctx != NULL) ? thread_ctx->segments + : modifier_ctx->sim->psys->part->draw_step; +} + +static void twist_get_axis(const ParticleChildModifierContext *modifier_ctx, + const float time, float r_axis[3]) +{ + const int num_segments = twist_num_segments(modifier_ctx); + const int index = clamp_i(time * num_segments, 0, num_segments); + if (index > 0) { + sub_v3_v3v3(r_axis, + modifier_ctx->parent_keys[index].co, + modifier_ctx->parent_keys[index - 1].co); + } + else { + sub_v3_v3v3(r_axis, + modifier_ctx->parent_keys[index + 1].co, + modifier_ctx->parent_keys[index].co); + } +} + +static float curvemapping_integrate_clamped(CurveMapping *curve, + float start, float end, float step) +{ + float integral = 0.0f; + float x = start; + while (x < end) { + float y = curvemapping_evaluateF(curve, 0, x); + y = clamp_f(y, 0.0f, 1.0f); + /* TODO(sergey): Clamp last step to end. */ + integral += y * step; + x += step; + } + return integral; +} + +static void do_twist(const ParticleChildModifierContext *modifier_ctx, + ParticleKey *state, const float time) +{ + ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx; + ParticleSimulationData *sim = modifier_ctx->sim; + ParticleTexture *ptex = modifier_ctx->ptex; + ParticleSettings *part = sim->psys->part; + /* Early output checks. */ + if (part->childtype != PART_CHILD_PARTICLES) { + /* Interpolated children behave weird with twist. */ + return; + } + if (part->twist == 0.0f) { + /* No twist along the strand. */ + return; + } + /* Dependent on whether it's threaded update or not, curve comes + * from different places. + */ + CurveMapping *twist_curve = NULL; + if (part->child_flag & PART_CHILD_USE_TWIST_CURVE) { + twist_curve = (thread_ctx != NULL) ? thread_ctx->twistcurve + : part->twistcurve; + } + /* Axis of rotation. */ + float axis[3]; + twist_get_axis(modifier_ctx, time, axis); + /* Angle of rotation. */ + float angle = part->twist; + if (ptex != NULL) { + angle *= (ptex->twist - 0.5f) * 2.0f; + } + if (twist_curve != NULL) { + const int num_segments = twist_num_segments(modifier_ctx); + angle *= curvemapping_integrate_clamped(twist_curve, + 0.0f, time, + 1.0f / num_segments); + } + else { + angle *= time; + } + /* Perform rotation around parent curve. */ + float vec[3]; + sub_v3_v3v3(vec, state->co, modifier_ctx->par_co); + rotate_v3_v3v3fl(state->co, vec, axis, angle * 2.0f * M_PI); + add_v3_v3(state->co, modifier_ctx->par_co); +} + +void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, + float mat[4][4], ParticleKey *state, float t) { + ParticleThreadContext *ctx = modifier_ctx->thread_ctx; + ParticleSimulationData *sim = modifier_ctx->sim; + ParticleTexture *ptex = modifier_ctx->ptex; + ChildParticle *cpa = modifier_ctx->cpa; ParticleSettings *part = sim->psys->part; CurveMapping *clumpcurve = NULL, *roughcurve = NULL; int i = cpa - sim->psys->child; @@ -694,6 +813,8 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, rough_end *= ptex->roughe; } + do_twist(modifier_ctx, state, t); + if (part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ guided = do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t); @@ -702,25 +823,43 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, float orco_offset[3]; float clump; - sub_v3_v3v3(orco_offset, orco, par_orco); - clump = do_clump(state, par_co, t, orco_offset, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f, - part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve); + sub_v3_v3v3(orco_offset, modifier_ctx->orco, modifier_ctx->par_orco); + clump = do_clump(state, + modifier_ctx->par_co, + t, + orco_offset, + part->clumpfac, + part->clumppow, + ptex ? ptex->clump : 1.0f, + part->child_flag & PART_CHILD_USE_CLUMP_NOISE, + part->clump_noise_size, + clumpcurve); if (kink_freq != 0.f) { kink_amp *= (1.f - kink_amp_clump * clump); - do_kink(state, par_co, par_vel, par_rot, t, kink_freq, part->kink_shape, - kink_amp, part->kink_flat, part->kink, part->kink_axis, - sim->ob->obmat, smooth_start); + do_kink(state, + modifier_ctx->par_co, + modifier_ctx->par_vel, + modifier_ctx->par_rot, + t, + kink_freq, + part->kink_shape, + kink_amp, + part->kink_flat, + part->kink, + part->kink_axis, + sim->ob->obmat, + smooth_start); } } if (roughcurve) { - do_rough_curve(orco, mat, t, rough1, part->rough1_size, roughcurve, state); + do_rough_curve(modifier_ctx->orco, mat, t, rough1, part->rough1_size, roughcurve, state); } else { if (rough1 > 0.f) - do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state); + do_rough(modifier_ctx->orco, mat, t, rough1, part->rough1_size, 0.0, state); if (rough2 > 0.f) { float vec[3]; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 0fcc918a069..8171f3e7812 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -499,6 +499,8 @@ void psys_thread_context_free(ParticleThreadContext *ctx) MEM_freeN(ctx->vg_rough2); if (ctx->vg_roughe) MEM_freeN(ctx->vg_roughe); + if (ctx->vg_twist) + MEM_freeN(ctx->vg_twist); if (ctx->sim.psys->lattice_deform_data) { end_latt_deform(ctx->sim.psys->lattice_deform_data); @@ -521,6 +523,9 @@ void psys_thread_context_free(ParticleThreadContext *ctx) if (ctx->roughcurve != NULL) { curvemapping_free(ctx->roughcurve); } + if (ctx->twistcurve != NULL) { + curvemapping_free(ctx->twistcurve); + } } static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p) diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 9f9818127bc..4ab7b76aaab 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1287,6 +1287,8 @@ static void emit_from_particles( curvemapping_changed_all(psys->part->clumpcurve); if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) curvemapping_changed_all(psys->part->roughcurve); + if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve) + curvemapping_changed_all(psys->part->twistcurve); /* initialize particle cache */ if (psys->part->type == PART_HAIR) { diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index fcedd880615..71b90641e02 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -412,6 +412,7 @@ void BKE_texture_mtex_default(MTex *mtex) mtex->kinkfac = 1.0f; mtex->kinkampfac = 1.0f; mtex->roughfac = 1.0f; + mtex->twistfac = 1.0f; mtex->padensfac = 1.0f; mtex->lifefac = 1.0f; mtex->sizefac = 1.0f; diff --git a/source/blender/blenkernel/particle_private.h b/source/blender/blenkernel/particle_private.h index b4878807df7..2189527118b 100644 --- a/source/blender/blenkernel/particle_private.h +++ b/source/blender/blenkernel/particle_private.h @@ -31,12 +31,24 @@ #ifndef __PARTICLE_PRIVATE_H__ #define __PARTICLE_PRIVATE_H__ +typedef struct ParticleChildModifierContext { + ParticleThreadContext *thread_ctx; + ParticleSimulationData *sim; + ParticleTexture *ptex; + ChildParticle *cpa; + const float *par_co; /* float3 */ + const float *par_vel; /* float3 */ + const float *par_rot; /* float4 */ + const float *par_orco; /* float3 */ + const float *orco; /* float3 */ + ParticleCacheKey *parent_keys; +} ParticleChildModifierContext; + void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat, short type, short axis, float obmat[4][4], int smooth_start); float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump, bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve); -void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, - ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3], - ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t); +void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, + float mat[4][4], ParticleKey *state, float t); #endif /* __PARTICLE_PRIVATE_H__ */ diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 05562502278..d6e48fa59e7 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -890,6 +890,8 @@ void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axi void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle) { + BLI_assert(r != p); + float axis_n[3]; normalize_v3_v3(axis_n, axis); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b75a2de935a..c20246bcbfb 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4406,6 +4406,9 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part) part->roughcurve = newdataadr(fd, part->roughcurve); if (part->roughcurve) direct_link_curvemapping(fd, part->roughcurve); + part->twistcurve = newdataadr(fd, part->twistcurve); + if (part->twistcurve) + direct_link_curvemapping(fd, part->twistcurve); part->effector_weights = newdataadr(fd, part->effector_weights); if (!part->effector_weights) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 712ce334002..d566058f4a7 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1337,6 +1337,9 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part) if (part->roughcurve) { write_curvemapping(wd, part->roughcurve); } + if (part->twistcurve) { + write_curvemapping(wd, part->twistcurve); + } for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 240eda4bf8e..75c217c4f0c 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -5978,6 +5978,8 @@ static void draw_new_particle_system( curvemapping_changed_all(psys->part->clumpcurve); if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) curvemapping_changed_all(psys->part->roughcurve); + if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve) + curvemapping_changed_all(psys->part->twistcurve); /* 2. */ sim.eval_ctx = eval_ctx; diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index ea7905eb2ad..a7be2e37c4b 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -263,6 +263,11 @@ typedef struct ParticleSettings { short pad5; int recalc; + + float twist; + float pad6; + struct CurveMapping *twistcurve; + void *pad7; } ParticleSettings; typedef struct ParticleSystem { @@ -305,7 +310,8 @@ typedef struct ParticleSystem { char bb_uvname[3][64]; /* billboard uv name, MAX_CUSTOMDATA_LAYER_NAME */ /* if you change these remember to update array lengths to PSYS_TOT_VG! */ - short vgroup[12], vg_neg, rt3; /* vertex groups, 0==disable, 1==starting index */ + short vgroup[13], vg_neg, rt3; /* vertex groups, 0==disable, 1==starting index */ + char pad[6]; /* temporary storage during render */ struct ParticleRenderData *renderdata; @@ -439,6 +445,7 @@ typedef enum eParticleChildFlag { PART_CHILD_USE_CLUMP_NOISE = (1<<0), PART_CHILD_USE_CLUMP_CURVE = (1<<1), PART_CHILD_USE_ROUGH_CURVE = (1<<2), + PART_CHILD_USE_TWIST_CURVE = (1<<3), } eParticleChildFlag; /* part->draw_col */ @@ -566,7 +573,7 @@ typedef enum eParticleChildFlag { #define PART_DUPLIW_CURRENT 1 /* psys->vg */ -#define PSYS_TOT_VG 12 +#define PSYS_TOT_VG 13 #define PSYS_VG_DENSITY 0 #define PSYS_VG_VEL 1 @@ -580,6 +587,7 @@ typedef enum eParticleChildFlag { #define PSYS_VG_TAN 9 #define PSYS_VG_ROT 10 #define PSYS_VG_EFFECTOR 11 +#define PSYS_VG_TWIST 12 /* ParticleTarget->flag */ #define PTARGET_CURRENT 1 @@ -611,7 +619,8 @@ typedef enum eParticleTextureInfluence { PAMAP_KINK_AMP = (1<<12), PAMAP_ROUGH = (1<<9), PAMAP_LENGTH = (1<<4), - PAMAP_CHILD = (PAMAP_CLUMP | PAMAP_KINK_FREQ | PAMAP_KINK_AMP | PAMAP_ROUGH | PAMAP_LENGTH), + PAMAP_TWIST = (1<<13), + PAMAP_CHILD = (PAMAP_CLUMP | PAMAP_KINK_FREQ | PAMAP_KINK_AMP | PAMAP_ROUGH | PAMAP_LENGTH | PAMAP_TWIST), } eParticleTextureInfluence; #endif diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 995d7645dc0..0eb54a9b5b3 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -86,7 +86,7 @@ typedef struct MTex { float timefac, lengthfac, clumpfac, dampfac; float kinkfac, kinkampfac, roughfac, padensfac, gravityfac; float lifefac, sizefac, ivelfac, fieldfac; - int pad2; + float twistfac; /* lamp */ float shadowfac; diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 1a819c3bcdb..14bf612f467 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -953,6 +953,19 @@ static void rna_ParticleSettings_use_roughness_curve_update(Main *bmain, Scene * rna_Particle_redo_child(bmain, scene, ptr); } +static void rna_ParticleSettings_use_twist_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + ParticleSettings *part = ptr->data; + + if (part->child_flag & PART_CHILD_USE_TWIST_CURVE) { + if (!part->twistcurve) { + BKE_particlesettings_twist_curve_init(part); + } + } + + rna_Particle_redo_child(bmain, scene, ptr); +} + static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value) { Object *ob = ptr->id.data; @@ -1309,6 +1322,7 @@ static void rna_ParticleVGroup_name_get_8(PointerRNA *ptr, char *value) { psys_v static void rna_ParticleVGroup_name_get_9(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 9); } static void rna_ParticleVGroup_name_get_10(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 10); } static void rna_ParticleVGroup_name_get_11(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 11); } +static void rna_ParticleVGroup_name_get_12(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 12); } static int rna_ParticleVGroup_name_len_0(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 0); } static int rna_ParticleVGroup_name_len_1(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 1); } @@ -1322,6 +1336,7 @@ static int rna_ParticleVGroup_name_len_8(PointerRNA *ptr) { return psys_vg_name_ static int rna_ParticleVGroup_name_len_9(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 9); } static int rna_ParticleVGroup_name_len_10(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 10); } static int rna_ParticleVGroup_name_len_11(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 11); } +static int rna_ParticleVGroup_name_len_12(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 12); } static void rna_ParticleVGroup_name_set_0(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 0); } static void rna_ParticleVGroup_name_set_1(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 1); } @@ -1335,6 +1350,7 @@ static void rna_ParticleVGroup_name_set_8(PointerRNA *ptr, const char *value) { static void rna_ParticleVGroup_name_set_9(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 9); } static void rna_ParticleVGroup_name_set_10(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 10); } static void rna_ParticleVGroup_name_set_11(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 11); } +static void rna_ParticleVGroup_name_set_12(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 12); } #else @@ -1887,6 +1903,10 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Length", "Affect the child hair length"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); + prop = RNA_def_property(srna, "use_map_twist", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_TWIST); + RNA_def_property_ui_text(prop, "Twist", "Affect the child twist"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); /* influence factors */ prop = RNA_def_property(srna, "time_factor", PROP_FLOAT, PROP_NONE); @@ -1968,6 +1988,12 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 1, 10, 3); RNA_def_property_ui_text(prop, "Rough Factor", "Amount texture affects child roughness"); RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); + + prop = RNA_def_property(srna, "twist_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "twistfac"); + RNA_def_property_ui_range(prop, 0, 1, 10, 3); + RNA_def_property_ui_text(prop, "Twist Factor", "Amount texture affects child twist"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); } static void rna_def_particle_settings(BlenderRNA *brna) @@ -3174,6 +3200,25 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "FieldSettings"); RNA_def_property_pointer_funcs(prop, "rna_Particle_field2_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Force Field 2", ""); + + /* twist */ + prop = RNA_def_property(srna, "twist", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, -100000.0f, 100000.0f); + RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Twist", "Number of turns around parent allong the strand"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); + + prop = RNA_def_property(srna, "use_twist_curve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_TWIST_CURVE); + RNA_def_property_ui_text(prop, "Use Twist Curve", "Use a curve to define twist"); + RNA_def_property_update(prop, 0, "rna_ParticleSettings_use_twist_curve_update"); + + prop = RNA_def_property(srna, "twist_curve", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "twistcurve"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Twist Curve", "Curve defining twist"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); } static void rna_def_particle_target(BlenderRNA *brna) @@ -3507,6 +3552,18 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Vertex Group Field Negate", "Negate the effect of the field vertex group"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); + prop = RNA_def_property(srna, "vertex_group_twist", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_12", "rna_ParticleVGroup_name_len_12", + "rna_ParticleVGroup_name_set_12"); + RNA_def_property_ui_text(prop, "Vertex Group Twist", "Vertex group to control twist"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); + + prop = RNA_def_property(srna, "invert_vertex_group_twist", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_TWIST)); + RNA_def_property_ui_text(prop, "Vertex Group Twist Negate", + "Negate the effect of the twist vertex group"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); + /* pointcache */ prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); |