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