Merge branch 'master' into blender2.8
This commit is contained in:
commit
2589f55a55
|
@ -1197,6 +1197,12 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
|
|||
col.label(text="Effects:")
|
||||
|
||||
sub = col.column(align=True)
|
||||
if part.child_type == 'SIMPLE':
|
||||
sub.prop(part, "twist")
|
||||
sub.prop(part, "use_twist_curve")
|
||||
if part.use_twist_curve:
|
||||
sub.template_curve_mapping(part, "twist_curve")
|
||||
|
||||
sub.prop(part, "use_clump_curve")
|
||||
if part.use_clump_curve:
|
||||
sub.template_curve_mapping(part, "clump_curve")
|
||||
|
@ -1384,6 +1390,10 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
|
|||
row.prop_search(psys, "vertex_group_roughness_end", ob, "vertex_groups", text="Roughness End")
|
||||
row.prop(psys, "invert_vertex_group_roughness_end", text="", toggle=True, icon='ARROW_LEFTRIGHT')
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop_search(psys, "vertex_group_twist", ob, "vertex_groups", text="Twist")
|
||||
row.prop(psys, "invert_vertex_group_twist", text="", toggle=True, icon='ARROW_LEFTRIGHT')
|
||||
|
||||
# Commented out vertex groups don't work and are still waiting for better implementation
|
||||
# row = layout.row()
|
||||
# row.prop_search(psys, "vertex_group_velocity", ob, "vertex_groups", text="Velocity")
|
||||
|
|
|
@ -1173,6 +1173,7 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
|
|||
col = split.column()
|
||||
factor_but(col, "use_map_length", "length_factor", "Length")
|
||||
factor_but(col, "use_map_clump", "clump_factor", "Clump")
|
||||
factor_but(col, "use_map_twist", "twist_factor", "Twist")
|
||||
|
||||
col = split.column()
|
||||
factor_but(col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude")
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.) */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue