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