Blender V4.3
particle_child.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_math_matrix.h"
10#include "BLI_math_rotation.h"
11#include "BLI_math_vector.h"
12#include "BLI_noise.h"
13
14#include "DNA_material_types.h"
15#include "DNA_object_types.h"
16
17#include "BKE_colortools.hh"
18#include "BKE_particle.h"
19
20#include "particle_private.h"
21
22/* ------------------------------------------------------------------------- */
23
32
34 ParticleCacheKey *keys,
35 int totkeys,
36 ParticleCacheKey *parent,
37 int index)
38{
39 BLI_assert(index >= 0 && index < totkeys);
40
41 iter->key = keys + index;
42 iter->index = index;
43 iter->time = float(index) / float(totkeys - 1);
44
45 if (parent) {
46 iter->parent_key = parent + index;
47 if (index > 0) {
48 mul_qt_qtqt(iter->parent_rotation, iter->parent_key->rot, parent->rot);
49 }
50 else {
51 copy_qt_qt(iter->parent_rotation, parent->rot);
52 }
53 }
54 else {
55 iter->parent_key = nullptr;
57 }
58}
59
60/* ------------------------------------------------------------------------- */
61
63 const float dir[3],
64 const float kink[3],
65 float time,
66 float freq,
67 float shape,
68 float amplitude,
69 const float spiral_start[3])
70{
71 float result[3];
72
73 CLAMP(time, 0.0f, 1.0f);
74
75 copy_v3_v3(result, state->co);
76
77 {
78 /* Creates a logarithmic spiral:
79 * r(theta) = a * exp(b * theta)
80 *
81 * The "density" parameter b is defined by the shape parameter
82 * and goes up to the Golden Spiral for 1.0
83 * https://en.wikipedia.org/wiki/Golden_spiral
84 */
85 const float b = shape * (1.0f + sqrtf(5.0f)) / float(M_PI) * 0.25f;
86 /* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
87 const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) : float(-M_PI_2)) +
88 (b > 0.0f ? -float(M_PI_2) : float(M_PI_2));
89
90 float spiral_axis[3], rot[3][3];
91 float vec[3];
92
93 float theta = freq * time * 2.0f * float(M_PI);
94 float radius = amplitude * expf(b * theta);
95
96 /* a bit more intuitive than using negative frequency for this */
97 if (amplitude < 0.0f) {
98 theta = -theta;
99 }
100
101 cross_v3_v3v3(spiral_axis, dir, kink);
102 normalize_v3(spiral_axis);
103
104 mul_v3_v3fl(vec, kink, -radius);
105
106 axis_angle_normalized_to_mat3(rot, spiral_axis, theta);
107 mul_m3_v3(rot, vec);
108
109 madd_v3_v3fl(vec, kink, amplitude);
110
111 axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle);
112 mul_m3_v3(rot, vec);
113
114 add_v3_v3v3(result, spiral_start, vec);
115 }
116
117 copy_v3_v3(state->co, result);
118}
119
121 ParticleTexture *ptex,
122 const float parent_orco[3],
123 ChildParticle *cpa,
124 const float orco[3],
125 float hairmat[4][4],
126 ParticleCacheKey *keys,
127 ParticleCacheKey *parent_keys,
128 int *r_totkeys,
129 float *r_max_length)
130{
131 ParticleSettings *part = ctx->sim.psys->part;
132 const int seed = ctx->sim.psys->child_seed + int(cpa - ctx->sim.psys->child);
133 const int totkeys = ctx->segments + 1;
134 const int extrakeys = ctx->extra_segments;
135
136 float kink_amp_random = part->kink_amp_random;
137 float kink_amp = part->kink_amp *
138 (1.0f - kink_amp_random * psys_frand(ctx->sim.psys, 93541 + seed));
139 float kink_freq = part->kink_freq;
140 float kink_shape = part->kink_shape;
141 float kink_axis_random = part->kink_axis_random;
142
144 ParticleCacheKey *key;
145 int k;
146
147 float dir[3];
148 float spiral_start[3] = {0.0f, 0.0f, 0.0f};
149 float spiral_start_time = 0.0f;
150 float spiral_par_co[3] = {0.0f, 0.0f, 0.0f};
151 float spiral_par_vel[3] = {0.0f, 0.0f, 0.0f};
152 float spiral_par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
153 float totlen;
154 float cut_time;
155 int start_index = 0, end_index = 0;
156 float kink_base[3];
157
158 kink_amp *= ptex->kink_amp;
159 kink_freq *= ptex->kink_freq;
160
161 cut_time = (totkeys - 1) * ptex->length;
162 zero_v3(spiral_start);
163
164 for (k = 0, key = keys; k < totkeys - 1; k++, key++) {
165 if (float(k + 1) >= cut_time) {
166 float fac = cut_time - float(k);
167 ParticleCacheKey *par = parent_keys + k;
168
169 start_index = k + 1;
170 end_index = start_index + extrakeys;
171
172 spiral_start_time = (float(k) + fac) / float(totkeys - 1);
173 interp_v3_v3v3(spiral_start, key->co, (key + 1)->co, fac);
174
175 interp_v3_v3v3(spiral_par_co, par->co, (par + 1)->co, fac);
176 interp_v3_v3v3(spiral_par_vel, par->vel, (par + 1)->vel, fac);
177 interp_qt_qtqt(spiral_par_rot, par->rot, (par + 1)->rot, fac);
178
179 break;
180 }
181 }
182
183 zero_v3(dir);
184
185 zero_v3(kink_base);
186 kink_base[part->kink_axis] = 1.0f;
187 mul_mat3_m4_v3(ctx->sim.ob->object_to_world().ptr(), kink_base);
188
189 /* Fill in invariant part of modifier context. */
190 ParticleChildModifierContext modifier_ctx = {nullptr};
191 modifier_ctx.thread_ctx = ctx;
192 modifier_ctx.sim = &ctx->sim;
193 modifier_ctx.ptex = ptex;
194 modifier_ctx.cpa = cpa;
195 modifier_ctx.orco = orco;
196 modifier_ctx.parent_keys = parent_keys;
197
198 for (k = 0, key = keys; k < end_index; k++, key++) {
199 float par_time;
200 float *par_co, *par_vel, *par_rot;
201
202 psys_path_iter_get(&iter, keys, end_index, nullptr, k);
203 if (k < start_index) {
204 sub_v3_v3v3(dir, (key + 1)->co, key->co);
205 normalize_v3(dir);
206
207 par_time = float(k) / float(totkeys - 1);
208 par_co = parent_keys[k].co;
209 par_vel = parent_keys[k].vel;
210 par_rot = parent_keys[k].rot;
211 }
212 else {
213 float spiral_time = float(k - start_index) / float(extrakeys - 1);
214 float kink[3], tmp[3];
215
216 /* use same time value for every point on the spiral */
217 par_time = spiral_start_time;
218 par_co = spiral_par_co;
219 par_vel = spiral_par_vel;
220 par_rot = spiral_par_rot;
221
222 project_v3_v3v3(tmp, kink_base, dir);
223 sub_v3_v3v3(kink, kink_base, tmp);
224 normalize_v3(kink);
225
226 if (kink_axis_random > 0.0f) {
227 float a = kink_axis_random * (psys_frand(ctx->sim.psys, 7112 + seed) * 2.0f - 1.0f) *
228 float(M_PI);
229 float rot[3][3];
230
232 mul_m3_v3(rot, kink);
233 }
234
236 dir,
237 kink,
238 spiral_time,
239 kink_freq,
240 kink_shape,
241 kink_amp,
242 spiral_start);
243 }
244
245 /* Fill in variant part of modifier context. */
246 modifier_ctx.par_co = par_co;
247 modifier_ctx.par_vel = par_vel;
248 modifier_ctx.par_rot = par_rot;
249 modifier_ctx.par_orco = parent_orco;
250
251 /* Apply different deformations to the child path/ */
252 do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, par_time);
253 }
254
255 totlen = 0.0f;
256 for (k = 0, key = keys; k < end_index - 1; k++, key++) {
257 totlen += len_v3v3((key + 1)->co, key->co);
258 }
259
260 *r_totkeys = end_index;
261 *r_max_length = totlen;
262}
263
264/* ------------------------------------------------------------------------- */
265
266static bool check_path_length(int k,
267 ParticleCacheKey *keys,
268 ParticleCacheKey *key,
269 float max_length,
270 float step_length,
271 float *cur_length,
272 float dvec[3])
273{
274 if (*cur_length + step_length > max_length) {
275 sub_v3_v3v3(dvec, key->co, (key - 1)->co);
276 mul_v3_fl(dvec, (max_length - *cur_length) / step_length);
277 add_v3_v3v3(key->co, (key - 1)->co, dvec);
278 keys->segments = k;
279 /* something over the maximum step value */
280 return false;
281 }
282
283 *cur_length += step_length;
284 return true;
285}
286
288 ListBase * /*modifiers*/,
289 ChildParticle *cpa,
290 ParticleTexture *ptex,
291 const float orco[3],
292 float hairmat[4][4],
293 ParticleCacheKey *keys,
294 ParticleCacheKey *parent_keys,
295 const float parent_orco[3])
296{
297 ParticleSettings *part = ctx->sim.psys->part;
298 Material *ma = ctx->ma;
299 const bool draw_col_ma = (part->draw_col == PART_DRAW_COL_MAT);
300 const bool use_length_check = !ELEM(part->kink, PART_KINK_SPIRAL);
301
302 ParticleCacheKey *key;
303 int totkeys, k;
304 float max_length;
305
306 /* TODO: for the future: use true particle modifiers that work on the whole curve. */
307
308 if (part->kink == PART_KINK_SPIRAL) {
310 ctx, ptex, parent_orco, cpa, orco, hairmat, keys, parent_keys, &totkeys, &max_length);
311 keys->segments = totkeys - 1;
312 }
313 else {
314 /* Fill in invariant part of modifier context. */
315 ParticleChildModifierContext modifier_ctx = {nullptr};
316 modifier_ctx.thread_ctx = ctx;
317 modifier_ctx.sim = &ctx->sim;
318 modifier_ctx.ptex = ptex;
319 modifier_ctx.cpa = cpa;
320 modifier_ctx.orco = orco;
321 modifier_ctx.parent_keys = parent_keys;
322
323 totkeys = ctx->segments + 1;
324 max_length = ptex->length;
325
326 for (k = 0, key = keys; k < totkeys; k++, key++) {
328 psys_path_iter_get(&iter, keys, totkeys, parent_keys, k);
329
330 ParticleKey *par = (ParticleKey *)iter.parent_key;
331
332 /* Fill in variant part of modifier context. */
333 modifier_ctx.par_co = par->co;
334 modifier_ctx.par_vel = par->vel;
335 modifier_ctx.par_rot = iter.parent_rotation;
336 modifier_ctx.par_orco = parent_orco;
337
338 /* Apply different deformations to the child path. */
339 do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, iter.time);
340 }
341 }
342
343 {
344 const float step_length = 1.0f / float(totkeys - 1);
345 float cur_length = 0.0f;
346
347 if (max_length <= 0.0f) {
348 keys->segments = -1;
349 totkeys = 0;
350 }
351
352 /* we have to correct velocity because of kink & clump */
353 for (k = 0, key = keys; k < totkeys; k++, key++) {
354 if (k >= 2) {
355 sub_v3_v3v3((key - 1)->vel, key->co, (key - 2)->co);
356 mul_v3_fl((key - 1)->vel, 0.5);
357 }
358
359 if (use_length_check && k > 0) {
360 float dvec[3];
361 /* check if path needs to be cut before actual end of data points */
362 if (!check_path_length(k, keys, key, max_length, step_length, &cur_length, dvec)) {
363 /* last key */
364 sub_v3_v3v3(key->vel, key->co, (key - 1)->co);
365 if (ma && draw_col_ma) {
366 copy_v3_v3(key->col, &ma->r);
367 }
368 break;
369 }
370 }
371 if (k == totkeys - 1) {
372 /* last key */
373 sub_v3_v3v3(key->vel, key->co, (key - 1)->co);
374 }
375
376 if (ma && draw_col_ma) {
377 copy_v3_v3(key->col, &ma->r);
378 }
379 }
380 }
381}
382
383/* ------------------------------------------------------------------------- */
384
386 const float par_co[3],
387 const float par_vel[3],
388 const float par_rot[4],
389 float time,
390 float freq,
391 float shape,
392 float amplitude,
393 float flat,
394 short type,
395 short axis,
396 const float obmat[4][4],
397 int smooth_start)
398{
399 float kink[3] = {1.0f, 0.0f, 0.0f}, par_vec[3];
400 float t, dt = 1.0f, result[3];
401
402 if (ELEM(type, PART_KINK_NO, PART_KINK_SPIRAL)) {
403 return;
404 }
405
406 CLAMP(time, 0.0f, 1.0f);
407
408 if (shape != 0.0f && !ELEM(type, PART_KINK_BRAID)) {
409 if (shape < 0.0f) {
410 time = float(pow(time, 1.0f + shape));
411 }
412 else {
413 time = float(pow(time, 1.0f / (1.0f - shape)));
414 }
415 }
416
417 t = time * freq * float(M_PI);
418
419 if (smooth_start) {
420 dt = fabsf(t);
421 /* smooth the beginning of kink */
422 CLAMP(dt, 0.0f, float(M_PI));
423 dt = sinf(dt / 2.0f);
424 }
425
426 if (!ELEM(type, PART_KINK_RADIAL)) {
427 float temp[3];
428
429 kink[axis] = 1.0f;
430
431 if (obmat) {
432 mul_mat3_m4_v3(obmat, kink);
433 }
434
435 mul_qt_v3(par_rot, kink);
436
437 /* make sure kink is normal to strand */
438 project_v3_v3v3(temp, kink, par_vel);
439 sub_v3_v3(kink, temp);
440 normalize_v3(kink);
441 }
442
443 copy_v3_v3(result, state->co);
444 sub_v3_v3v3(par_vec, par_co, state->co);
445
446 switch (type) {
447 case PART_KINK_CURL: {
448 float curl_offset[3];
449 float q1[4] = {1.0f, 0.0f, 0.0f, 0.0f};
450
451 /* rotate kink vector around strand tangent */
452 mul_v3_v3fl(curl_offset, kink, amplitude);
453 axis_angle_to_quat(q1, par_vel, t);
454 mul_qt_v3(q1, curl_offset);
455
456 interp_v3_v3v3(par_vec, state->co, par_co, flat);
457 add_v3_v3v3(result, par_vec, curl_offset);
458 break;
459 }
460 case PART_KINK_RADIAL: {
461 if (flat > 0.0f) {
462 float proj[3];
463 /* flatten along strand */
464 project_v3_v3v3(proj, par_vec, par_vel);
465 madd_v3_v3fl(result, proj, flat);
466 }
467
468 madd_v3_v3fl(result, par_vec, -amplitude * sinf(t));
469 break;
470 }
471 case PART_KINK_WAVE: {
472 madd_v3_v3fl(result, kink, amplitude * sinf(t));
473
474 if (flat > 0.0f) {
475 float proj[3];
476 /* flatten along wave */
477 project_v3_v3v3(proj, par_vec, kink);
478 madd_v3_v3fl(result, proj, flat);
479
480 /* flatten along strand */
481 project_v3_v3v3(proj, par_vec, par_vel);
482 madd_v3_v3fl(result, proj, flat);
483 }
484 break;
485 }
486 case PART_KINK_BRAID: {
487 float y_vec[3] = {0.0f, 1.0f, 0.0f};
488 float z_vec[3] = {0.0f, 0.0f, 1.0f};
489 float vec_one[3], state_co[3];
490 float inp_y, inp_z, length;
491
492 if (par_rot) {
493 mul_qt_v3(par_rot, y_vec);
494 mul_qt_v3(par_rot, z_vec);
495 }
496
497 negate_v3(par_vec);
498 normalize_v3_v3(vec_one, par_vec);
499
500 inp_y = dot_v3v3(y_vec, vec_one);
501 inp_z = dot_v3v3(z_vec, vec_one);
502
503 if (inp_y > 0.5f) {
504 copy_v3_v3(state_co, y_vec);
505
506 mul_v3_fl(y_vec, amplitude * cosf(t));
507 mul_v3_fl(z_vec, amplitude / 2.0f * sinf(2.0f * t));
508 }
509 else if (inp_z > 0.0f) {
510 mul_v3_v3fl(state_co, z_vec, sinf(float(M_PI) / 3.0f));
511 madd_v3_v3fl(state_co, y_vec, -0.5f);
512
513 mul_v3_fl(y_vec, -amplitude * cosf(t + float(M_PI) / 3.0f));
514 mul_v3_fl(z_vec, amplitude / 2.0f * cosf(2.0f * t + float(M_PI) / 6.0f));
515 }
516 else {
517 mul_v3_v3fl(state_co, z_vec, -sinf(float(M_PI) / 3.0f));
518 madd_v3_v3fl(state_co, y_vec, -0.5f);
519
520 mul_v3_fl(y_vec, amplitude * -sinf(t + float(M_PI) / 6.0f));
521 mul_v3_fl(z_vec, amplitude / 2.0f * -sinf(2.0f * t + float(M_PI) / 3.0f));
522 }
523
524 mul_v3_fl(state_co, amplitude);
525 add_v3_v3(state_co, par_co);
526 sub_v3_v3v3(par_vec, state->co, state_co);
527
528 length = normalize_v3(par_vec);
529 mul_v3_fl(par_vec, std::min(length, amplitude / 2.0f));
530
531 add_v3_v3v3(state_co, par_co, y_vec);
532 add_v3_v3(state_co, z_vec);
533 add_v3_v3(state_co, par_vec);
534
535 shape = 2.0f * float(M_PI) * (1.0f + shape);
536
537 if (t < shape) {
538 shape = t / shape;
539 shape = float(sqrt(double(shape)));
540 interp_v3_v3v3(result, result, state_co, shape);
541 }
542 else {
543 copy_v3_v3(result, state_co);
544 }
545 break;
546 }
547 }
548
549 /* blend the start of the kink */
550 if (dt < 1.0f) {
551 interp_v3_v3v3(state->co, state->co, result, dt);
552 }
553 else {
554 copy_v3_v3(state->co, result);
555 }
556}
557
558static float do_clump_level(float result[3],
559 const float co[3],
560 const float par_co[3],
561 float time,
562 float clumpfac,
563 float clumppow,
564 float pa_clump,
565 const CurveMapping *clumpcurve)
566{
567 float clump = 0.0f;
568
569 if (clumpcurve) {
570 clump = pa_clump *
571 (1.0f - clamp_f(BKE_curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
572
573 interp_v3_v3v3(result, co, par_co, clump);
574 }
575 else if (clumpfac != 0.0f) {
576 float cpow;
577
578 if (clumppow < 0.0f) {
579 cpow = 1.0f + clumppow;
580 }
581 else {
582 cpow = 1.0f + 9.0f * clumppow;
583 }
584
585 if (clumpfac < 0.0f) { /* clump roots instead of tips */
586 clump = -clumpfac * pa_clump * float(pow(1.0 - double(time), double(cpow)));
587 }
588 else {
589 clump = clumpfac * pa_clump * float(pow(double(time), double(cpow)));
590 }
591
592 interp_v3_v3v3(result, co, par_co, clump);
593 }
594
595 return clump;
596}
597
599 const float par_co[3],
600 float time,
601 const float orco_offset[3],
602 float clumpfac,
603 float clumppow,
604 float pa_clump,
605 bool use_clump_noise,
606 float clump_noise_size,
607 const CurveMapping *clumpcurve)
608{
609 float clump;
610
611 if (use_clump_noise && clump_noise_size != 0.0f) {
612 float center[3], noisevec[3];
613 float da[4], pa[12];
614
615 mul_v3_v3fl(noisevec, orco_offset, 1.0f / clump_noise_size);
616 BLI_noise_voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0);
617 mul_v3_fl(&pa[0], clump_noise_size);
618 add_v3_v3v3(center, par_co, &pa[0]);
619
620 do_clump_level(state->co, state->co, center, time, clumpfac, clumppow, pa_clump, clumpcurve);
621 }
622
623 clump = do_clump_level(
624 state->co, state->co, par_co, time, clumpfac, clumppow, pa_clump, clumpcurve);
625
626 return clump;
627}
628
629static void do_rough(const float loc[3],
630 const float mat[4][4],
631 float t,
632 float fac,
633 float size,
634 float thres,
636{
637 float rough[3];
638 float rco[3];
639
640 if (thres != 0.0f) {
641 if (fabsf(float(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) {
642 return;
643 }
644 }
645
646 copy_v3_v3(rco, loc);
647 mul_v3_fl(rco, t);
648 rough[0] = -1.0f +
649 2.0f * BLI_noise_generic_turbulence(size, rco[0], rco[1], rco[2], 2, false, 2);
650 rough[1] = -1.0f +
651 2.0f * BLI_noise_generic_turbulence(size, rco[1], rco[2], rco[0], 2, false, 2);
652 rough[2] = -1.0f +
653 2.0f * BLI_noise_generic_turbulence(size, rco[2], rco[0], rco[1], 2, false, 2);
654
655 madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
656 madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
657 madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
658}
659
660static void do_rough_end(
661 const float loc[3], const float mat[4][4], float t, float fac, float shape, ParticleKey *state)
662{
663 float rough[2];
664 float roughfac;
665
666 roughfac = fac * float(pow(double(t), shape));
667 copy_v2_v2(rough, loc);
668 rough[0] = -1.0f + 2.0f * rough[0];
669 rough[1] = -1.0f + 2.0f * rough[1];
670 mul_v2_fl(rough, roughfac);
671
672 madd_v3_v3fl(state->co, mat[0], rough[0]);
673 madd_v3_v3fl(state->co, mat[1], rough[1]);
674}
675
676static void do_rough_curve(const float loc[3],
677 const float mat[4][4],
678 float time,
679 float fac,
680 float size,
681 CurveMapping *roughcurve,
683{
684 float rough[3];
685 float rco[3];
686
687 if (!roughcurve) {
688 return;
689 }
690
691 fac *= clamp_f(BKE_curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
692
693 copy_v3_v3(rco, loc);
694 mul_v3_fl(rco, time);
695 rough[0] = -1.0f +
696 2.0f * BLI_noise_generic_turbulence(size, rco[0], rco[1], rco[2], 2, false, 2);
697 rough[1] = -1.0f +
698 2.0f * BLI_noise_generic_turbulence(size, rco[1], rco[2], rco[0], 2, false, 2);
699 rough[2] = -1.0f +
700 2.0f * BLI_noise_generic_turbulence(size, rco[2], rco[0], rco[1], 2, false, 2);
701
702 madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
703 madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
704 madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
705}
706
708{
709 ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx;
710 return (thread_ctx != nullptr) ? thread_ctx->segments : modifier_ctx->sim->psys->part->draw_step;
711}
712
713static void twist_get_axis(const ParticleChildModifierContext *modifier_ctx,
714 const float time,
715 float r_axis[3])
716{
717 const int num_segments = twist_num_segments(modifier_ctx);
718 const int index = clamp_i(time * num_segments, 0, num_segments);
719 if (index > 0) {
721 r_axis, modifier_ctx->parent_keys[index].co, modifier_ctx->parent_keys[index - 1].co);
722 }
723 else {
725 r_axis, modifier_ctx->parent_keys[index + 1].co, modifier_ctx->parent_keys[index].co);
726 }
727}
728
730 float start,
731 float end,
732 float step)
733{
734 float integral = 0.0f;
735 float x = start;
736 while (x < end) {
737 float y = BKE_curvemapping_evaluateF(curve, 0, x);
738 y = clamp_f(y, 0.0f, 1.0f);
739 /* TODO(sergey): Clamp last step to end. */
740 integral += y * step;
741 x += step;
742 }
743 return integral;
744}
745
746static void do_twist(const ParticleChildModifierContext *modifier_ctx,
748 const float time)
749{
750 ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx;
751 ParticleSimulationData *sim = modifier_ctx->sim;
752 ParticleTexture *ptex = modifier_ctx->ptex;
753 ParticleSettings *part = sim->psys->part;
754 /* Early output checks. */
755 if (modifier_ctx->parent_keys == nullptr) {
756 /* Cannot get axis of rotation... */
757 return;
758 }
759 if (part->childtype != PART_CHILD_PARTICLES) {
760 /* Interpolated children behave weird with twist. */
761 return;
762 }
763 if (part->twist == 0.0f) {
764 /* No twist along the strand. */
765 return;
766 }
767 /* Dependent on whether it's threaded update or not, curve comes
768 * from different places.
769 */
770 CurveMapping *twist_curve = nullptr;
771 if (part->child_flag & PART_CHILD_USE_TWIST_CURVE) {
772 twist_curve = (thread_ctx != nullptr) ? thread_ctx->twistcurve : part->twistcurve;
773 }
774 /* Axis of rotation. */
775 float axis[3];
776 twist_get_axis(modifier_ctx, time, axis);
777 /* Angle of rotation. */
778 float angle = part->twist;
779 if (ptex != nullptr) {
780 angle *= (ptex->twist - 0.5f) * 2.0f;
781 }
782 if (twist_curve != nullptr) {
783 const int num_segments = twist_num_segments(modifier_ctx);
784 angle *= BKE_curvemapping_integrate_clamped(twist_curve, 0.0f, time, 1.0f / num_segments);
785 }
786 else {
787 angle *= time;
788 }
789 /* Perform rotation around parent curve. */
790 float vec[3];
791 sub_v3_v3v3(vec, state->co, modifier_ctx->par_co);
792 rotate_v3_v3v3fl(state->co, vec, axis, angle * 2.0f * M_PI);
793 add_v3_v3(state->co, modifier_ctx->par_co);
794}
795
797 float mat[4][4],
799 float t)
800{
801 ParticleThreadContext *ctx = modifier_ctx->thread_ctx;
802 ParticleSimulationData *sim = modifier_ctx->sim;
803 ParticleTexture *ptex = modifier_ctx->ptex;
804 ChildParticle *cpa = modifier_ctx->cpa;
805 ParticleSettings *part = sim->psys->part;
806 CurveMapping *clumpcurve = nullptr, *roughcurve = nullptr;
807 int i = cpa - sim->psys->child;
808 int guided = 0;
809
810 if (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) {
811 clumpcurve = (ctx != nullptr) ? ctx->clumpcurve : part->clumpcurve;
812 }
813 if (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) {
814 roughcurve = (ctx != nullptr) ? ctx->roughcurve : part->roughcurve;
815 }
816
817 float kink_amp = part->kink_amp;
818 float kink_amp_clump = part->kink_amp_clump;
819 float kink_freq = part->kink_freq;
820 float rough1 = part->rough1;
821 float rough2 = part->rough2;
822 float rough_end = part->rough_end;
823 const bool smooth_start = (sim->psys->part->childtype == PART_CHILD_FACES);
824
825 if (ptex) {
826 kink_amp *= ptex->kink_amp;
827 kink_freq *= ptex->kink_freq;
828 rough1 *= ptex->rough1;
829 rough2 *= ptex->rough2;
830 rough_end *= ptex->roughe;
831 }
832
833 do_twist(modifier_ctx, state, t);
834
835 if (part->flag & PART_CHILD_EFFECT) {
836 /* state is safe to cast, since only co and vel are used */
837 guided = do_guides(sim->depsgraph,
838 sim->psys->part,
839 sim->psys->effectors,
841 cpa->parent,
842 t);
843 }
844
845 if (guided == 0) {
846 float orco_offset[3];
847 float clump;
848
849 sub_v3_v3v3(orco_offset, modifier_ctx->orco, modifier_ctx->par_orco);
850 clump = do_clump(state,
851 modifier_ctx->par_co,
852 t,
853 orco_offset,
854 part->clumpfac,
855 part->clumppow,
856 ptex ? ptex->clump : 1.0f,
857 part->child_flag & PART_CHILD_USE_CLUMP_NOISE,
858 part->clump_noise_size,
859 clumpcurve);
860
861 if (kink_freq != 0.0f) {
862 kink_amp *= (1.0f - kink_amp_clump * clump);
863
865 modifier_ctx->par_co,
866 modifier_ctx->par_vel,
867 modifier_ctx->par_rot,
868 t,
869 kink_freq,
870 part->kink_shape,
871 kink_amp,
872 part->kink_flat,
873 part->kink,
874 part->kink_axis,
875 sim->ob->object_to_world().ptr(),
876 smooth_start);
877 }
878 }
879
880 if (roughcurve) {
881 do_rough_curve(modifier_ctx->orco, mat, t, rough1, part->rough1_size, roughcurve, state);
882 }
883 else {
884 if (rough1 > 0.0f) {
885 do_rough(modifier_ctx->orco, mat, t, rough1, part->rough1_size, 0.0, state);
886 }
887
888 if (rough2 > 0.0f) {
889 float vec[3];
890 psys_frand_vec(sim->psys, i + 27, vec);
891 do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
892 }
893
894 if (rough_end > 0.0f) {
895 float vec[3];
896 psys_frand_vec(sim->psys, i + 27, vec);
897 do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state);
898 }
899 }
900}
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
bool do_guides(struct Depsgraph *depsgraph, struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int index, float time)
Definition particle.cc:2332
BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float vec[3])
BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
#define BLI_assert(a)
Definition BLI_assert.h:50
sqrt(x)+1/max(0
MINLINE float clamp_f(float value, float min, float max)
#define M_PI_2
MINLINE int clamp_i(int value, int min, int max)
#define M_PI
void mul_m3_v3(const float M[3][3], float r[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
void mul_qt_v3(const float q[4], float r[3])
void unit_qt(float q[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void copy_qt_qt(float q[4], const float a[4])
void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], float angle)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
void BLI_noise_voronoi(float x, float y, float z, float *da, float *pa, float me, int dtype)
Definition noise.c:915
float BLI_noise_generic_turbulence(float noisesize, float x, float y, float z, int oct, bool hard, int noisebasis)
Definition noise.c:1210
#define CLAMP(a, b, c)
#define ELEM(...)
Object is a sort of wrapper for general info.
@ PART_DRAW_COL_MAT
@ PART_CHILD_EFFECT
@ PART_CHILD_PARTICLES
@ PART_CHILD_FACES
@ PART_KINK_BRAID
@ PART_KINK_WAVE
@ PART_KINK_SPIRAL
@ PART_KINK_RADIAL
@ PART_KINK_CURL
@ PART_KINK_NO
@ PART_CHILD_USE_TWIST_CURVE
@ PART_CHILD_USE_CLUMP_CURVE
@ PART_CHILD_USE_CLUMP_NOISE
@ PART_CHILD_USE_ROUGH_CURVE
static unsigned long seed
Definition btSoftBody.h:39
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
local_group_size(16, 16) .push_constant(Type b
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
double time
#define sinf(x)
#define cosf(x)
#define expf(x)
#define atanf(x)
#define fabsf(x)
#define sqrtf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define rot(x, k)
static ulong state[N]
static void do_twist(const ParticleChildModifierContext *modifier_ctx, ParticleKey *state, const float time)
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, const CurveMapping *clumpcurve)
static bool check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *key, float max_length, float step_length, float *cur_length, float dvec[3])
static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const float kink[3], float time, float freq, float shape, float amplitude, const float spiral_start[3])
static float BKE_curvemapping_integrate_clamped(const CurveMapping *curve, float start, float end, float step)
void psys_apply_child_modifiers(ParticleThreadContext *ctx, ListBase *, ChildParticle *cpa, ParticleTexture *ptex, const float orco[3], float hairmat[4][4], ParticleCacheKey *keys, ParticleCacheKey *parent_keys, const float parent_orco[3])
static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, const float parent_orco[3], ChildParticle *cpa, const float orco[3], float hairmat[4][4], ParticleCacheKey *keys, ParticleCacheKey *parent_keys, int *r_totkeys, float *r_max_length)
static void do_rough_end(const float loc[3], const float mat[4][4], float t, float fac, float shape, ParticleKey *state)
static void twist_get_axis(const ParticleChildModifierContext *modifier_ctx, const float time, float r_axis[3])
static float do_clump_level(float result[3], const float co[3], const float par_co[3], float time, float clumpfac, float clumppow, float pa_clump, const CurveMapping *clumpcurve)
static void do_rough(const float loc[3], const float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state)
static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *keys, int totkeys, ParticleCacheKey *parent, int index)
static int twist_num_segments(const ParticleChildModifierContext *modifier_ctx)
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, const float obmat[4][4], int smooth_start)
void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, float mat[4][4], ParticleKey *state, float t)
static void do_rough_curve(const float loc[3], const float mat[4][4], float time, float fac, float size, CurveMapping *roughcurve, ParticleKey *state)
ParticleThreadContext * thread_ctx
ParticleSimulationData * sim
ParticleCacheKey * key
ParticleCacheKey * parent_key
struct Depsgraph * depsgraph
struct ParticleSystem * psys
struct Object * ob
ChildParticle * child
ParticleSettings * part
struct ListBase * effectors
struct CurveMapping * roughcurve
struct Material * ma
struct CurveMapping * twistcurve
struct CurveMapping * clumpcurve
struct ParticleSimulationData sim