From ff82968a6ca3332cc5cccbf766821274d8bb469e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 14 Feb 2018 12:33:34 +0100 Subject: Particles: Wrap insane amount of arguments to child modifier evaluation Use single structure. It seems we will need to pass more information soon, so better to do it via the structure. --- source/blender/blenkernel/intern/particle.c | 25 ++++++- source/blender/blenkernel/intern/particle_child.c | 85 ++++++++++++++++++----- source/blender/blenkernel/particle_private.h | 17 ++++- 3 files changed, 103 insertions(+), 24 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2b5c293932a..8aa7b167b85 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3925,7 +3925,17 @@ 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; + do_child_modifiers(&modifier_ctx, hairmat, state, t); /* try to estimate correct velocity */ if (vel) { @@ -4028,7 +4038,18 @@ 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; + + 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 d420f331707..70e635e16cf 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -235,6 +235,14 @@ 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; + for (k = 0, key = keys; k < end_index; k++, key++) { float par_time; float *par_co, *par_vel, *par_rot; @@ -274,8 +282,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 +345,31 @@ 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; totkeys = ctx->segments + 1; max_length = ptex->length; 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 +688,13 @@ 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) +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; @@ -702,25 +731,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/particle_private.h b/source/blender/blenkernel/particle_private.h index b4878807df7..00a7637e246 100644 --- a/source/blender/blenkernel/particle_private.h +++ b/source/blender/blenkernel/particle_private.h @@ -31,12 +31,23 @@ #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 */ +} 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__ */ -- cgit v1.2.3 From bb3efe61276346f7ee12d24308d95d447941b0ec Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 14 Feb 2018 14:29:37 +0100 Subject: Blenlib: Assert when attempting to rotate point around vector and store result in the point This isn't supported since there are subsequent reads to all point coordinates after modification started. Probably we need to create a temp copy of point, but that's like extra CPU ticks. --- source/blender/blenlib/intern/math_vector.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source') 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); -- cgit v1.2.3 From ffde74a878882618ab4d4179ba8dd9b98aab15e2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 14 Feb 2018 14:33:53 +0100 Subject: Simple hair children: Initial implementation of twist control It allows to have children hair to be twisted around parent curve, which is quite an essential feature when creating hair braids. There are currently two controls: - Number of turns around parent children. - Influence curve, which allows to modify "twistness" along the strand. --- source/blender/blenkernel/BKE_particle.h | 2 + source/blender/blenkernel/intern/particle.c | 26 +++++++ source/blender/blenkernel/intern/particle_child.c | 87 ++++++++++++++++++++++ source/blender/blenkernel/intern/particle_system.c | 3 + source/blender/blenkernel/intern/smoke.c | 2 + source/blender/blenkernel/particle_private.h | 1 + source/blender/blenloader/intern/readfile.c | 3 + source/blender/blenloader/intern/writefile.c | 3 + source/blender/editors/space_view3d/drawobject.c | 2 + source/blender/makesdna/DNA_particle_types.h | 5 ++ source/blender/makesrna/intern/rna_particle.c | 32 ++++++++ 11 files changed, 166 insertions(+) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 2c72373c2a9..747a6b65bb0 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -162,6 +162,7 @@ typedef struct ParticleThreadContext { struct CurveMapping *clumpcurve; struct CurveMapping *roughcurve; + struct CurveMapping *twistcurve; } ParticleThreadContext; typedef struct ParticleTask { @@ -349,6 +350,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 8aa7b167b85..ea27e23ed2f 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -405,6 +405,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); @@ -2152,6 +2154,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; } @@ -3337,6 +3346,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. @@ -3359,6 +3380,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); @@ -3935,6 +3959,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * 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 */ @@ -4048,6 +4073,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta 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); diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index 70e635e16cf..53bf577d4f4 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -242,6 +242,7 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co 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; @@ -352,6 +353,7 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod 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; @@ -688,6 +690,89 @@ 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]); } +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; + 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 (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) { @@ -723,6 +808,8 @@ void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, 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->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index dfc732dcb74..bae76354705 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -519,6 +519,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 3cf98b284b1..34ff9a155b4 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1285,6 +1285,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/particle_private.h b/source/blender/blenkernel/particle_private.h index 00a7637e246..2189527118b 100644 --- a/source/blender/blenkernel/particle_private.h +++ b/source/blender/blenkernel/particle_private.h @@ -41,6 +41,7 @@ typedef struct ParticleChildModifierContext { 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, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2a25de121b3..9aa67e8651f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4253,6 +4253,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 ceb1233596a..5941f96041c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1304,6 +1304,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 828617d1447..c3823627009 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -5044,6 +5044,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv 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.scene = scene; diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index f6bed37dfa2..371b53567a6 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -261,6 +261,10 @@ typedef struct ParticleSettings { short use_modifier_stack; short pad5[3]; + float twist; + float pad6; + struct CurveMapping *twistcurve; + void *pad7; } ParticleSettings; typedef struct ParticleSystem { @@ -435,6 +439,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 */ diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 9e52457d32a..e9bbc981a13 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -944,6 +944,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; @@ -3170,6 +3183,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) -- cgit v1.2.3 From 67cec97387965009dfaa57f7f4c8ab948e048e70 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 14 Feb 2018 16:46:29 +0100 Subject: Simple hair children: Make twist affected by vertex group The idea is to give a control over direction of twist, and maybe amount of twist as well. More concrete example: make braids on left and right side of character head to be twisting opposite directions. Now, tricky part: we need some negative values to flip direction, but weights can not be negative. So we use same trick as displacement map and tangent normal maps, where 0.5 is neutral, values below 0.5 are considered negative and values above 0.5 are considered positive. --- source/blender/blenkernel/BKE_particle.h | 2 ++ source/blender/blenkernel/intern/particle.c | 5 +++++ source/blender/blenkernel/intern/particle_child.c | 4 ++++ source/blender/blenkernel/intern/particle_system.c | 2 ++ source/blender/makesdna/DNA_particle_types.h | 6 ++++-- source/blender/makesrna/intern/rna_particle.c | 15 +++++++++++++++ 6 files changed, 32 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 747a6b65bb0..0cda7dceb33 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -112,6 +112,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 { @@ -159,6 +160,7 @@ 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; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index ea27e23ed2f..723bb86cb47 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2136,6 +2136,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); @@ -3502,6 +3503,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; @@ -3579,6 +3581,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; @@ -3744,6 +3747,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) diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index 53bf577d4f4..fae304d6580 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -734,6 +734,7 @@ static void do_twist(const ParticleChildModifierContext *modifier_ctx, { 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) { @@ -757,6 +758,9 @@ static void do_twist(const ParticleChildModifierContext *modifier_ctx, 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, diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bae76354705..7851cd5e801 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -497,6 +497,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); diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 371b53567a6..8dd4d46a596 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -307,7 +307,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; @@ -567,7 +568,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 @@ -581,6 +582,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 diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index e9bbc981a13..caf120e0ea1 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1313,6 +1313,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); } @@ -1326,6 +1327,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); } @@ -1339,6 +1341,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 @@ -3535,6 +3538,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); -- cgit v1.2.3 From 5ce6ca05366e653cc576ac6beaed72d07c0e2e6c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 15 Feb 2018 10:27:39 +0100 Subject: Fix T54078: Adding subsurf prior to particle system breaks simple children vgroups and textures cpa->num points to a face index on BASE mesh, but get_child_modifier_parameters() expects index on a FINAL dm. So wrong index was used here. --- source/blender/blenkernel/intern/particle.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 723bb86cb47..87322b5fddc 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2306,7 +2306,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; -- cgit v1.2.3 From 6d4022f61980ba46efd391dcfe96dd88a8db8deb Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 15 Feb 2018 11:22:44 +0100 Subject: Simple hair children: Make twist affected by texture This completes twist feature, which is now possible to also control by texture. Since textures can not easily contain negative values as well, same trick with 0.5 neutral as vertex groups is used. All in all, this twist features allows to do following things. Original hair: {F2287535} Hair with scientifically calculated twist value of 0.5: {F2287540} And we can also twist braids in opposite directions dependent on left/right side: {F2287548} --- source/blender/blenkernel/intern/particle.c | 2 ++ source/blender/blenkernel/intern/particle_child.c | 1 + source/blender/blenkernel/intern/texture.c | 1 + source/blender/makesdna/DNA_particle_types.h | 3 ++- source/blender/makesdna/DNA_texture_types.h | 2 +- source/blender/makesrna/intern/rna_particle.c | 10 ++++++++++ 6 files changed, 17 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 87322b5fddc..d7e08233601 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3568,6 +3568,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); } } @@ -3668,6 +3669,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); } } diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index fae304d6580..48ecdb04348 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -358,6 +358,7 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod totkeys = ctx->segments + 1; max_length = ptex->length; + printf("%f\n", ptex->twist); for (k = 0, key = keys; k < totkeys; k++, key++) { ParticlePathIterator iter; psys_path_iter_get(&iter, keys, totkeys, parent_keys, k); 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/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 8dd4d46a596..9dbd1a18703 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -614,7 +614,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 caf120e0ea1..2710a184367 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1894,6 +1894,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); @@ -1975,6 +1979,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) -- cgit v1.2.3