Merge branch 'master' into blender2.8

This commit is contained in:
Sergey Sharybin 2018-02-15 12:33:44 +01:00
commit 2589f55a55
16 changed files with 345 additions and 29 deletions

View File

@ -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")

View File

@ -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")

View File

@ -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]);

View File

@ -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);

View File

@ -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];

View File

@ -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)

View File

@ -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) {

View File

@ -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;

View File

@ -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__ */

View File

@ -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);

View File

@ -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)

View File

@ -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.) */

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);