Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/intern/particle.c26
-rw-r--r--source/blender/blenkernel/intern/particle_child.c87
-rw-r--r--source/blender/blenkernel/intern/particle_system.c3
-rw-r--r--source/blender/blenkernel/intern/smoke.c2
-rw-r--r--source/blender/blenkernel/particle_private.h1
6 files changed, 121 insertions, 0 deletions
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,