Blender  V3.3
particle_system.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Janne Karhu. All rights reserved.
3  * 2011-2012 AutoCRC (adaptive time step, Classical SPH). */
4 
9 #include <stddef.h>
10 
11 #include <math.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "MEM_guardedalloc.h"
16 
17 #include "DNA_anim_types.h"
18 #include "DNA_boid_types.h"
19 #include "DNA_cloth_types.h"
20 #include "DNA_curve_types.h"
21 #include "DNA_listBase.h"
22 #include "DNA_mesh_types.h"
23 #include "DNA_meshdata_types.h"
24 #include "DNA_modifier_types.h"
25 #include "DNA_object_force_types.h"
26 #include "DNA_object_types.h"
27 #include "DNA_particle_types.h"
28 #include "DNA_scene_types.h"
29 #include "DNA_texture_types.h"
30 
31 #include "BLI_blenlib.h"
32 #include "BLI_edgehash.h"
33 #include "BLI_kdopbvh.h"
34 #include "BLI_kdtree.h"
35 #include "BLI_linklist.h"
36 #include "BLI_math.h"
37 #include "BLI_rand.h"
38 #include "BLI_string_utils.h"
39 #include "BLI_task.h"
40 #include "BLI_threads.h"
41 #include "BLI_utildefines.h"
42 
43 #include "BKE_animsys.h"
44 #include "BKE_boids.h"
45 #include "BKE_collision.h"
46 #include "BKE_colortools.h"
47 #include "BKE_effect.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_lib_query.h"
51 #include "BKE_particle.h"
52 
53 #include "BKE_bvhutils.h"
54 #include "BKE_cloth.h"
55 #include "BKE_collection.h"
56 #include "BKE_lattice.h"
57 #include "BKE_material.h"
58 #include "BKE_mesh.h"
59 #include "BKE_modifier.h"
60 #include "BKE_object.h"
61 #include "BKE_pointcache.h"
62 #include "BKE_scene.h"
63 
64 #include "DEG_depsgraph.h"
65 #include "DEG_depsgraph_physics.h"
66 #include "DEG_depsgraph_query.h"
67 
68 #include "PIL_time.h"
69 
70 #include "RE_texture.h"
71 
72 /* FLUID sim particle import */
73 #ifdef WITH_FLUID
74 # include "DNA_fluid_types.h"
75 # include "manta_fluid_API.h"
76 #endif // WITH_FLUID
77 
79 
80 /************************************************/
81 /* Reacting to system events */
82 /************************************************/
83 
85 {
86  if (psys->pointcache->flag & PTCACHE_BAKED) {
87  return 0;
88  }
89 
90  if (psys->part->type == PART_HAIR) {
91  return psys->flag & PSYS_HAIR_DYNAMICS;
92  }
93 
95 }
96 
97 float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_render_params)
98 {
99  ParticleSettings *part = psys->part;
100 
101  if ((use_render_params &&
102  !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
103  (part->child_percent && part->childtype) || /* display percentage applies to children */
104  (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
105  {
106  return 1.0f;
107  }
108 
109  return psys->part->disp / 100.0f;
110 }
111 
112 static int tot_particles(ParticleSystem *psys, PTCacheID *pid)
113 {
114  if (pid && psys->pointcache->flag & PTCACHE_EXTERNAL) {
115  return pid->cache->totpoint;
116  }
117  if (psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) {
118  return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist;
119  }
120 
121  return psys->part->totpart - psys->totunexist;
122 }
123 
124 void psys_reset(ParticleSystem *psys, int mode)
125 {
126  PARTICLE_P;
127 
129  if (mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) {
130  /* don't free if not absolutely necessary */
131  if (psys->totpart != tot_particles(psys, NULL)) {
132  psys_free_particles(psys);
133  psys->totpart = 0;
134  }
135 
136  psys->totkeyed = 0;
137  psys->flag &= ~(PSYS_HAIR_DONE | PSYS_KEYED);
138 
139  if (psys->edit && psys->free_edit) {
140  psys->free_edit(psys->edit);
141  psys->edit = NULL;
142  psys->free_edit = NULL;
143  }
144  }
145  }
146  else if (mode == PSYS_RESET_CACHE_MISS) {
147  /* set all particles to be skipped */
149  {
150  pa->flag |= PARS_NO_DISP;
151  }
152  }
153 
154  /* reset children */
155  MEM_SAFE_FREE(psys->child);
156 
157  psys->totchild = 0;
158 
159  /* reset path cache */
160  psys_free_path_cache(psys, psys->edit);
161 
162  /* reset point cache */
164 
166 
167  psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
168 }
169 
170 void psys_unique_name(Object *object, ParticleSystem *psys, const char *defname)
171 {
173  psys,
174  defname,
175  '.',
176  offsetof(ParticleSystem, name),
177  sizeof(psys->name));
178 }
179 
180 static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
181 {
182  ParticleSystem *psys = sim->psys;
183  ParticleSettings *part = psys->part;
184  ParticleData *newpars = NULL;
185  BoidParticle *newboids = NULL;
186  PARTICLE_P;
187  int totpart, totsaved = 0;
188 
189  if (new_totpart < 0) {
190  if ((part->distr == PART_DISTR_GRID) && (part->from != PART_FROM_VERT)) {
191  totpart = part->grid_res;
192  totpart *= totpart * totpart;
193  }
194  else {
195  totpart = part->totpart;
196  }
197  }
198  else {
199  totpart = new_totpart;
200  }
201 
202  if (totpart != psys->totpart) {
203  if (psys->edit && psys->free_edit) {
204  psys->free_edit(psys->edit);
205  psys->edit = NULL;
206  psys->free_edit = NULL;
207  }
208 
209  if (totpart) {
210  newpars = MEM_callocN(totpart * sizeof(ParticleData), "particles");
211  if (newpars == NULL) {
212  return;
213  }
214 
215  if (psys->part->phystype == PART_PHYS_BOIDS) {
216  newboids = MEM_callocN(totpart * sizeof(BoidParticle), "boid particles");
217 
218  if (newboids == NULL) {
219  /* allocation error! */
220  if (newpars) {
221  MEM_freeN(newpars);
222  }
223  return;
224  }
225  }
226  }
227 
228  if (psys->particles) {
229  totsaved = MIN2(psys->totpart, totpart);
230  /* Save old pars. */
231  if (totsaved) {
232  memcpy(newpars, psys->particles, totsaved * sizeof(ParticleData));
233 
234  if (psys->particles->boid) {
235  memcpy(newboids, psys->particles->boid, totsaved * sizeof(BoidParticle));
236  }
237  }
238 
239  if (psys->particles->keys) {
240  MEM_freeN(psys->particles->keys);
241  }
242 
243  if (psys->particles->boid) {
244  MEM_freeN(psys->particles->boid);
245  }
246 
247  for (p = 0, pa = newpars; p < totsaved; p++, pa++) {
248  if (pa->keys) {
249  pa->keys = NULL;
250  pa->totkey = 0;
251  }
252  }
253 
254  for (p = totsaved, pa = psys->particles + totsaved; p < psys->totpart; p++, pa++) {
255  if (pa->hair) {
256  MEM_freeN(pa->hair);
257  }
258  }
259 
260  MEM_freeN(psys->particles);
261  psys_free_pdd(psys);
262  }
263 
264  psys->particles = newpars;
265  psys->totpart = totpart;
266 
267  if (newboids) {
269  {
270  pa->boid = newboids++;
271  }
272  }
273  }
274 
275  if (psys->child) {
276  MEM_freeN(psys->child);
277  psys->child = NULL;
278  psys->totchild = 0;
279  }
280 }
281 
282 int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params)
283 {
284  int child_num;
285 
286  if (!psys->part->childtype) {
287  return 0;
288  }
289 
290  if (use_render_params) {
291  child_num = psys->part->child_render_percent;
292  }
293  else {
294  child_num = psys->part->child_percent;
295  }
296 
297  return get_render_child_particle_number(&scene->r, child_num, use_render_params);
298 }
299 
300 int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params)
301 {
302  return psys->totpart * psys_get_child_number(scene, psys, use_render_params);
303 }
304 
305 /************************************************/
306 /* Distribution */
307 /************************************************/
308 
309 void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, ParticleSystem *psys)
310 {
311  /* use for building derived mesh mapping info:
312  *
313  * node: the allocated links - total derived mesh element count
314  * nodearray: the array of nodes aligned with the base mesh's elements, so
315  * each original elements can reference its derived elements
316  */
317  Mesh *me = (Mesh *)ob->data;
318  bool use_modifier_stack = psys->part->use_modifier_stack;
319  PARTICLE_P;
320 
321  /* CACHE LOCATIONS */
322  if (!mesh_final->runtime.deformed_only) {
323  /* Will use later to speed up subsurf/evaluated mesh. */
324  LinkNode *node, *nodedmelem, **nodearray;
325  int totdmelem, totelem, i;
326  const int *origindex;
327  const int *origindex_poly = NULL;
328  if (psys->part->from == PART_FROM_VERT) {
329  totdmelem = mesh_final->totvert;
330 
331  if (use_modifier_stack) {
332  totelem = totdmelem;
333  origindex = NULL;
334  }
335  else {
336  totelem = me->totvert;
337  origindex = CustomData_get_layer(&mesh_final->vdata, CD_ORIGINDEX);
338  }
339  }
340  else { /* FROM_FACE/FROM_VOLUME */
341  totdmelem = mesh_final->totface;
342 
343  if (use_modifier_stack) {
344  totelem = totdmelem;
345  origindex = NULL;
346  origindex_poly = NULL;
347  }
348  else {
349  totelem = mesh_original->totface;
350  origindex = CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX);
351 
352  /* for face lookups we need the poly origindex too */
353  origindex_poly = CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX);
354  if (origindex_poly == NULL) {
355  origindex = NULL;
356  }
357  }
358  }
359 
360  nodedmelem = MEM_callocN(sizeof(LinkNode) * totdmelem, "psys node elems");
361  nodearray = MEM_callocN(sizeof(LinkNode *) * totelem, "psys node array");
362 
363  for (i = 0, node = nodedmelem; i < totdmelem; i++, node++) {
364  int origindex_final;
365  node->link = POINTER_FROM_INT(i);
366 
367  /* may be vertex or face origindex */
368  if (use_modifier_stack) {
369  origindex_final = i;
370  }
371  else {
372  origindex_final = origindex ? origindex[i] : ORIGINDEX_NONE;
373 
374  /* if we have a poly source, do an index lookup */
375  if (origindex_poly && origindex_final != ORIGINDEX_NONE) {
376  origindex_final = origindex_poly[origindex_final];
377  }
378  }
379 
380  if (origindex_final != ORIGINDEX_NONE && origindex_final < totelem) {
381  if (nodearray[origindex_final]) {
382  /* prepend */
383  node->next = nodearray[origindex_final];
384  nodearray[origindex_final] = node;
385  }
386  else {
387  nodearray[origindex_final] = node;
388  }
389  }
390  }
391 
392  /* cache the verts/faces! */
394  {
395  if (pa->num < 0) {
396  pa->num_dmcache = DMCACHE_NOTFOUND;
397  continue;
398  }
399 
400  if (use_modifier_stack) {
401  if (pa->num < totelem) {
402  pa->num_dmcache = DMCACHE_ISCHILD;
403  }
404  else {
405  pa->num_dmcache = DMCACHE_NOTFOUND;
406  }
407  }
408  else {
409  if (psys->part->from == PART_FROM_VERT) {
410  if (pa->num < totelem && nodearray[pa->num]) {
411  pa->num_dmcache = POINTER_AS_INT(nodearray[pa->num]->link);
412  }
413  else {
414  pa->num_dmcache = DMCACHE_NOTFOUND;
415  }
416  }
417  else { /* FROM_FACE/FROM_VOLUME */
418  pa->num_dmcache = psys_particle_dm_face_lookup(
419  mesh_final, mesh_original, pa->num, pa->fuv, nodearray);
420  }
421  }
422  }
423 
424  MEM_freeN(nodearray);
425  MEM_freeN(nodedmelem);
426  }
427  else {
428  /* TODO_PARTICLE: make the following line unnecessary, each function
429  * should know to use the num or num_dmcache, set the num_dmcache to
430  * an invalid value, just in case. */
431 
433  {
434  pa->num_dmcache = DMCACHE_NOTFOUND;
435  }
436  }
437 }
438 
440 {
441  memset(ctx, 0, sizeof(ParticleThreadContext));
442  ctx->sim = *sim;
443  ctx->mesh = ctx->sim.psmd->mesh_final;
444  ctx->ma = BKE_object_material_get(sim->ob, sim->psys->part->omat);
445 }
446 
448  int startpart,
449  int endpart,
450  ParticleTask **r_tasks,
451  int *r_numtasks)
452 {
453  ParticleTask *tasks;
454  int numtasks = min_ii(BLI_system_thread_count() * 4, endpart - startpart);
455  int particles_per_task = numtasks > 0 ? (endpart - startpart) / numtasks : 0;
456  int remainder = numtasks > 0 ? (endpart - startpart) - particles_per_task * numtasks : 0;
457 
458  tasks = MEM_callocN(sizeof(ParticleTask) * numtasks, "ParticleThread");
459  *r_numtasks = numtasks;
460  *r_tasks = tasks;
461 
462  int p = startpart;
463  for (int i = 0; i < numtasks; i++) {
464  tasks[i].ctx = ctx;
465  tasks[i].begin = p;
466  p = p + particles_per_task + (i < remainder ? 1 : 0);
467  tasks[i].end = p;
468  }
469 
470  /* Verify that all particles are accounted for. */
471  if (numtasks > 0) {
472  BLI_assert(tasks[numtasks - 1].end == endpart);
473  }
474 }
475 
476 void psys_tasks_free(ParticleTask *tasks, int numtasks)
477 {
478  int i;
479 
480  /* threads */
481  for (i = 0; i < numtasks; i++) {
482  if (tasks[i].rng) {
483  BLI_rng_free(tasks[i].rng);
484  }
485  if (tasks[i].rng_path) {
486  BLI_rng_free(tasks[i].rng_path);
487  }
488  }
489 
490  MEM_freeN(tasks);
491 }
492 
494 {
495  /* path caching */
496  if (ctx->vg_length) {
497  MEM_freeN(ctx->vg_length);
498  }
499  if (ctx->vg_clump) {
500  MEM_freeN(ctx->vg_clump);
501  }
502  if (ctx->vg_kink) {
503  MEM_freeN(ctx->vg_kink);
504  }
505  if (ctx->vg_rough1) {
506  MEM_freeN(ctx->vg_rough1);
507  }
508  if (ctx->vg_rough2) {
509  MEM_freeN(ctx->vg_rough2);
510  }
511  if (ctx->vg_roughe) {
512  MEM_freeN(ctx->vg_roughe);
513  }
514  if (ctx->vg_twist) {
515  MEM_freeN(ctx->vg_twist);
516  }
517 
518  psys_sim_data_free(&ctx->sim);
519 
520  /* distribution */
521  if (ctx->jit) {
522  MEM_freeN(ctx->jit);
523  }
524  if (ctx->jitoff) {
525  MEM_freeN(ctx->jitoff);
526  }
527  if (ctx->weight) {
528  MEM_freeN(ctx->weight);
529  }
530  if (ctx->index) {
531  MEM_freeN(ctx->index);
532  }
533  if (ctx->seams) {
534  MEM_freeN(ctx->seams);
535  }
536  // if (ctx->vertpart) MEM_freeN(ctx->vertpart);
537  BLI_kdtree_3d_free(ctx->tree);
538 
539  if (ctx->clumpcurve != NULL) {
541  }
542  if (ctx->roughcurve != NULL) {
544  }
545  if (ctx->twistcurve != NULL) {
547  }
548 }
549 
551 {
552  ParticleSystem *psys = sim->psys;
553  ParticleSettings *part = psys->part;
554  ParticleTexture ptex;
555 
556  psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.0f);
557 
558  switch (part->type) {
559  case PART_EMITTER:
560  if (ptex.exist < psys_frand(psys, p + 125)) {
561  pa->flag |= PARS_UNEXIST;
562  }
563  pa->time = part->sta + (part->end - part->sta) * ptex.time;
564  break;
565  case PART_HAIR:
566  if (ptex.exist < psys_frand(psys, p + 125)) {
567  pa->flag |= PARS_UNEXIST;
568  }
569  pa->time = 0.0f;
570  break;
571  }
572 }
573 
575 {
576  ParticleSettings *part = sim->psys->part;
577  float birth_time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
578 
579  pa->flag &= ~PARS_UNEXIST;
580  pa->time = part->sta + (part->end - part->sta) * birth_time;
581 
582  pa->hair_index = 0;
583  /* We can't reset to -1 anymore since we've figured out correct index in #distribute_particles
584  * usage other than straight after distribute has to handle this index by itself - jahka. */
585  // pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we don't have a derived mesh face */
586 }
587 
589 {
590  ParticleSystem *psys = sim->psys;
591  ParticleSettings *part = psys->part;
592  /* Grid distributionsets UNEXIST flag, need to take care of
593  * it here because later this flag is being reset.
594  *
595  * We can't do it for any distribution, because it'll then
596  * conflict with texture influence, which does not free
597  * unexisting particles and only sets flag.
598  *
599  * It's not so bad, because only grid distribution sets
600  * UNEXIST flag.
601  */
602  const bool emit_from_volume_grid = (part->distr == PART_DISTR_GRID) &&
604  PARTICLE_P;
606  {
607  if (!(emit_from_volume_grid && (pa->flag & PARS_UNEXIST) != 0)) {
608  init_particle(sim, pa);
609  }
610  }
611 }
612 
614 {
615  ParticleSystem *psys = sim->psys;
616  PARTICLE_P;
617 
618  psys->totunexist = 0;
619 
621  {
622  if (pa->flag & PARS_UNEXIST) {
623  psys->totunexist++;
624  }
625  }
626 
627  if (psys->totpart && psys->totunexist == psys->totpart) {
628  if (psys->particles->boid) {
629  MEM_freeN(psys->particles->boid);
630  }
631 
632  MEM_freeN(psys->particles);
633  psys->particles = NULL;
634  psys->totpart = psys->totunexist = 0;
635  }
636 
637  if (psys->totunexist) {
638  int newtotpart = psys->totpart - psys->totunexist;
639  ParticleData *npa, *newpars;
640 
641  npa = newpars = MEM_callocN(newtotpart * sizeof(ParticleData), "particles");
642 
643  for (p = 0, pa = psys->particles; p < newtotpart; p++, pa++, npa++) {
644  while (pa->flag & PARS_UNEXIST) {
645  pa++;
646  }
647 
648  memcpy(npa, pa, sizeof(ParticleData));
649  }
650 
651  if (psys->particles->boid) {
652  MEM_freeN(psys->particles->boid);
653  }
654  MEM_freeN(psys->particles);
655  psys->particles = newpars;
656  psys->totpart -= psys->totunexist;
657 
658  if (psys->particles->boid) {
659  BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles");
660 
662  {
663  pa->boid = newboids++;
664  }
665  }
666  }
667 }
668 
669 static void get_angular_velocity_vector(short avemode, ParticleKey *state, float vec[3])
670 {
671  switch (avemode) {
672  case PART_AVE_VELOCITY:
673  copy_v3_v3(vec, state->vel);
674  break;
675  case PART_AVE_HORIZONTAL: {
676  float zvec[3];
677  zvec[0] = zvec[1] = 0;
678  zvec[2] = 1.0f;
679  cross_v3_v3v3(vec, state->vel, zvec);
680  break;
681  }
682  case PART_AVE_VERTICAL: {
683  float zvec[3], temp[3];
684  zvec[0] = zvec[1] = 0;
685  zvec[2] = 1.0f;
686  cross_v3_v3v3(temp, state->vel, zvec);
687  cross_v3_v3v3(vec, temp, state->vel);
688  break;
689  }
690  case PART_AVE_GLOBAL_X:
691  vec[0] = 1.0f;
692  vec[1] = vec[2] = 0;
693  break;
694  case PART_AVE_GLOBAL_Y:
695  vec[1] = 1.0f;
696  vec[0] = vec[2] = 0;
697  break;
698  case PART_AVE_GLOBAL_Z:
699  vec[2] = 1.0f;
700  vec[0] = vec[1] = 0;
701  break;
702  }
703 }
704 
706  ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
707 {
708  Object *ob = sim->ob;
709  ParticleSystem *psys = sim->psys;
710  ParticleSettings *part = psys->part;
711  ParticleTexture ptex;
712  float fac, phasefac, nor[3] = {0, 0, 0}, loc[3], vel[3] = {0.0, 0.0, 0.0}, rot[4], q2[4];
713  float r_vel[3], r_ave[3], r_rot[4], vec[3], p_vel[3] = {0.0, 0.0, 0.0};
714  float x_vec[3] = {1.0, 0.0, 0.0}, utan[3] = {0.0, 1.0, 0.0}, vtan[3] = {0.0, 0.0, 1.0},
715  rot_vec[3] = {0.0, 0.0, 0.0};
716  float q_phase[4];
717 
718  const bool use_boids = ((part->phystype == PART_PHYS_BOIDS) && (pa->boid != NULL));
719  const bool use_tangents = ((use_boids == false) &&
720  ((part->tanfac != 0.0f) || (part->rotmode == PART_ROT_NOR_TAN)));
721 
722  int p = pa - psys->particles;
723 
724  /* get birth location from object */
725  if (use_tangents) {
727  part->from,
728  pa->num,
729  pa->num_dmcache,
730  pa->fuv,
731  pa->foffset,
732  loc,
733  nor,
734  utan,
735  vtan,
736  0);
737  }
738  else {
740  sim->psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, nor, 0, 0, 0);
741  }
742 
743  /* get possible textural influence */
744  psys_get_texture(sim, pa, &ptex, PAMAP_IVEL, cfra);
745 
746  /* particles live in global space so */
747  /* let's convert: */
748  /* -location */
749  mul_m4_v3(ob->obmat, loc);
750 
751  /* -normal */
752  mul_mat3_m4_v3(ob->obmat, nor);
753  normalize_v3(nor);
754 
755  /* -tangent */
756  if (use_tangents) {
757 #if 0
758  float phase = vg_rot ?
759  2.0f *
760  (psys_particle_value_from_verts(sim->psmd->dm, part->from, pa, vg_rot) -
761  0.5f) :
762  0.0f;
763 #else
764  float phase = 0.0f;
765 #endif
766  mul_v3_fl(vtan, -cosf((float)M_PI * (part->tanphase + phase)));
767  fac = -sinf((float)M_PI * (part->tanphase + phase));
768  madd_v3_v3fl(vtan, utan, fac);
769 
770  mul_mat3_m4_v3(ob->obmat, vtan);
771 
772  copy_v3_v3(utan, nor);
773  mul_v3_fl(utan, dot_v3v3(vtan, nor));
774  sub_v3_v3(vtan, utan);
775 
776  normalize_v3(vtan);
777  }
778 
779  /* -velocity (boids need this even if there's no random velocity) */
780  if (part->randfac != 0.0f || (part->phystype == PART_PHYS_BOIDS && pa->boid)) {
781  r_vel[0] = 2.0f * (psys_frand(psys, p + 10) - 0.5f);
782  r_vel[1] = 2.0f * (psys_frand(psys, p + 11) - 0.5f);
783  r_vel[2] = 2.0f * (psys_frand(psys, p + 12) - 0.5f);
784 
785  mul_mat3_m4_v3(ob->obmat, r_vel);
786  normalize_v3(r_vel);
787  }
788 
789  /* -angular velocity */
790  if (part->avemode == PART_AVE_RAND) {
791  r_ave[0] = 2.0f * (psys_frand(psys, p + 13) - 0.5f);
792  r_ave[1] = 2.0f * (psys_frand(psys, p + 14) - 0.5f);
793  r_ave[2] = 2.0f * (psys_frand(psys, p + 15) - 0.5f);
794 
795  mul_mat3_m4_v3(ob->obmat, r_ave);
796  normalize_v3(r_ave);
797  }
798 
799  /* -rotation */
800  if (part->randrotfac != 0.0f) {
801  r_rot[0] = 2.0f * (psys_frand(psys, p + 16) - 0.5f);
802  r_rot[1] = 2.0f * (psys_frand(psys, p + 17) - 0.5f);
803  r_rot[2] = 2.0f * (psys_frand(psys, p + 18) - 0.5f);
804  r_rot[3] = 2.0f * (psys_frand(psys, p + 19) - 0.5f);
805  normalize_qt(r_rot);
806 
807  mat4_to_quat(rot, ob->obmat);
808  mul_qt_qtqt(r_rot, r_rot, rot);
809  }
810 
811  if (use_boids) {
812  float dvec[3], q[4], mat[3][3];
813 
814  copy_v3_v3(state->co, loc);
815 
816  /* boids don't get any initial velocity. */
817  zero_v3(state->vel);
818 
819  /* boids store direction in ave */
820  if (fabsf(nor[2]) == 1.0f) {
821  sub_v3_v3v3(state->ave, loc, ob->obmat[3]);
822  normalize_v3(state->ave);
823  }
824  else {
825  copy_v3_v3(state->ave, nor);
826  }
827 
828  /* calculate rotation matrix */
829  project_v3_v3v3(dvec, r_vel, state->ave);
830  sub_v3_v3v3(mat[0], state->ave, dvec);
831  normalize_v3(mat[0]);
832  negate_v3_v3(mat[2], r_vel);
833  normalize_v3(mat[2]);
834  cross_v3_v3v3(mat[1], mat[2], mat[0]);
835 
836  /* apply rotation */
837  mat3_to_quat_is_ok(q, mat);
838  copy_qt_qt(state->rot, q);
839  }
840  else {
841  /* conversion done so now we apply new: */
842  /* -velocity from: */
843 
844  /* *reactions */
845  if (dtime > 0.0f) {
846  sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel);
847  }
848 
849  /* *emitter velocity */
850  if (dtime != 0.0f && part->obfac != 0.0f) {
851  sub_v3_v3v3(vel, loc, state->co);
852  mul_v3_fl(vel, part->obfac / dtime);
853  }
854 
855  /* *emitter normal */
856  if (part->normfac != 0.0f) {
857  madd_v3_v3fl(vel, nor, part->normfac);
858  }
859 
860  /* *emitter tangent */
861  if (sim->psmd && part->tanfac != 0.0f) {
862  madd_v3_v3fl(vel, vtan, part->tanfac);
863  }
864 
865  /* *emitter object orientation */
866  if (part->ob_vel[0] != 0.0f) {
867  normalize_v3_v3(vec, ob->obmat[0]);
868  madd_v3_v3fl(vel, vec, part->ob_vel[0]);
869  }
870  if (part->ob_vel[1] != 0.0f) {
871  normalize_v3_v3(vec, ob->obmat[1]);
872  madd_v3_v3fl(vel, vec, part->ob_vel[1]);
873  }
874  if (part->ob_vel[2] != 0.0f) {
875  normalize_v3_v3(vec, ob->obmat[2]);
876  madd_v3_v3fl(vel, vec, part->ob_vel[2]);
877  }
878 
879  /* *texture */
880  /* TODO */
881 
882  /* *random */
883  if (part->randfac != 0.0f) {
884  madd_v3_v3fl(vel, r_vel, part->randfac);
885  }
886 
887  /* *particle */
888  if (part->partfac != 0.0f) {
889  madd_v3_v3fl(vel, p_vel, part->partfac);
890  }
891 
892  mul_v3_v3fl(state->vel, vel, ptex.ivel);
893 
894  /* -location from emitter */
895  copy_v3_v3(state->co, loc);
896 
897  /* -rotation */
898  unit_qt(state->rot);
899 
900  if (part->rotmode) {
901  bool use_global_space;
902 
903  /* create vector into which rotation is aligned */
904  switch (part->rotmode) {
905  case PART_ROT_NOR:
906  case PART_ROT_NOR_TAN:
907  copy_v3_v3(rot_vec, nor);
908  use_global_space = false;
909  break;
910  case PART_ROT_VEL:
911  copy_v3_v3(rot_vec, vel);
912  use_global_space = true;
913  break;
914  case PART_ROT_GLOB_X:
915  case PART_ROT_GLOB_Y:
916  case PART_ROT_GLOB_Z:
917  rot_vec[part->rotmode - PART_ROT_GLOB_X] = 1.0f;
918  use_global_space = true;
919  break;
920  case PART_ROT_OB_X:
921  case PART_ROT_OB_Y:
922  case PART_ROT_OB_Z:
923  copy_v3_v3(rot_vec, ob->obmat[part->rotmode - PART_ROT_OB_X]);
924  use_global_space = false;
925  break;
926  default:
927  use_global_space = true;
928  break;
929  }
930 
931  /* create rotation quat */
932 
933  if (use_global_space) {
934  negate_v3(rot_vec);
935  vec_to_quat(q2, rot_vec, OB_POSX, OB_POSZ);
936 
937  /* randomize rotation quat */
938  if (part->randrotfac != 0.0f) {
939  interp_qt_qtqt(rot, q2, r_rot, part->randrotfac);
940  }
941  else {
942  copy_qt_qt(rot, q2);
943  }
944  }
945  else {
946  /* calculate rotation in local-space */
947  float q_obmat[4];
948  float q_imat[4];
949 
950  mat4_to_quat(q_obmat, ob->obmat);
951  invert_qt_qt_normalized(q_imat, q_obmat);
952 
953  if (part->rotmode != PART_ROT_NOR_TAN) {
954  float rot_vec_local[3];
955 
956  /* rot_vec */
957  negate_v3(rot_vec);
958  copy_v3_v3(rot_vec_local, rot_vec);
959  mul_qt_v3(q_imat, rot_vec_local);
960  normalize_v3(rot_vec_local);
961 
962  vec_to_quat(q2, rot_vec_local, OB_POSX, OB_POSZ);
963  }
964  else {
965  /* (part->rotmode == PART_ROT_NOR_TAN) */
966  float tmat[3][3];
967 
968  /* NOTE: utan_local is not taken from 'utan', we calculate from rot_vec/vtan. */
969  /* NOTE(campbell): it looks like rotation phase may be applied twice
970  * (once with vtan, again below) however this isn't the case. */
971  float *rot_vec_local = tmat[0];
972  float *vtan_local = tmat[1];
973  float *utan_local = tmat[2];
974 
975  /* use tangents */
976  BLI_assert(use_tangents == true);
977 
978  /* rot_vec */
979  copy_v3_v3(rot_vec_local, rot_vec);
980  mul_qt_v3(q_imat, rot_vec_local);
981 
982  /* vtan_local */
983  copy_v3_v3(vtan_local, vtan); /* flips, can't use */
984  mul_qt_v3(q_imat, vtan_local);
985 
986  /* ensure orthogonal matrix (rot_vec aligned) */
987  cross_v3_v3v3(utan_local, vtan_local, rot_vec_local);
988  cross_v3_v3v3(vtan_local, utan_local, rot_vec_local);
989 
990  /* NOTE: no need to normalize. */
991  mat3_to_quat(q2, tmat);
992  }
993 
994  /* randomize rotation quat */
995  if (part->randrotfac != 0.0f) {
996  mul_qt_qtqt(r_rot, r_rot, q_imat);
997  interp_qt_qtqt(rot, q2, r_rot, part->randrotfac);
998  }
999  else {
1000  copy_qt_qt(rot, q2);
1001  }
1002 
1003  mul_qt_qtqt(rot, q_obmat, rot);
1004  }
1005 
1006  /* rotation phase */
1007  phasefac = part->phasefac;
1008  if (part->randphasefac != 0.0f) {
1009  phasefac += part->randphasefac * psys_frand(psys, p + 20);
1010  }
1011  axis_angle_to_quat(q_phase, x_vec, phasefac * (float)M_PI);
1012 
1013  /* combine base rotation & phase */
1014  mul_qt_qtqt(state->rot, rot, q_phase);
1015  }
1016 
1017  /* -angular velocity */
1018 
1019  zero_v3(state->ave);
1020 
1021  if (part->avemode) {
1022  if (part->avemode == PART_AVE_RAND) {
1023  copy_v3_v3(state->ave, r_ave);
1024  }
1025  else {
1027  }
1028 
1029  normalize_v3(state->ave);
1030  mul_v3_fl(state->ave, part->avefac);
1031  }
1032  }
1033 }
1034 
1035 /* recursively evaluate emitter parent anim at cfra */
1037  Scene *scene,
1038  Object *ob,
1039  float cfra)
1040 {
1041  if (ob->parent) {
1043  }
1044 
1046 }
1047 
1048 void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra)
1049 {
1050  ParticleSystem *psys = sim->psys;
1051  ParticleSettings *part;
1052  ParticleTexture ptex;
1053  int p = pa - psys->particles;
1054  part = psys->part;
1055 
1056  /* get precise emitter matrix if particle is born */
1057  if (part->type != PART_HAIR && dtime > 0.0f && pa->time < cfra && pa->time >= sim->psys->cfra) {
1058  evaluate_emitter_anim(sim->depsgraph, sim->scene, sim->ob, pa->time);
1059 
1060  psys->flag |= PSYS_OB_ANIM_RESTORE;
1061  }
1062 
1063  psys_get_birth_coords(sim, pa, &pa->state, dtime, cfra);
1064 
1065  /* Initialize particle settings which depends on texture.
1066  *
1067  * We could only do it now because we'll need to know coordinate
1068  * before sampling the texture.
1069  */
1070  init_particle_texture(sim, pa, p);
1071 
1072  if (part->phystype == PART_PHYS_BOIDS && pa->boid) {
1073  BoidParticle *bpa = pa->boid;
1074 
1075  /* and gravity in r_ve */
1076  bpa->gravity[0] = bpa->gravity[1] = 0.0f;
1077  bpa->gravity[2] = -1.0f;
1079  (sim->scene->physics_settings.gravity[2] != 0.0f)) {
1080  bpa->gravity[2] = sim->scene->physics_settings.gravity[2];
1081  }
1082 
1083  bpa->data.health = part->boids->health;
1084  bpa->data.mode = eBoidMode_InAir;
1085  bpa->data.state_id = ((BoidState *)part->boids->states.first)->id;
1086  bpa->data.acc[0] = bpa->data.acc[1] = bpa->data.acc[2] = 0.0f;
1087  }
1088 
1089  if (part->type == PART_HAIR) {
1090  pa->lifetime = 100.0f;
1091  }
1092  else {
1093  /* initialize the lifetime, in case the texture coordinates
1094  * are from Particles/Strands, which would cause undefined values
1095  */
1096  pa->lifetime = part->lifetime * (1.0f - part->randlife * psys_frand(psys, p + 21));
1097  pa->dietime = pa->time + pa->lifetime;
1098 
1099  /* get possible textural influence */
1100  psys_get_texture(sim, pa, &ptex, PAMAP_LIFE, cfra);
1101 
1102  pa->lifetime = part->lifetime * ptex.life;
1103 
1104  if (part->randlife != 0.0f) {
1105  pa->lifetime *= 1.0f - part->randlife * psys_frand(psys, p + 21);
1106  }
1107  }
1108 
1109  pa->dietime = pa->time + pa->lifetime;
1110 
1111  if ((sim->psys->pointcache) && (sim->psys->pointcache->flag & PTCACHE_BAKED) &&
1112  (sim->psys->pointcache->mem_cache.first)) {
1113  float dietime = psys_get_dietime_from_cache(sim->psys->pointcache, p);
1114  pa->dietime = MIN2(pa->dietime, dietime);
1115  }
1116 
1117  if (pa->time > cfra) {
1118  pa->alive = PARS_UNBORN;
1119  }
1120  else if (pa->dietime <= cfra) {
1121  pa->alive = PARS_DEAD;
1122  }
1123  else {
1124  pa->alive = PARS_ALIVE;
1125  }
1126 
1127  pa->state.time = cfra;
1128 }
1129 static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from)
1130 {
1131  ParticleData *pa;
1132  int p, totpart = sim->psys->totpart;
1133 
1134  for (p = from, pa = sim->psys->particles + from; p < totpart; p++, pa++) {
1135  reset_particle(sim, pa, dtime, cfra);
1136  }
1137 }
1138 
1139 /************************************************/
1140 /* Particle targets */
1141 /************************************************/
1142 
1144 {
1145  ParticleSystem *psys = NULL;
1146 
1147  if (ELEM(pt->ob, NULL, ob)) {
1148  psys = BLI_findlink(&ob->particlesystem, pt->psys - 1);
1149  }
1150  else {
1151  psys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1);
1152  }
1153 
1154  if (psys) {
1155  pt->flag |= PTARGET_VALID;
1156  }
1157  else {
1158  pt->flag &= ~PTARGET_VALID;
1159  }
1160 
1161  return psys;
1162 }
1163 
1164 /************************************************/
1165 /* Keyed particles */
1166 /************************************************/
1167 
1169 {
1170  ParticleSystem *psys = sim->psys, *kpsys;
1171  ParticleTarget *pt = psys->targets.first;
1172  int keys_valid = 1;
1173  psys->totkeyed = 0;
1174 
1175  for (; pt; pt = pt->next) {
1176  kpsys = psys_get_target_system(sim->ob, pt);
1177 
1178  if (kpsys && kpsys->totpart) {
1179  psys->totkeyed += keys_valid;
1180  if (psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f) {
1181  psys->totkeyed += 1;
1182  }
1183  }
1184  else {
1185  keys_valid = 0;
1186  }
1187  }
1188 
1189  psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops;
1190 }
1191 
1193 {
1194  ParticleSystem *psys = sim->psys;
1195  ParticleSimulationData ksim = {0};
1196  ParticleTarget *pt;
1197  PARTICLE_P;
1198  ParticleKey *key;
1199  int totpart = psys->totpart, k, totkeys = psys->totkeyed;
1200  int keyed_flag = 0;
1201 
1202  ksim.depsgraph = sim->depsgraph;
1203  ksim.scene = sim->scene;
1204 
1205  /* no proper targets so let's clear and bail out */
1206  if (psys->totkeyed == 0) {
1207  free_keyed_keys(psys);
1208  psys->flag &= ~PSYS_KEYED;
1209  return;
1210  }
1211 
1212  if (totpart && psys->particles->totkey != totkeys) {
1213  free_keyed_keys(psys);
1214 
1215  key = MEM_callocN(totpart * totkeys * sizeof(ParticleKey), "Keyed keys");
1216 
1218  {
1219  pa->keys = key;
1220  pa->totkey = totkeys;
1221  key += totkeys;
1222  }
1223  }
1224 
1225  psys->flag &= ~PSYS_KEYED;
1226 
1227  pt = psys->targets.first;
1228  for (k = 0; k < totkeys; k++) {
1229  ksim.ob = pt->ob ? pt->ob : sim->ob;
1230  ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1);
1231  keyed_flag = (ksim.psys->flag & PSYS_KEYED);
1232  ksim.psys->flag &= ~PSYS_KEYED;
1233 
1235  {
1236  key = pa->keys + k;
1237  key->time = -1.0; /* use current time */
1238 
1239  const int p_ksim = (ksim.psys->totpart) ? p % ksim.psys->totpart : 0;
1240  psys_get_particle_state(&ksim, p_ksim, key, 1);
1241 
1242  if (psys->flag & PSYS_KEYED_TIMING) {
1243  key->time = pa->time + pt->time;
1244  if (pt->duration != 0.0f && k + 1 < totkeys) {
1245  copy_particle_key(key + 1, key, 1);
1246  (key + 1)->time = pa->time + pt->time + pt->duration;
1247  }
1248  }
1249  else if (totkeys > 1) {
1250  key->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime;
1251  }
1252  else {
1253  key->time = pa->time;
1254  }
1255  }
1256 
1257  if (psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f) {
1258  k++;
1259  }
1260 
1261  ksim.psys->flag |= keyed_flag;
1262 
1263  pt = (pt->next && pt->next->flag & PTARGET_VALID) ? pt->next : psys->targets.first;
1264  }
1265 
1266  psys->flag |= PSYS_KEYED;
1267 }
1268 
1269 /************************************************/
1270 /* Point Cache */
1271 /************************************************/
1272 
1274 {
1275  PointCache *cache = psys->pointcache;
1276 
1277  if (cache->flag & PTCACHE_DISK_CACHE && BLI_listbase_is_empty(&cache->mem_cache)) {
1278  PTCacheID pid;
1279  BKE_ptcache_id_from_particles(&pid, ob, psys);
1280  cache->flag &= ~PTCACHE_DISK_CACHE;
1282  cache->flag |= PTCACHE_DISK_CACHE;
1283  }
1284 }
1286 {
1287  if (psys->pointcache->flag & PTCACHE_DISK_CACHE) {
1289  }
1290 }
1291 void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
1292 {
1293  ParticleSettings *part = psys->part;
1294 
1295  *sfra = max_ii(1, (int)part->sta);
1296  *efra = min_ii((int)(part->end + part->lifetime + 1.0f), max_ii(scene->r.pefra, scene->r.efra));
1297 }
1298 
1299 /* BVH tree balancing inside a mutex lock must be run in isolation. Balancing
1300  * is multithreaded, and we do not want the current thread to start another task
1301  * that may involve acquiring the same mutex lock that it is waiting for. */
1302 static void bvhtree_balance_isolated(void *userdata)
1303 {
1304  BLI_bvhtree_balance((BVHTree *)userdata);
1305 }
1306 
1307 /************************************************/
1308 /* Effectors */
1309 /************************************************/
1310 
1311 static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra)
1312 {
1313  if (psys) {
1314  PARTICLE_P;
1315  int totpart = 0;
1316  bool need_rebuild;
1317 
1319  need_rebuild = !psys->bvhtree || psys->bvhtree_frame != cfra;
1321 
1322  if (need_rebuild) {
1324  {
1325  totpart++;
1326  }
1327 
1329 
1330  BLI_bvhtree_free(psys->bvhtree);
1331  psys->bvhtree = BLI_bvhtree_new(totpart, 0.0, 4, 6);
1332 
1334  {
1335  if (pa->alive == PARS_ALIVE) {
1336  if (pa->state.time == cfra) {
1337  BLI_bvhtree_insert(psys->bvhtree, p, pa->prev_state.co, 1);
1338  }
1339  else {
1340  BLI_bvhtree_insert(psys->bvhtree, p, pa->state.co, 1);
1341  }
1342  }
1343  }
1344 
1346 
1347  psys->bvhtree_frame = cfra;
1348 
1350  }
1351  }
1352 }
1354 {
1355  if (psys) {
1356  PARTICLE_P;
1357  int totpart = 0;
1358 
1359  if (!psys->tree || psys->tree_frame != cfra) {
1361  {
1362  totpart++;
1363  }
1364 
1365  BLI_kdtree_3d_free(psys->tree);
1366  psys->tree = BLI_kdtree_3d_new(psys->totpart);
1367 
1369  {
1370  if (pa->alive == PARS_ALIVE) {
1371  if (pa->state.time == cfra) {
1372  BLI_kdtree_3d_insert(psys->tree, p, pa->prev_state.co);
1373  }
1374  else {
1375  BLI_kdtree_3d_insert(psys->tree, p, pa->state.co);
1376  }
1377  }
1378  }
1379  BLI_kdtree_3d_balance(psys->tree);
1380 
1381  psys->tree_frame = cfra;
1382  }
1383  }
1384 }
1385 
1387 {
1389  bool use_rotation = (sim->psys->part->flag & PART_ROT_DYN) != 0;
1391  sim->depsgraph, sim->ob, sim->psys, sim->psys->part->effector_weights, use_rotation);
1392  precalc_guides(sim, sim->psys->effectors);
1393 }
1394 
1396  ParticleSettings *part,
1397  ParticleData *pa,
1398  float dtime,
1399  float *external_acceleration,
1400  void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse),
1401  void *forcedata)
1402 {
1403 #define ZERO_F43 \
1404  { \
1405  {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, \
1406  { \
1407  0.0f, 0.0f, 0.0f \
1408  } \
1409  }
1410 
1411  ParticleKey states[5];
1412  float force[3], acceleration[3], impulse[3], dx[4][3] = ZERO_F43, dv[4][3] = ZERO_F43, oldpos[3];
1413  float pa_mass = (part->flag & PART_SIZEMASS) ? (part->mass * pa->size) : part->mass;
1414  int i, steps = 1;
1415  int integrator = part->integrator;
1416 
1417 #undef ZERO_F43
1418 
1419  copy_v3_v3(oldpos, pa->state.co);
1420 
1421  /* Verlet integration behaves strangely with moving emitters, so do first step with euler. */
1422  if (pa->prev_state.time < 0.0f && integrator == PART_INT_VERLET) {
1423  integrator = PART_INT_EULER;
1424  }
1425 
1426  switch (integrator) {
1427  case PART_INT_EULER:
1428  steps = 1;
1429  break;
1430  case PART_INT_MIDPOINT:
1431  steps = 2;
1432  break;
1433  case PART_INT_RK4:
1434  steps = 4;
1435  break;
1436  case PART_INT_VERLET:
1437  steps = 1;
1438  break;
1439  }
1440 
1441  for (i = 0; i < steps; i++) {
1442  copy_particle_key(states + i, &pa->state, 1);
1443  }
1444 
1445  states->time = 0.0f;
1446 
1447  for (i = 0; i < steps; i++) {
1448  zero_v3(force);
1449  zero_v3(impulse);
1450 
1451  force_func(forcedata, states + i, force, impulse);
1452 
1453  /* Force to acceleration. */
1454  mul_v3_v3fl(acceleration, force, 1.0f / pa_mass);
1455 
1456  if (external_acceleration) {
1457  add_v3_v3(acceleration, external_acceleration);
1458  }
1459 
1460  /* calculate next state */
1461  add_v3_v3(states[i].vel, impulse);
1462 
1463  switch (integrator) {
1464  case PART_INT_EULER:
1465  madd_v3_v3v3fl(pa->state.co, states->co, states->vel, dtime);
1466  madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime);
1467  break;
1468  case PART_INT_MIDPOINT:
1469  if (i == 0) {
1470  madd_v3_v3v3fl(states[1].co, states->co, states->vel, dtime * 0.5f);
1471  madd_v3_v3v3fl(states[1].vel, states->vel, acceleration, dtime * 0.5f);
1472  states[1].time = dtime * 0.5f;
1473  /*fra=sim->psys->cfra+0.5f*dfra;*/
1474  }
1475  else {
1476  madd_v3_v3v3fl(pa->state.co, states->co, states[1].vel, dtime);
1477  madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime);
1478  }
1479  break;
1480  case PART_INT_RK4:
1481  switch (i) {
1482  case 0:
1483  copy_v3_v3(dx[0], states->vel);
1484  mul_v3_fl(dx[0], dtime);
1485  copy_v3_v3(dv[0], acceleration);
1486  mul_v3_fl(dv[0], dtime);
1487 
1488  madd_v3_v3v3fl(states[1].co, states->co, dx[0], 0.5f);
1489  madd_v3_v3v3fl(states[1].vel, states->vel, dv[0], 0.5f);
1490  states[1].time = dtime * 0.5f;
1491  /*fra=sim->psys->cfra+0.5f*dfra;*/
1492  break;
1493  case 1:
1494  madd_v3_v3v3fl(dx[1], states->vel, dv[0], 0.5f);
1495  mul_v3_fl(dx[1], dtime);
1496  copy_v3_v3(dv[1], acceleration);
1497  mul_v3_fl(dv[1], dtime);
1498 
1499  madd_v3_v3v3fl(states[2].co, states->co, dx[1], 0.5f);
1500  madd_v3_v3v3fl(states[2].vel, states->vel, dv[1], 0.5f);
1501  states[2].time = dtime * 0.5f;
1502  break;
1503  case 2:
1504  madd_v3_v3v3fl(dx[2], states->vel, dv[1], 0.5f);
1505  mul_v3_fl(dx[2], dtime);
1506  copy_v3_v3(dv[2], acceleration);
1507  mul_v3_fl(dv[2], dtime);
1508 
1509  add_v3_v3v3(states[3].co, states->co, dx[2]);
1510  add_v3_v3v3(states[3].vel, states->vel, dv[2]);
1511  states[3].time = dtime;
1512  /*fra=cfra;*/
1513  break;
1514  case 3:
1515  add_v3_v3v3(dx[3], states->vel, dv[2]);
1516  mul_v3_fl(dx[3], dtime);
1517  copy_v3_v3(dv[3], acceleration);
1518  mul_v3_fl(dv[3], dtime);
1519 
1520  madd_v3_v3v3fl(pa->state.co, states->co, dx[0], 1.0f / 6.0f);
1521  madd_v3_v3fl(pa->state.co, dx[1], 1.0f / 3.0f);
1522  madd_v3_v3fl(pa->state.co, dx[2], 1.0f / 3.0f);
1523  madd_v3_v3fl(pa->state.co, dx[3], 1.0f / 6.0f);
1524 
1525  madd_v3_v3v3fl(pa->state.vel, states->vel, dv[0], 1.0f / 6.0f);
1526  madd_v3_v3fl(pa->state.vel, dv[1], 1.0f / 3.0f);
1527  madd_v3_v3fl(pa->state.vel, dv[2], 1.0f / 3.0f);
1528  madd_v3_v3fl(pa->state.vel, dv[3], 1.0f / 6.0f);
1529  }
1530  break;
1531  case PART_INT_VERLET: /* Verlet integration */
1532  madd_v3_v3v3fl(pa->state.vel, pa->prev_state.vel, acceleration, dtime);
1533  madd_v3_v3v3fl(pa->state.co, pa->prev_state.co, pa->state.vel, dtime);
1534 
1535  sub_v3_v3v3(pa->state.vel, pa->state.co, oldpos);
1536  mul_v3_fl(pa->state.vel, 1.0f / dtime);
1537  break;
1538  }
1539  }
1540 }
1541 
1542 /* -------------------------------------------------------------------- */
1558 #define PSYS_FLUID_SPRINGS_INITIAL_SIZE 256
1560 {
1561  /* Are more refs required? */
1562  if (psys->alloc_fluidsprings == 0 || psys->fluid_springs == NULL) {
1565  psys->alloc_fluidsprings * sizeof(ParticleSpring), "Particle Fluid Springs");
1566  }
1567  else if (psys->tot_fluidsprings == psys->alloc_fluidsprings) {
1568  /* Double the number of refs allocated */
1569  psys->alloc_fluidsprings *= 2;
1571  psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
1572  }
1573 
1574  memcpy(psys->fluid_springs + psys->tot_fluidsprings, spring, sizeof(ParticleSpring));
1575  psys->tot_fluidsprings++;
1576 
1577  return psys->fluid_springs + psys->tot_fluidsprings - 1;
1578 }
1579 static void sph_spring_delete(ParticleSystem *psys, int j)
1580 {
1581  if (j != psys->tot_fluidsprings - 1) {
1582  psys->fluid_springs[j] = psys->fluid_springs[psys->tot_fluidsprings - 1];
1583  }
1584 
1585  psys->tot_fluidsprings--;
1586 
1587  if (psys->tot_fluidsprings < psys->alloc_fluidsprings / 2 &&
1589  psys->alloc_fluidsprings /= 2;
1591  psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
1592  }
1593 }
1594 static void sph_springs_modify(ParticleSystem *psys, float dtime)
1595 {
1596  SPHFluidSettings *fluid = psys->part->fluid;
1597  ParticleData *pa1, *pa2;
1598  ParticleSpring *spring = psys->fluid_springs;
1599 
1600  float h, d, Rij[3], rij, Lij;
1601  int i;
1602 
1603  float yield_ratio = fluid->yield_ratio;
1604  float plasticity = fluid->plasticity_constant;
1605  /* scale things according to dtime */
1606  float timefix = 25.0f * dtime;
1607 
1608  if ((fluid->flag & SPH_VISCOELASTIC_SPRINGS) == 0 || fluid->spring_k == 0.0f) {
1609  return;
1610  }
1611 
1612  /* Loop through the springs */
1613  for (i = 0; i < psys->tot_fluidsprings; i++, spring++) {
1614  pa1 = psys->particles + spring->particle_index[0];
1615  pa2 = psys->particles + spring->particle_index[1];
1616 
1617  sub_v3_v3v3(Rij, pa2->prev_state.co, pa1->prev_state.co);
1618  rij = normalize_v3(Rij);
1619 
1620  /* adjust rest length */
1621  Lij = spring->rest_length;
1622  d = yield_ratio * timefix * Lij;
1623 
1624  if (rij > Lij + d) { /* Stretch */
1625  spring->rest_length += plasticity * (rij - Lij - d) * timefix;
1626  }
1627  else if (rij < Lij - d) { /* Compress */
1628  spring->rest_length -= plasticity * (Lij - d - rij) * timefix;
1629  }
1630 
1631  h = 4.0f * pa1->size;
1632 
1633  if (spring->rest_length > h) {
1634  spring->delete_flag = 1;
1635  }
1636  }
1637 
1638  /* Loop through springs backwaqrds - for efficient delete function */
1639  for (i = psys->tot_fluidsprings - 1; i >= 0; i--) {
1640  if (psys->fluid_springs[i].delete_flag) {
1641  sph_spring_delete(psys, i);
1642  }
1643  }
1644 }
1646 {
1647  EdgeHash *springhash = NULL;
1648  ParticleSpring *spring;
1649  int i = 0;
1650 
1651  springhash = BLI_edgehash_new_ex(__func__, psys->tot_fluidsprings);
1652 
1653  for (i = 0, spring = psys->fluid_springs; i < psys->tot_fluidsprings; i++, spring++) {
1655  springhash, spring->particle_index[0], spring->particle_index[1], POINTER_FROM_INT(i + 1));
1656  }
1657 
1658  return springhash;
1659 }
1660 
1661 #define SPH_NEIGHBORS 512
1662 typedef struct SPHNeighbor {
1664  int index;
1666 
1667 typedef struct SPHRangeData {
1670 
1671  float *data;
1672 
1675 
1676  float h;
1677  float mass;
1678  float massfac;
1681 
1683  ParticleSystem **psys,
1684  const float co[3],
1685  SPHRangeData *pfr,
1686  float interaction_radius,
1688 {
1689  int i;
1690 
1691  pfr->tot_neighbors = 0;
1692 
1693  for (i = 0; i < 10 && psys[i]; i++) {
1694  pfr->npsys = psys[i];
1695  pfr->massfac = psys[i]->part->mass / pfr->mass;
1696  pfr->use_size = psys[i]->part->flag & PART_SIZEMASS;
1697 
1698  if (tree) {
1699  BLI_bvhtree_range_query(tree, co, interaction_radius, callback, pfr);
1700  break;
1701  }
1702 
1704 
1705  BLI_bvhtree_range_query(psys[i]->bvhtree, co, interaction_radius, callback, pfr);
1706 
1708  }
1709 }
1710 static void sph_density_accum_cb(void *userdata, int index, const float co[3], float squared_dist)
1711 {
1712  SPHRangeData *pfr = (SPHRangeData *)userdata;
1713  ParticleData *npa = pfr->npsys->particles + index;
1714  float q;
1715  float dist;
1716 
1717  UNUSED_VARS(co);
1718 
1719  if (npa == pfr->pa || squared_dist < FLT_EPSILON) {
1720  return;
1721  }
1722 
1723  /* Ugh! One particle has too many neighbors! If some aren't taken into
1724  * account, the forces will be biased by the tree search order. This
1725  * effectively adds energy to the system, and results in a churning motion.
1726  * But, we have to stop somewhere, and it's not the end of the world.
1727  * - jahka and z0r
1728  */
1729  if (pfr->tot_neighbors >= SPH_NEIGHBORS) {
1730  return;
1731  }
1732 
1733  pfr->neighbors[pfr->tot_neighbors].index = index;
1734  pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
1735  pfr->tot_neighbors++;
1736 
1737  dist = sqrtf(squared_dist);
1738  q = (1.0f - dist / pfr->h) * pfr->massfac;
1739 
1740  if (pfr->use_size) {
1741  q *= npa->size;
1742  }
1743 
1744  pfr->data[0] += q * q;
1745  pfr->data[1] += q * q * q;
1746 }
1747 
1748 /*
1749  * Find the Courant number for an SPH particle (used for adaptive time step).
1750  */
1751 static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
1752 {
1753  ParticleData *pa, *npa;
1754  int i;
1755  float flow[3], offset[3], dist;
1756 
1757  zero_v3(flow);
1758 
1759  dist = 0.0f;
1760  if (pfr->tot_neighbors > 0) {
1761  pa = pfr->pa;
1762  for (i = 0; i < pfr->tot_neighbors; i++) {
1763  npa = pfr->neighbors[i].psys->particles + pfr->neighbors[i].index;
1765  dist += len_v3(offset);
1766  add_v3_v3(flow, npa->prev_state.vel);
1767  }
1768  dist += sphdata->psys[0]->part->fluid->radius; // TODO: remove this? - z0r
1769  sphdata->element_size = dist / pfr->tot_neighbors;
1770  mul_v3_v3fl(sphdata->flow, flow, 1.0f / pfr->tot_neighbors);
1771  }
1772  else {
1773  sphdata->element_size = FLT_MAX;
1774  copy_v3_v3(sphdata->flow, flow);
1775  }
1776 }
1777 static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
1778 {
1779  SPHData *sphdata = (SPHData *)sphdata_v;
1780  ParticleSystem **psys = sphdata->psys;
1781  ParticleData *pa = sphdata->pa;
1782  SPHFluidSettings *fluid = psys[0]->part->fluid;
1783  ParticleSpring *spring = NULL;
1784  SPHRangeData pfr;
1785  SPHNeighbor *pfn;
1786  float *gravity = sphdata->gravity;
1787  EdgeHash *springhash = sphdata->eh;
1788 
1789  float q, u, rij, dv[3];
1790  float pressure, near_pressure;
1791 
1792  float visc = fluid->viscosity_omega;
1793  float stiff_visc = fluid->viscosity_beta *
1794  (fluid->flag & SPH_FAC_VISCOSITY ? fluid->viscosity_omega : 1.0f);
1795 
1796  float inv_mass = 1.0f / sphdata->mass;
1797  float spring_constant = fluid->spring_k;
1798 
1799  /* 4.0 seems to be a pretty good value */
1800  float interaction_radius = fluid->radius *
1801  (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
1802  float h = interaction_radius * sphdata->hfac;
1803  /* 4.77 is an experimentally determined density factor */
1804  float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f);
1805  float rest_length = fluid->rest_length *
1806  (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.0f);
1807 
1808  float stiffness = fluid->stiffness_k;
1809  float stiffness_near_fac = fluid->stiffness_knear *
1810  (fluid->flag & SPH_FAC_REPULSION ? fluid->stiffness_k : 1.0f);
1811 
1812  ParticleData *npa;
1813  float vec[3];
1814  float vel[3];
1815  float co[3];
1816  float data[2];
1817  float density, near_density;
1818 
1819  int i, spring_index, index = pa - psys[0]->particles;
1820 
1821  data[0] = data[1] = 0;
1822  pfr.data = data;
1823  pfr.h = h;
1824  pfr.pa = pa;
1825  pfr.mass = sphdata->mass;
1826 
1827  sph_evaluate_func(NULL, psys, state->co, &pfr, interaction_radius, sph_density_accum_cb);
1828 
1829  density = data[0];
1830  near_density = data[1];
1831 
1832  pressure = stiffness * (density - rest_density);
1833  near_pressure = stiffness_near_fac * near_density;
1834 
1835  pfn = pfr.neighbors;
1836  for (i = 0; i < pfr.tot_neighbors; i++, pfn++) {
1837  npa = pfn->psys->particles + pfn->index;
1838 
1839  madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
1840 
1841  sub_v3_v3v3(vec, co, state->co);
1842  rij = normalize_v3(vec);
1843 
1844  q = (1.0f - rij / h) * pfn->psys->part->mass * inv_mass;
1845 
1846  if (pfn->psys->part->flag & PART_SIZEMASS) {
1847  q *= npa->size;
1848  }
1849 
1850  copy_v3_v3(vel, npa->prev_state.vel);
1851 
1852  /* Double Density Relaxation */
1853  madd_v3_v3fl(force, vec, -(pressure + near_pressure * q) * q);
1854 
1855  /* Viscosity */
1856  if (visc > 0.0f || stiff_visc > 0.0f) {
1857  sub_v3_v3v3(dv, vel, state->vel);
1858  u = dot_v3v3(vec, dv);
1859 
1860  if (u < 0.0f && visc > 0.0f) {
1861  madd_v3_v3fl(force, vec, 0.5f * q * visc * u);
1862  }
1863 
1864  if (u > 0.0f && stiff_visc > 0.0f) {
1865  madd_v3_v3fl(force, vec, 0.5f * q * stiff_visc * u);
1866  }
1867  }
1868 
1869  if (spring_constant > 0.0f) {
1870  /* Viscoelastic spring force */
1871  if (pfn->psys == psys[0] && fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash) {
1872  /* BLI_edgehash_lookup appears to be thread-safe. - z0r */
1873  spring_index = POINTER_AS_INT(BLI_edgehash_lookup(springhash, index, pfn->index));
1874 
1875  if (spring_index) {
1876  spring = psys[0]->fluid_springs + spring_index - 1;
1877 
1878  madd_v3_v3fl(force,
1879  vec,
1880  -10.0f * spring_constant * (1.0f - rij / h) * (spring->rest_length - rij));
1881  }
1882  else if (fluid->spring_frames == 0 ||
1883  (pa->prev_state.time - pa->time) <= fluid->spring_frames) {
1884  ParticleSpring temp_spring;
1885  temp_spring.particle_index[0] = index;
1886  temp_spring.particle_index[1] = pfn->index;
1887  temp_spring.rest_length = (fluid->flag & SPH_CURRENT_REST_LENGTH) ? rij : rest_length;
1888  temp_spring.delete_flag = 0;
1889 
1890  BLI_buffer_append(&sphdata->new_springs, ParticleSpring, temp_spring);
1891  }
1892  }
1893  else { /* PART_SPRING_HOOKES - Hooke's spring force */
1894  madd_v3_v3fl(
1895  force, vec, -10.0f * spring_constant * (1.0f - rij / h) * (rest_length - rij));
1896  }
1897  }
1898  }
1899 
1900  /* Artificial buoyancy force in negative gravity direction. */
1901  if (fluid->buoyancy > 0.0f && gravity) {
1902  madd_v3_v3fl(force, gravity, fluid->buoyancy * (density - rest_density));
1903  }
1904 
1905  if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF) {
1906  sph_particle_courant(sphdata, &pfr);
1907  }
1908  sphdata->pass++;
1909 }
1910 
1911 static void sphclassical_density_accum_cb(void *userdata,
1912  int index,
1913  const float co[3],
1914  float UNUSED(squared_dist))
1915 {
1916  SPHRangeData *pfr = (SPHRangeData *)userdata;
1917  ParticleData *npa = pfr->npsys->particles + index;
1918  float q;
1919  float qfac = 21.0f / (256.0f * (float)M_PI);
1920  float rij, rij_h;
1921  float vec[3];
1922 
1923  /* Exclude particles that are more than 2h away. Can't use squared_dist here
1924  * because it is not accurate enough. Use current state, i.e. the output of
1925  * basic_integrate() - z0r */
1926  sub_v3_v3v3(vec, npa->state.co, co);
1927  rij = len_v3(vec);
1928  rij_h = rij / pfr->h;
1929  if (rij_h > 2.0f) {
1930  return;
1931  }
1932 
1933  /* Smoothing factor. Utilize the Wendland kernel. gnuplot:
1934  * q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x)
1935  * plot [0:2] q1(x) */
1936  q = qfac / pow3f(pfr->h) * pow4f(2.0f - rij_h) * (1.0f + 2.0f * rij_h);
1937  q *= pfr->npsys->part->mass;
1938 
1939  if (pfr->use_size) {
1940  q *= pfr->pa->size;
1941  }
1942 
1943  pfr->data[0] += q;
1944  pfr->data[1] += q / npa->sphdensity;
1945 }
1946 
1947 static void sphclassical_neighbor_accum_cb(void *userdata,
1948  int index,
1949  const float co[3],
1950  float UNUSED(squared_dist))
1951 {
1952  SPHRangeData *pfr = (SPHRangeData *)userdata;
1953  ParticleData *npa = pfr->npsys->particles + index;
1954  float rij, rij_h;
1955  float vec[3];
1956 
1957  if (pfr->tot_neighbors >= SPH_NEIGHBORS) {
1958  return;
1959  }
1960 
1961  /* Exclude particles that are more than 2h away. Can't use squared_dist here
1962  * because it is not accurate enough. Use current state, i.e. the output of
1963  * basic_integrate() - z0r */
1964  sub_v3_v3v3(vec, npa->state.co, co);
1965  rij = len_v3(vec);
1966  rij_h = rij / pfr->h;
1967  if (rij_h > 2.0f) {
1968  return;
1969  }
1970 
1971  pfr->neighbors[pfr->tot_neighbors].index = index;
1972  pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
1973  pfr->tot_neighbors++;
1974 }
1975 static void sphclassical_force_cb(void *sphdata_v,
1976  ParticleKey *state,
1977  float *force,
1978  float *UNUSED(impulse))
1979 {
1980  SPHData *sphdata = (SPHData *)sphdata_v;
1981  ParticleSystem **psys = sphdata->psys;
1982  ParticleData *pa = sphdata->pa;
1983  SPHFluidSettings *fluid = psys[0]->part->fluid;
1984  SPHRangeData pfr;
1985  SPHNeighbor *pfn;
1986  float *gravity = sphdata->gravity;
1987 
1988  float dq, u, rij, dv[3];
1989  float pressure, npressure;
1990 
1991  float visc = fluid->viscosity_omega;
1992 
1993  float interaction_radius;
1994  float h, hinv;
1995  /* 4.77 is an experimentally determined density factor */
1996  float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f);
1997 
1998  /* Use speed of sound squared */
1999  float stiffness = pow2f(fluid->stiffness_k);
2000 
2001  ParticleData *npa;
2002  float vec[3];
2003  float co[3];
2004  float pressureTerm;
2005 
2006  int i;
2007 
2008  float qfac2 = 42.0f / (256.0f * (float)M_PI);
2009  float rij_h;
2010 
2011  /* 4.0 here is to be consistent with previous formulation/interface */
2012  interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
2013  h = interaction_radius * sphdata->hfac;
2014  hinv = 1.0f / h;
2015 
2016  pfr.h = h;
2017  pfr.pa = pa;
2018 
2020  NULL, psys, state->co, &pfr, interaction_radius, sphclassical_neighbor_accum_cb);
2021  pressure = stiffness * (pow7f(pa->sphdensity / rest_density) - 1.0f);
2022 
2023  /* multiply by mass so that we return a force, not accel */
2024  qfac2 *= sphdata->mass / pow3f(pfr.h);
2025 
2026  pfn = pfr.neighbors;
2027  for (i = 0; i < pfr.tot_neighbors; i++, pfn++) {
2028  npa = pfn->psys->particles + pfn->index;
2029  if (npa == pa) {
2030  /* we do not contribute to ourselves */
2031  continue;
2032  }
2033 
2034  /* Find vector to neighbor. Exclude particles that are more than 2h
2035  * away. Can't use current state here because it may have changed on
2036  * another thread - so do own mini integration. Unlike basic_integrate,
2037  * SPH integration depends on neighboring particles. - z0r */
2038  madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
2039  sub_v3_v3v3(vec, co, state->co);
2040  rij = normalize_v3(vec);
2041  rij_h = rij / pfr.h;
2042  if (rij_h > 2.0f) {
2043  continue;
2044  }
2045 
2046  npressure = stiffness * (pow7f(npa->sphdensity / rest_density) - 1.0f);
2047 
2048  /* First derivative of smoothing factor. Utilize the Wendland kernel.
2049  * gnuplot:
2050  * q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x)
2051  * plot [0:2] q2(x)
2052  * Particles > 2h away are excluded above. */
2053  dq = qfac2 * (2.0f * pow4f(2.0f - rij_h) - 4.0f * pow3f(2.0f - rij_h) * (1.0f + 2.0f * rij_h));
2054 
2055  if (pfn->psys->part->flag & PART_SIZEMASS) {
2056  dq *= npa->size;
2057  }
2058 
2059  pressureTerm = pressure / pow2f(pa->sphdensity) + npressure / pow2f(npa->sphdensity);
2060 
2061  /* Note that 'minus' is removed, because vec = vecBA, not vecAB.
2062  * This applies to the viscosity calculation below, too. */
2063  madd_v3_v3fl(force, vec, pressureTerm * dq);
2064 
2065  /* Viscosity */
2066  if (visc > 0.0f) {
2067  sub_v3_v3v3(dv, npa->prev_state.vel, pa->prev_state.vel);
2068  u = dot_v3v3(vec, dv);
2069  /* Apply parameters */
2070  u *= -dq * hinv * visc / (0.5f * npa->sphdensity + 0.5f * pa->sphdensity);
2071  madd_v3_v3fl(force, vec, u);
2072  }
2073  }
2074 
2075  /* Artificial buoyancy force in negative gravity direction. */
2076  if (fluid->buoyancy > 0.0f && gravity) {
2077  madd_v3_v3fl(force, gravity, fluid->buoyancy * (pa->sphdensity - rest_density));
2078  }
2079 
2080  if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF) {
2081  sph_particle_courant(sphdata, &pfr);
2082  }
2083  sphdata->pass++;
2084 }
2085 
2086 static void sphclassical_calc_dens(ParticleData *pa, float UNUSED(dfra), SPHData *sphdata)
2087 {
2088  ParticleSystem **psys = sphdata->psys;
2089  SPHFluidSettings *fluid = psys[0]->part->fluid;
2090  /* 4.0 seems to be a pretty good value */
2091  float interaction_radius = fluid->radius *
2092  (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
2093  SPHRangeData pfr;
2094  float data[2];
2095 
2096  data[0] = 0;
2097  data[1] = 0;
2098  pfr.data = data;
2099  pfr.h = interaction_radius * sphdata->hfac;
2100  pfr.pa = pa;
2101  pfr.mass = sphdata->mass;
2102 
2104  NULL, psys, pa->state.co, &pfr, interaction_radius, sphclassical_density_accum_cb);
2105  pa->sphdensity = min_ff(max_ff(data[0], fluid->rest_density * 0.9f), fluid->rest_density * 1.1f);
2106 }
2107 
2109 {
2110  ParticleTarget *pt;
2111  int i;
2112 
2114 
2115  /* Add other coupled particle systems. */
2116  sphdata->psys[0] = sim->psys;
2117  for (i = 1, pt = sim->psys->targets.first; i < 10; i++, pt = (pt ? pt->next : NULL)) {
2118  sphdata->psys[i] = pt ? psys_get_target_system(sim->ob, pt) : NULL;
2119  }
2120 
2121  if (psys_uses_gravity(sim)) {
2122  sphdata->gravity = sim->scene->physics_settings.gravity;
2123  }
2124  else {
2125  sphdata->gravity = NULL;
2126  }
2127  sphdata->eh = sph_springhash_build(sim->psys);
2128 
2129  /* These per-particle values should be overridden later, but just for
2130  * completeness we give them default values now. */
2131  sphdata->pa = NULL;
2132  sphdata->mass = 1.0f;
2133 
2134  if (sim->psys->part->fluid->solver == SPH_SOLVER_DDR) {
2135  sphdata->force_cb = sph_force_cb;
2136  sphdata->density_cb = sph_density_accum_cb;
2137  sphdata->hfac = 1.0f;
2138  }
2139  else {
2140  /* SPH_SOLVER_CLASSICAL */
2141  sphdata->force_cb = sphclassical_force_cb;
2143  sphdata->hfac = 0.5f;
2144  }
2145 }
2146 
2147 static void psys_sph_flush_springs(SPHData *sphdata)
2148 {
2149  for (int i = 0; i < sphdata->new_springs.count; i++) {
2150  /* sph_spring_add is not thread-safe. - z0r */
2151  sph_spring_add(sphdata->psys[0], &BLI_buffer_at(&sphdata->new_springs, ParticleSpring, i));
2152  }
2153 
2155 }
2156 
2158 {
2159  psys_sph_flush_springs(sphdata);
2160 
2161  if (sphdata->eh) {
2162  BLI_edgehash_free(sphdata->eh, NULL);
2163  sphdata->eh = NULL;
2164  }
2165 }
2166 
2167 void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2])
2168 {
2169  ParticleSystem **psys = sphdata->psys;
2170  SPHFluidSettings *fluid = psys[0]->part->fluid;
2171  /* 4.0 seems to be a pretty good value */
2172  float interaction_radius = fluid->radius *
2173  (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
2174  SPHRangeData pfr;
2175  float density[2];
2176 
2177  density[0] = density[1] = 0.0f;
2178  pfr.data = density;
2179  pfr.h = interaction_radius * sphdata->hfac;
2180  pfr.mass = sphdata->mass;
2181 
2182  sph_evaluate_func(tree, psys, co, &pfr, interaction_radius, sphdata->density_cb);
2183 
2184  vars[0] = pfr.data[0];
2185  vars[1] = pfr.data[1];
2186 }
2187 
2189  ParticleData *pa,
2190  float dfra,
2191  SPHData *sphdata)
2192 {
2193  ParticleSettings *part = sim->psys->part;
2194  // float timestep = psys_get_timestep(sim); /* UNUSED */
2195  float pa_mass = part->mass * ((part->flag & PART_SIZEMASS) ? pa->size : 1.0f);
2196  float dtime = dfra * psys_get_timestep(sim);
2197  // int steps = 1; // UNUSED
2198  float effector_acceleration[3];
2199 
2200  sphdata->pa = pa;
2201  sphdata->mass = pa_mass;
2202  sphdata->pass = 0;
2203  /* #sphdata.element_size and #sphdata.flow are set in the callback. */
2204 
2205  /* Restore previous state and treat gravity & effectors as external acceleration. */
2206  sub_v3_v3v3(effector_acceleration, pa->state.vel, pa->prev_state.vel);
2207  mul_v3_fl(effector_acceleration, 1.0f / dtime);
2208 
2209  copy_particle_key(&pa->state, &pa->prev_state, 0);
2210 
2211  integrate_particle(part, pa, dtime, effector_acceleration, sphdata->force_cb, sphdata);
2212 }
2213 
2216 /************************************************/
2217 /* Basic physics */
2218 /************************************************/
2219 
2220 typedef struct EfData {
2225 static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, float *impulse)
2226 {
2227  EfData *efdata = (EfData *)efdata_v;
2228  ParticleSimulationData *sim = efdata->sim;
2229  ParticleSettings *part = sim->psys->part;
2230  ParticleData *pa = efdata->pa;
2231  EffectedPoint epoint;
2232  RNG *rng = sim->rng;
2233 
2234  /* add effectors */
2235  pd_point_from_particle(efdata->sim, efdata->pa, state, &epoint);
2236  if (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR) {
2238  sim->colliders,
2239  part->effector_weights,
2240  &epoint,
2241  force,
2242  NULL,
2243  impulse);
2244  }
2245 
2246  mul_v3_fl(force, efdata->ptex.field);
2247  mul_v3_fl(impulse, efdata->ptex.field);
2248 
2249  /* calculate air-particle interaction */
2250  if (part->dragfac != 0.0f) {
2251  madd_v3_v3fl(force, state->vel, -part->dragfac * pa->size * pa->size * len_v3(state->vel));
2252  }
2253 
2254  /* brownian force */
2255  if (part->brownfac != 0.0f) {
2256  force[0] += (BLI_rng_get_float(rng) - 0.5f) * part->brownfac;
2257  force[1] += (BLI_rng_get_float(rng) - 0.5f) * part->brownfac;
2258  force[2] += (BLI_rng_get_float(rng) - 0.5f) * part->brownfac;
2259  }
2260 
2261  if (part->flag & PART_ROT_DYN && epoint.ave) {
2262  copy_v3_v3(pa->state.ave, epoint.ave);
2263  }
2264 }
2265 /* gathers all forces that effect particles and calculates a new state for the particle */
2266 static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, float cfra)
2267 {
2268  ParticleSettings *part = sim->psys->part;
2269  ParticleData *pa = sim->psys->particles + p;
2270  ParticleKey tkey;
2271  float dtime = dfra * psys_get_timestep(sim), time;
2272  float *gravity = NULL, gr[3];
2273  EfData efdata;
2274 
2275  psys_get_texture(sim, pa, &efdata.ptex, PAMAP_PHYSICS, cfra);
2276 
2277  efdata.pa = pa;
2278  efdata.sim = sim;
2279 
2280  /* add global acceleration (gravitation) */
2281  if (psys_uses_gravity(sim) &&
2282  /* normal gravity is too strong for hair so it's disabled by default */
2283  (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) {
2284  zero_v3(gr);
2285  madd_v3_v3fl(gr,
2287  part->effector_weights->global_gravity * efdata.ptex.gravity);
2288  gravity = gr;
2289  }
2290 
2291  /* maintain angular velocity */
2292  copy_v3_v3(pa->state.ave, pa->prev_state.ave);
2293 
2294  integrate_particle(part, pa, dtime, gravity, basic_force_cb, &efdata);
2295 
2296  /* damp affects final velocity */
2297  if (part->dampfac != 0.0f) {
2298  mul_v3_fl(pa->state.vel, 1.0f - part->dampfac * efdata.ptex.damp * 25.0f * dtime);
2299  }
2300 
2301  // copy_v3_v3(pa->state.ave, states->ave);
2302 
2303  /* finally we do guides */
2304  time = (cfra - pa->time) / pa->lifetime;
2305  CLAMP(time, 0.0f, 1.0f);
2306 
2307  copy_v3_v3(tkey.co, pa->state.co);
2308  copy_v3_v3(tkey.vel, pa->state.vel);
2309  tkey.time = pa->state.time;
2310 
2311  if (part->type != PART_HAIR) {
2312  if (do_guides(sim->depsgraph, sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
2313  copy_v3_v3(pa->state.co, tkey.co);
2314  /* guides don't produce valid velocity */
2315  sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co);
2316  mul_v3_fl(pa->state.vel, 1.0f / dtime);
2317  pa->state.time = tkey.time;
2318  }
2319  }
2320 }
2321 static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, float timestep)
2322 {
2323  float rotfac, rot1[4], rot2[4] = {1.0, 0.0, 0.0, 0.0}, dtime = dfra * timestep, extrotfac;
2324 
2325  if ((part->flag & PART_ROTATIONS) == 0) {
2326  unit_qt(pa->state.rot);
2327  return;
2328  }
2329 
2330  if (part->flag & PART_ROT_DYN) {
2331  extrotfac = len_v3(pa->state.ave);
2332  }
2333  else {
2334  extrotfac = 0.0f;
2335  }
2336 
2337  if ((part->flag & PART_ROT_DYN) &&
2339  float angle;
2340  float len1 = len_v3(pa->prev_state.vel);
2341  float len2 = len_v3(pa->state.vel);
2342  float vec[3];
2343 
2344  if (len1 == 0.0f || len2 == 0.0f) {
2345  zero_v3(pa->state.ave);
2346  }
2347  else {
2348  cross_v3_v3v3(pa->state.ave, pa->prev_state.vel, pa->state.vel);
2349  normalize_v3(pa->state.ave);
2350  angle = dot_v3v3(pa->prev_state.vel, pa->state.vel) / (len1 * len2);
2351  mul_v3_fl(pa->state.ave, saacos(angle) / dtime);
2352  }
2353 
2354  get_angular_velocity_vector(part->avemode, &pa->state, vec);
2355  axis_angle_to_quat(rot2, vec, dtime * part->avefac);
2356  }
2357 
2358  rotfac = len_v3(pa->state.ave);
2359  if (rotfac == 0.0f || (part->flag & PART_ROT_DYN) == 0 || extrotfac == 0.0f) {
2360  unit_qt(rot1);
2361  }
2362  else {
2363  axis_angle_to_quat(rot1, pa->state.ave, rotfac * dtime);
2364  }
2365  mul_qt_qtqt(pa->state.rot, rot1, pa->prev_state.rot);
2366  mul_qt_qtqt(pa->state.rot, rot2, pa->state.rot);
2367 
2368  /* keep rotation quat in good health */
2369  normalize_qt(pa->state.rot);
2370 }
2371 
2372 /************************************************
2373  * Collisions
2374  *
2375  * The algorithm is roughly:
2376  * 1. Use a BVH tree to search for faces that a particle may collide with.
2377  * 2. Use Newton's method to find the exact time at which the collision occurs.
2378  * https://en.wikipedia.org/wiki/Newton's_method
2379  *
2380  ************************************************/
2381 #define COLLISION_MIN_RADIUS 0.001f
2382 #define COLLISION_MIN_DISTANCE 0.0001f
2383 #define COLLISION_ZERO 0.00001f
2384 #define COLLISION_INIT_STEP 0.00008f
2385 typedef float (*NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor);
2386 static float nr_signed_distance_to_plane(float *p,
2387  float radius,
2389  float *nor)
2390 {
2391  float p0[3], e1[3], e2[3], d;
2392 
2393  sub_v3_v3v3(e1, pce->x1, pce->x0);
2394  sub_v3_v3v3(e2, pce->x2, pce->x0);
2395  sub_v3_v3v3(p0, p, pce->x0);
2396 
2397  cross_v3_v3v3(nor, e1, e2);
2398  normalize_v3(nor);
2399 
2400  d = dot_v3v3(p0, nor);
2401 
2402  if (pce->inv_nor == -1) {
2403  if (d < 0.0f) {
2404  pce->inv_nor = 1;
2405  }
2406  else {
2407  pce->inv_nor = 0;
2408  }
2409  }
2410 
2411  if (pce->inv_nor == 1) {
2412  negate_v3(nor);
2413  d = -d;
2414  }
2415 
2416  return d - radius;
2417 }
2418 static float nr_distance_to_edge(float *p,
2419  float radius,
2421  float *UNUSED(nor))
2422 {
2423  float v0[3], v1[3], v2[3], c[3];
2424 
2425  sub_v3_v3v3(v0, pce->x1, pce->x0);
2426  sub_v3_v3v3(v1, p, pce->x0);
2427  sub_v3_v3v3(v2, p, pce->x1);
2428 
2429  cross_v3_v3v3(c, v1, v2);
2430 
2431  return fabsf(len_v3(c) / len_v3(v0)) - radius;
2432 }
2433 static float nr_distance_to_vert(float *p,
2434  float radius,
2436  float *UNUSED(nor))
2437 {
2438  return len_v3v3(p, pce->x0) - radius;
2439 }
2441  float t,
2442  float fac,
2444 {
2445  /* t is the current time for newton rhapson */
2446  /* fac is the starting factor for current collision iteration */
2447  /* The col->fac's are factors for the particle subframe step start
2448  * and end during collision modifier step. */
2449  float f = fac + t * (1.0f - fac);
2450  float mul = col->fac1 + f * (col->fac2 - col->fac1);
2451  if (pce->tot > 0) {
2452  madd_v3_v3v3fl(pce->x0, pce->x[0], pce->v[0], mul);
2453 
2454  if (pce->tot > 1) {
2455  madd_v3_v3v3fl(pce->x1, pce->x[1], pce->v[1], mul);
2456 
2457  if (pce->tot > 2) {
2458  madd_v3_v3v3fl(pce->x2, pce->x[2], pce->v[2], mul);
2459  }
2460  }
2461  }
2462 }
2464 {
2465  float v[3];
2466 
2467  copy_v3_v3(pce->vel, pce->v[0]);
2468 
2469  if (pce->tot > 1) {
2470  sub_v3_v3v3(v, pce->v[1], pce->v[0]);
2471  madd_v3_v3fl(pce->vel, v, pce->uv[0]);
2472 
2473  if (pce->tot > 2) {
2474  sub_v3_v3v3(v, pce->v[2], pce->v[0]);
2475  madd_v3_v3fl(pce->vel, v, pce->uv[1]);
2476  }
2477  }
2478 }
2480  float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *nor)
2481 {
2482  if (fac >= 0.0f) {
2483  collision_interpolate_element(pce, 0.0f, fac, col);
2484  }
2485 
2486  switch (pce->tot) {
2487  case 1: {
2488  sub_v3_v3v3(nor, p, pce->x0);
2489  return normalize_v3(nor);
2490  }
2491  case 2: {
2492  float u, e[3], vec[3];
2493  sub_v3_v3v3(e, pce->x1, pce->x0);
2494  sub_v3_v3v3(vec, p, pce->x0);
2495  u = dot_v3v3(vec, e) / dot_v3v3(e, e);
2496 
2497  madd_v3_v3v3fl(nor, vec, e, -u);
2498  return normalize_v3(nor);
2499  }
2500  case 3:
2501  return nr_signed_distance_to_plane(p, 0.0f, pce, nor);
2502  }
2503  return 0;
2504 }
2506  const float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *co)
2507 {
2508  collision_interpolate_element(pce, 0.0f, fac, col);
2509 
2510  switch (pce->tot) {
2511  case 1: {
2512  sub_v3_v3v3(co, p, pce->x0);
2513  normalize_v3(co);
2514  madd_v3_v3v3fl(co, pce->x0, co, col->radius);
2515  break;
2516  }
2517  case 2: {
2518  float u, e[3], vec[3], nor[3];
2519  sub_v3_v3v3(e, pce->x1, pce->x0);
2520  sub_v3_v3v3(vec, p, pce->x0);
2521  u = dot_v3v3(vec, e) / dot_v3v3(e, e);
2522 
2523  madd_v3_v3v3fl(nor, vec, e, -u);
2524  normalize_v3(nor);
2525 
2526  madd_v3_v3v3fl(co, pce->x0, e, pce->uv[0]);
2527  madd_v3_v3fl(co, nor, col->radius);
2528  break;
2529  }
2530  case 3: {
2531  float p0[3], e1[3], e2[3], nor[3];
2532 
2533  sub_v3_v3v3(e1, pce->x1, pce->x0);
2534  sub_v3_v3v3(e2, pce->x2, pce->x0);
2535  sub_v3_v3v3(p0, p, pce->x0);
2536 
2537  cross_v3_v3v3(nor, e1, e2);
2538  normalize_v3(nor);
2539 
2540  if (pce->inv_nor == 1) {
2541  negate_v3(nor);
2542  }
2543 
2544  madd_v3_v3v3fl(co, pce->x0, nor, col->radius);
2545  madd_v3_v3fl(co, e1, pce->uv[0]);
2546  madd_v3_v3fl(co, e2, pce->uv[1]);
2547  break;
2548  }
2549  }
2550 }
2551 /* find first root in range [0-1] starting from 0 */
2553  float radius,
2555  NRDistanceFunc distance_func)
2556 {
2557  float t0, t1, dt_init, d0, d1, dd, n[3];
2558  int iter;
2559 
2560  pce->inv_nor = -1;
2561 
2562  if (col->inv_total_time > 0.0f) {
2563  /* Initial step size should be small, but not too small or floating point
2564  * precision errors will appear. - z0r */
2565  dt_init = COLLISION_INIT_STEP * col->inv_total_time;
2566  }
2567  else {
2568  dt_init = 0.001f;
2569  }
2570 
2571  /* start from the beginning */
2572  t0 = 0.0f;
2573  collision_interpolate_element(pce, t0, col->f, col);
2574  d0 = distance_func(col->co1, radius, pce, n);
2575  t1 = dt_init;
2576  d1 = 0.0f;
2577 
2578  for (iter = 0; iter < 10; iter++) { //, itersum++) {
2579  /* get current location */
2580  collision_interpolate_element(pce, t1, col->f, col);
2581  interp_v3_v3v3(pce->p, col->co1, col->co2, t1);
2582 
2583  d1 = distance_func(pce->p, radius, pce, n);
2584 
2585  /* particle already inside face, so report collision */
2586  if (iter == 0 && d0 < 0.0f && d0 > -radius) {
2587  copy_v3_v3(pce->p, col->co1);
2588  copy_v3_v3(pce->nor, n);
2589  pce->inside = 1;
2590  return 0.0f;
2591  }
2592 
2593  /* Zero gradient (no movement relative to element). Can't step from
2594  * here. */
2595  if (d1 == d0) {
2596  /* If first iteration, try from other end where the gradient may be
2597  * greater. NOTE: code duplicated below. */
2598  if (iter == 0) {
2599  t0 = 1.0f;
2600  collision_interpolate_element(pce, t0, col->f, col);
2601  d0 = distance_func(col->co2, radius, pce, n);
2602  t1 = 1.0f - dt_init;
2603  d1 = 0.0f;
2604  continue;
2605  }
2606 
2607  return -1.0f;
2608  }
2609 
2610  dd = (t1 - t0) / (d1 - d0);
2611 
2612  t0 = t1;
2613  d0 = d1;
2614 
2615  t1 -= d1 * dd;
2616 
2617  /* Particle moving away from plane could also mean a strangely rotating
2618  * face, so check from end. NOTE: code duplicated above. */
2619  if (iter == 0 && t1 < 0.0f) {
2620  t0 = 1.0f;
2621  collision_interpolate_element(pce, t0, col->f, col);
2622  d0 = distance_func(col->co2, radius, pce, n);
2623  t1 = 1.0f - dt_init;
2624  d1 = 0.0f;
2625  continue;
2626  }
2627  if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.0f)) {
2628  return -1.0f;
2629  }
2630 
2631  if (d1 <= COLLISION_ZERO && d1 >= -COLLISION_ZERO) {
2632  if (t1 >= -COLLISION_ZERO && t1 <= 1.0f) {
2633  if (distance_func == nr_signed_distance_to_plane) {
2634  copy_v3_v3(pce->nor, n);
2635  }
2636 
2637  CLAMP(t1, 0.0f, 1.0f);
2638 
2639  return t1;
2640  }
2641 
2642  return -1.0f;
2643  }
2644  }
2645  return -1.0;
2646 }
2648  float radius,
2650  float *t)
2651 {
2653  float ct, u, v;
2654 
2655  pce->inv_nor = -1;
2656  pce->inside = 0;
2657 
2659 
2660  if (ct >= 0.0f && ct < *t && (result->inside == 0 || pce->inside == 1)) {
2661  float e1[3], e2[3], p0[3];
2662  float e1e1, e1e2, e1p0, e2e2, e2p0, inv;
2663 
2664  sub_v3_v3v3(e1, pce->x1, pce->x0);
2665  sub_v3_v3v3(e2, pce->x2, pce->x0);
2666  /* XXX: add radius correction here? */
2667  sub_v3_v3v3(p0, pce->p, pce->x0);
2668 
2669  e1e1 = dot_v3v3(e1, e1);
2670  e1e2 = dot_v3v3(e1, e2);
2671  e1p0 = dot_v3v3(e1, p0);
2672  e2e2 = dot_v3v3(e2, e2);
2673  e2p0 = dot_v3v3(e2, p0);
2674 
2675  inv = 1.0f / (e1e1 * e2e2 - e1e2 * e1e2);
2676  u = (e2e2 * e1p0 - e1e2 * e2p0) * inv;
2677  v = (e1e1 * e2p0 - e1e2 * e1p0) * inv;
2678 
2679  if (u >= 0.0f && u <= 1.0f && v >= 0.0f && u + v <= 1.0f) {
2680  *result = *pce;
2681 
2682  /* normal already calculated in pce */
2683 
2684  result->uv[0] = u;
2685  result->uv[1] = v;
2686 
2687  *t = ct;
2688  return 1;
2689  }
2690  }
2691  return 0;
2692 }
2694  float radius,
2696  float *t)
2697 {
2698  ParticleCollisionElement edge[3], *cur = NULL, *hit = NULL;
2700 
2701  float ct;
2702  int i;
2703 
2704  for (i = 0; i < 3; i++) {
2705  cur = edge + i;
2706  cur->x[0] = pce->x[i];
2707  cur->x[1] = pce->x[(i + 1) % 3];
2708  cur->v[0] = pce->v[i];
2709  cur->v[1] = pce->v[(i + 1) % 3];
2710  cur->tot = 2;
2711  cur->inside = 0;
2712 
2713  ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_edge);
2714 
2715  if (ct >= 0.0f && ct < *t) {
2716  float u, e[3], vec[3];
2717 
2718  sub_v3_v3v3(e, cur->x1, cur->x0);
2719  sub_v3_v3v3(vec, cur->p, cur->x0);
2720  u = dot_v3v3(vec, e) / dot_v3v3(e, e);
2721 
2722  if (u < 0.0f || u > 1.0f) {
2723  break;
2724  }
2725 
2726  *result = *cur;
2727 
2728  madd_v3_v3v3fl(result->nor, vec, e, -u);
2729  normalize_v3(result->nor);
2730 
2731  result->uv[0] = u;
2732 
2733  hit = cur;
2734  *t = ct;
2735  }
2736  }
2737 
2738  return hit != NULL;
2739 }
2741  float radius,
2743  float *t)
2744 {
2745  ParticleCollisionElement vert[3], *cur = NULL, *hit = NULL;
2747 
2748  float ct;
2749  int i;
2750 
2751  for (i = 0; i < 3; i++) {
2752  cur = vert + i;
2753  cur->x[0] = pce->x[i];
2754  cur->v[0] = pce->v[i];
2755  cur->tot = 1;
2756  cur->inside = 0;
2757 
2758  ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_vert);
2759 
2760  if (ct >= 0.0f && ct < *t) {
2761  *result = *cur;
2762 
2763  sub_v3_v3v3(result->nor, cur->p, cur->x0);
2764  normalize_v3(result->nor);
2765 
2766  hit = cur;
2767  *t = ct;
2768  }
2769  }
2770 
2771  return hit != NULL;
2772 }
2774  int index,
2775  const BVHTreeRay *ray,
2776  BVHTreeRayHit *hit)
2777 {
2778  ParticleCollision *col = (ParticleCollision *)userdata;
2780  const MVertTri *vt = &col->md->tri[index];
2781  MVert *x = col->md->x;
2782  MVert *v = col->md->current_v;
2783  float t = hit->dist / col->original_ray_length;
2784  int collision = 0;
2785 
2786  pce.x[0] = x[vt->tri[0]].co;
2787  pce.x[1] = x[vt->tri[1]].co;
2788  pce.x[2] = x[vt->tri[2]].co;
2789 
2790  pce.v[0] = v[vt->tri[0]].co;
2791  pce.v[1] = v[vt->tri[1]].co;
2792  pce.v[2] = v[vt->tri[2]].co;
2793 
2794  pce.tot = 3;
2795  pce.inside = 0;
2796  pce.index = index;
2797 
2798  collision = collision_sphere_to_tri(col, ray->radius, &pce, &t);
2799  if (col->pce.inside == 0) {
2800  collision += collision_sphere_to_edges(col, ray->radius, &pce, &t);
2801  collision += collision_sphere_to_verts(col, ray->radius, &pce, &t);
2802  }
2803 
2804  if (collision) {
2805  hit->dist = col->original_ray_length * t;
2806  hit->index = index;
2807 
2809 
2810  col->hit = col->current;
2811  }
2812 }
2815  BVHTreeRayHit *hit,
2816  ListBase *colliders)
2817 {
2818  const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
2819  ColliderCache *coll;
2820  float ray_dir[3];
2821 
2822  if (BLI_listbase_is_empty(colliders)) {
2823  return 0;
2824  }
2825 
2826  sub_v3_v3v3(ray_dir, col->co2, col->co1);
2827  hit->index = -1;
2828  hit->dist = col->original_ray_length = normalize_v3(ray_dir);
2829  col->pce.inside = 0;
2830 
2831  /* even if particle is stationary we want to check for moving colliders */
2832  /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */
2833  if (hit->dist == 0.0f) {
2834  hit->dist = col->original_ray_length = 0.000001f;
2835  }
2836 
2837  for (coll = colliders->first; coll; coll = coll->next) {
2838  /* for boids: don't check with current ground object; also skip if permeated */
2839  bool skip = false;
2840 
2841  for (int i = 0; i < col->skip_count; i++) {
2842  if (coll->ob == col->skip[i]) {
2843  skip = true;
2844  break;
2845  }
2846  }
2847 
2848  if (skip) {
2849  continue;
2850  }
2851 
2852  /* particles should not collide with emitter at birth */
2853  if (coll->ob == col->emitter && pa->time < col->cfra && pa->time >= col->old_cfra) {
2854  continue;
2855  }
2856 
2857  col->current = coll->ob;
2858  col->md = coll->collmd;
2859  col->fac1 = (col->old_cfra - coll->collmd->time_x) /
2860  (coll->collmd->time_xnew - coll->collmd->time_x);
2861  col->fac2 = (col->cfra - coll->collmd->time_x) /
2862  (coll->collmd->time_xnew - coll->collmd->time_x);
2863 
2864  if (col->md && col->md->bvhtree) {
2865  BLI_bvhtree_ray_cast_ex(col->md->bvhtree,
2866  col->co1,
2867  ray_dir,
2868  col->radius,
2869  hit,
2871  col,
2872  raycast_flag);
2873  }
2874  }
2875 
2876  return hit->index >= 0;
2877 }
2879  ParticleData *pa,
2881  BVHTreeRayHit *hit,
2882  int kill,
2883  int dynamic_rotation)
2884 {
2885  ParticleCollisionElement *pce = &col->pce;
2886  PartDeflect *pd = col->hit->pd;
2887  RNG *rng = sim->rng;
2888  /* point of collision */
2889  float co[3];
2890  /* location factor of collision between this iteration */
2891  float x = hit->dist / col->original_ray_length;
2892  /* time factor of collision between timestep */
2893  float f = col->f + x * (1.0f - col->f);
2894  /* time since previous collision (in seconds) */
2895  float dt1 = (f - col->f) * col->total_time;
2896  /* time left after collision (in seconds) */
2897  float dt2 = (1.0f - f) * col->total_time;
2898  /* did particle pass through the collision surface? */
2899  int through = (BLI_rng_get_float(rng) < pd->pdef_perm) ? 1 : 0;
2900 
2901  /* calculate exact collision location */
2902  interp_v3_v3v3(co, col->co1, col->co2, x);
2903 
2904  /* particle dies in collision */
2905  if (through == 0 && (kill || pd->flag & PDEFLE_KILL_PART)) {
2906  pa->alive = PARS_DYING;
2907  pa->dietime = col->old_cfra + (col->cfra - col->old_cfra) * f;
2908 
2909  copy_v3_v3(pa->state.co, co);
2910  interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f);
2911  interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f);
2912  interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f);
2913 
2914  /* particle is dead so we don't need to calculate further */
2915  return 0;
2916  }
2917  /* figure out velocity and other data after collision */
2918 
2919  /* velocity directly before collision to be modified into velocity directly after collision */
2920  float v0[3];
2921  /* normal component of v0 */
2922  float v0_nor[3];
2923  /* tangential component of v0 */
2924  float v0_tan[3];
2925  /* tangential component of collision surface velocity */
2926  float vc_tan[3];
2927  float v0_dot, vc_dot;
2928  float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_rng_get_float(rng) - 0.5f);
2929  float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_rng_get_float(rng) - 0.5f);
2930  float distance, nor[3], dot;
2931 
2932  CLAMP(damp, 0.0f, 1.0f);
2933  CLAMP(frict, 0.0f, 1.0f);
2934 
2935  /* get exact velocity right before collision */
2936  madd_v3_v3v3fl(v0, col->ve1, col->acc, dt1);
2937 
2938  /* Convert collider velocity from `1/frame_step` to `1/s` TODO:
2939  * here we assume 1 frame step for collision modifier. */
2940  mul_v3_fl(pce->vel, col->inv_timestep);
2941 
2942  /* calculate tangential particle velocity */
2943  v0_dot = dot_v3v3(pce->nor, v0);
2944  madd_v3_v3v3fl(v0_tan, v0, pce->nor, -v0_dot);
2945 
2946  /* calculate tangential collider velocity */
2947  vc_dot = dot_v3v3(pce->nor, pce->vel);
2948  madd_v3_v3v3fl(vc_tan, pce->vel, pce->nor, -vc_dot);
2949 
2950  /* handle friction effects (tangential and angular velocity) */
2951  if (frict > 0.0f) {
2952  /* angular <-> linear velocity */
2953  if (dynamic_rotation) {
2954  float vr_tan[3], v1_tan[3], ave[3];
2955 
2956  /* linear velocity of particle surface */
2957  cross_v3_v3v3(vr_tan, pce->nor, pa->state.ave);
2958  mul_v3_fl(vr_tan, pa->size);
2959 
2960  /* change to coordinates that move with the collision plane */
2961  sub_v3_v3v3(v1_tan, v0_tan, vc_tan);
2962 
2963  /* The resulting velocity is a weighted average of particle cm & surface
2964  * velocity. This weight (related to particle's moment of inertia) could
2965  * be made a parameter for angular <-> linear conversion.
2966  */
2967  madd_v3_v3fl(v1_tan, vr_tan, -0.4);
2968  mul_v3_fl(v1_tan, 1.0f / 1.4f); /* 1/(1+0.4) */
2969 
2970  /* rolling friction is around 0.01 of sliding friction
2971  * (could be made a parameter) */
2972  mul_v3_fl(v1_tan, 1.0f - 0.01f * frict);
2973 
2974  /* surface_velocity is opposite to cm velocity */
2975  negate_v3_v3(vr_tan, v1_tan);
2976 
2977  /* get back to global coordinates */
2978  add_v3_v3(v1_tan, vc_tan);
2979 
2980  /* Convert to angular velocity. */
2981  cross_v3_v3v3(ave, vr_tan, pce->nor);
2982  mul_v3_fl(ave, 1.0f / MAX2(pa->size, 0.001f));
2983 
2984  /* only friction will cause change in linear & angular velocity */
2985  interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict);
2986  interp_v3_v3v3(v0_tan, v0_tan, v1_tan, frict);
2987  }
2988  else {
2989  /* just basic friction (unphysical due to the friction model used in Blender) */
2990  interp_v3_v3v3(v0_tan, v0_tan, vc_tan, frict);
2991  }
2992  }
2993 
2994  /* Stickiness was possibly added before,
2995  * so cancel that before calculating new normal velocity.
2996  * Otherwise particles go flying out of the surface
2997  * because of high reversed sticky velocity. */
2998  if (v0_dot < 0.0f) {
2999  v0_dot += pd->pdef_stickness;
3000  if (v0_dot > 0.0f) {
3001  v0_dot = 0.0f;
3002  }
3003  }
3004 
3005  /* damping and flipping of velocity around normal */
3006  v0_dot *= 1.0f - damp;
3007  vc_dot *= through ? damp : 1.0f;
3008 
3009  /* calculate normal particle velocity */
3010  /* special case for object hitting the particle from behind */
3011  if (through == 0 && ((vc_dot > 0.0f && v0_dot > 0.0f && vc_dot > v0_dot) ||
3012  (vc_dot < 0.0f && v0_dot < 0.0f && vc_dot < v0_dot))) {
3013  mul_v3_v3fl(v0_nor, pce->nor, vc_dot);
3014  }
3015  else if (v0_dot > 0.0f) {
3016  mul_v3_v3fl(v0_nor, pce->nor, vc_dot + v0_dot);
3017  }
3018  else {
3019  mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot);
3020  }
3021 
3022  /* combine components together again */
3023  add_v3_v3v3(v0, v0_nor, v0_tan);
3024 
3025  if (col->boid) {
3026  /* keep boids above ground */
3027  BoidParticle *bpa = pa->boid;
3028  if (bpa->data.mode == eBoidMode_OnLand || co[2] <= col->boid_z) {
3029  co[2] = col->boid_z;
3030  v0[2] = 0.0f;
3031  }
3032  }
3033 
3034  /* re-apply acceleration to final location and velocity */
3035  madd_v3_v3v3fl(pa->state.co, co, v0, dt2);
3036  madd_v3_v3fl(pa->state.co, col->acc, 0.5f * dt2 * dt2);
3037  madd_v3_v3v3fl(pa->state.vel, v0, col->acc, dt2);
3038 
3039  /* make sure particle stays on the right side of the surface */
3040  if (!through) {
3042 
3043  if (distance < col->radius + COLLISION_MIN_DISTANCE) {
3045  }
3046 
3047  dot = dot_v3v3(nor, v0);
3048  if (dot < 0.0f) {
3049  madd_v3_v3fl(v0, nor, -dot);
3050  }
3051 
3053 
3054  if (distance < col->radius + COLLISION_MIN_DISTANCE) {
3056  }
3057 
3058  dot = dot_v3v3(nor, pa->state.vel);
3059  if (dot < 0.0f) {
3060  madd_v3_v3fl(pa->state.vel, nor, -dot);
3061  }
3062  }
3063 
3064  /* add stickiness to surface */
3065  madd_v3_v3fl(pa->state.vel, pce->nor, -pd->pdef_stickness);
3066 
3067  /* set coordinates for next iteration */
3068  copy_v3_v3(col->co1, co);
3069  copy_v3_v3(col->co2, pa->state.co);
3070 
3071  copy_v3_v3(col->ve1, v0);
3072  copy_v3_v3(col->ve2, pa->state.vel);
3073 
3074  col->f = f;
3075 
3076  /* if permeability random roll succeeded, disable collider for this sim step */
3077  if (through) {
3078  col->skip[col->skip_count++] = col->hit;
3079  }
3080 
3081  return 1;
3082 }
3084 {
3085  /* final chance to prevent total failure, so stick to the surface and hope for the best */
3086  collision_point_on_surface(col->co1, &col->pce, 1.0f, col, pa->state.co);
3087 
3088  copy_v3_v3(pa->state.vel, col->pce.vel);
3089  mul_v3_fl(pa->state.vel, col->inv_timestep);
3090 
3091  // printf("max iterations\n");
3092 }
3093 
3094 /* Particle - Mesh collision detection and response
3095  * Features:
3096  * -friction and damping
3097  * -angular momentum <-> linear momentum
3098  * -high accuracy by re-applying particle acceleration after collision
3099  * -handles moving, rotating and deforming meshes
3100  * -uses Newton-Rhapson iteration to find the collisions
3101  * -handles spherical particles and (nearly) point like particles
3102  */
3103 static void collision_check(ParticleSimulationData *sim, int p, float dfra, float cfra)
3104 {
3105  ParticleSettings *part = sim->psys->part;
3106  ParticleData *pa = sim->psys->particles + p;
3108  BVHTreeRayHit hit;
3109  int collision_count = 0;
3110 
3111  float timestep = psys_get_timestep(sim);
3112 
3113  memset(&col, 0, sizeof(ParticleCollision));
3114 
3115  col.total_time = timestep * dfra;
3116  col.inv_total_time = 1.0f / col.total_time;
3117  col.inv_timestep = 1.0f / timestep;
3118 
3119  col.cfra = cfra;
3120  col.old_cfra = sim->psys->cfra;
3121 
3122  /* Get acceleration (from gravity, force-fields etc. to be re-applied in collision response). */
3123  sub_v3_v3v3(col.acc, pa->state.vel, pa->prev_state.vel);
3124  mul_v3_fl(col.acc, 1.0f / col.total_time);
3125 
3126  /* set values for first iteration */
3127  copy_v3_v3(col.co1, pa->prev_state.co);
3128  copy_v3_v3(col.co2, pa->state.co);
3129  copy_v3_v3(col.ve1, pa->prev_state.vel);
3130  copy_v3_v3(col.ve2, pa->state.vel);
3131  col.f = 0.0f;
3132 
3133  col.radius = ((part->flag & PART_SIZE_DEFL) || (part->phystype == PART_PHYS_BOIDS)) ?
3134  pa->size :
3136 
3137  /* override for boids */
3138  if (part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) {
3139  col.boid = 1;
3140  col.boid_z = pa->state.co[2];
3141  col.skip[col.skip_count++] = pa->boid->ground;
3142  }
3143 
3144  /* 10 iterations to catch multiple collisions */
3145  while (collision_count < PARTICLE_COLLISION_MAX_COLLISIONS) {
3146  if (collision_detect(pa, &col, &hit, sim->colliders)) {
3147 
3148  collision_count++;
3149 
3150  if (collision_count == PARTICLE_COLLISION_MAX_COLLISIONS) {
3151  collision_fail(pa, &col);
3152  }
3153  else if (collision_response(
3154  sim, pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN) ==
3155  0) {
3156  return;
3157  }
3158  }
3159  else {
3160  return;
3161  }
3162  }
3163 }
3164 
3165 /************************************************/
3166 /* Hair */
3167 /************************************************/
3168 
3173  float cfra,
3174  const bool use_render_params)
3175 {
3176  ParticleSystem *psys = sim->psys;
3177  ParticleSettings *part = psys->part;
3179  int distr = 0, alloc = 0, skip = 0;
3180 
3181  if ((psys->part->childtype &&
3182  psys->totchild != psys_get_tot_child(sim->scene, psys, use_render_params)) ||
3183  psys->recalc & ID_RECALC_PSYS_RESET) {
3184  alloc = 1;
3185  }
3186 
3187  if (alloc || psys->recalc & ID_RECALC_PSYS_CHILD ||
3188  (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT))) {
3189  distr = 1;
3190  }
3191 
3192  if (distr) {
3193  if (alloc) {
3194  realloc_particles(sim, sim->psys->totpart);
3195  }
3196 
3197  if (psys_get_tot_child(sim->scene, psys, use_render_params)) {
3198  /* don't generate children while computing the hair keys */
3199  if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
3201 
3202  if (part->childtype == PART_CHILD_FACES && part->parents != 0.0f) {
3203  psys_find_parents(sim, use_render_params);
3204  }
3205  }
3206  }
3207  else {
3208  psys_free_children(psys);
3209  }
3210  }
3211 
3212  if ((part->type == PART_HAIR || psys->flag & PSYS_KEYED ||
3213  psys->pointcache->flag & PTCACHE_BAKED) == 0) {
3214  skip = 1; /* only hair, keyed and baked stuff can have paths */
3215  }
3216  else if (part->ren_as != PART_DRAW_PATH &&
3217  !(part->type == PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))) {
3218  skip = 1; /* particle visualization must be set as path */
3219  }
3220  else if (DEG_get_mode(sim->depsgraph) != DAG_EVAL_RENDER) {
3221  if (part->draw_as != PART_DRAW_REND) {
3222  skip = 1; /* draw visualization */
3223  }
3224  else if (psys->pointcache->flag & PTCACHE_BAKING) {
3225  skip = 1; /* no need to cache paths while baking dynamics */
3226  }
3227  else if (psys_in_edit_mode(sim->depsgraph, psys)) {
3228  if ((pset->flag & PE_DRAW_PART) == 0) {
3229  skip = 1;
3230  }
3231  else if (part->childtype == 0 &&
3232  (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) == 0) {
3233  skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */
3234  }
3235  }
3236  }
3237 
3238  if (!skip) {
3239  psys_cache_paths(sim, cfra, use_render_params);
3240 
3241  /* for render, child particle paths are computed on the fly */
3242  if (part->childtype) {
3243  if (!psys->totchild) {
3244  skip = 1;
3245  }
3246  else if (psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE) == 0) {
3247  skip = 1;
3248  }
3249 
3250  if (!skip) {
3251  psys_cache_child_paths(sim, cfra, 0, use_render_params);
3252  }
3253  }
3254  }
3255  else if (psys->pathcache) {
3256  psys_free_path_cache(psys, NULL);
3257  }
3258 }
3259 
3260 static bool psys_hair_use_simulation(ParticleData *pa, float max_length)
3261 {
3262  /* Minimum segment length relative to average length.
3263  * Hairs with segments below this length will be excluded from the simulation,
3264  * because otherwise the solver will become unstable.
3265  * The hair system should always make sure the hair segments have reasonable length ratios,
3266  * but this can happen in old files when e.g. cutting hair.
3267  */
3268  const float min_length = 0.1f * max_length;
3269 
3270  HairKey *key;
3271  int k;
3272 
3273  if (pa->totkey < 2) {
3274  return false;
3275  }
3276 
3277  for (k = 1, key = pa->hair + 1; k < pa->totkey; k++, key++) {
3278  float length = len_v3v3(key->co, (key - 1)->co);
3279  if (length < min_length) {
3280  return false;
3281  }
3282  }
3283 
3284  return true;
3285 }
3286 
3287 static MDeformVert *hair_set_pinning(MDeformVert *dvert, float weight)
3288 {
3289  if (dvert) {
3290  if (!dvert->totweight) {
3291  dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight");
3292  dvert->totweight = 1;
3293  }
3294 
3295  dvert->dw->weight = weight;
3296  dvert++;
3297  }
3298  return dvert;
3299 }
3300 
3302  int totpoint,
3303  int totedge,
3304  Mesh **r_mesh)
3305 {
3306  ParticleSystem *psys = sim->psys;
3307  ParticleSettings *part = psys->part;
3308  Mesh *mesh;
3309  MVert *mvert;
3310  MEdge *medge;
3311  MDeformVert *dvert;
3312  HairKey *key;
3313  PARTICLE_P;
3314  int k, hair_index;
3315  float hairmat[4][4];
3316  float max_length;
3317  float hair_radius;
3318 
3319  mesh = *r_mesh;
3320  if (!mesh) {
3321  *r_mesh = mesh = BKE_mesh_new_nomain(totpoint, totedge, 0, 0, 0);
3324  }
3325  mvert = mesh->mvert;
3326  medge = mesh->medge;
3327  dvert = mesh->dvert;
3328 
3329  if (psys->clmd->hairdata == NULL) {
3330  psys->clmd->hairdata = MEM_mallocN(sizeof(ClothHairData) * totpoint, "hair data");
3331  }
3332 
3333  /* calculate maximum segment length */
3334  max_length = 0.0f;
3336  {
3337  if (!(pa->flag & PARS_UNEXIST)) {
3338  for (k = 1, key = pa->hair + 1; k < pa->totkey; k++, key++) {
3339  float length = len_v3v3(key->co, (key - 1)->co);
3340  if (max_length < length) {
3341  max_length = length;
3342  }
3343  }
3344  }
3345  }
3346 
3347  psys->clmd->sim_parms->vgroup_mass = 1;
3348 
3349  /* XXX placeholder for more flexible future hair settings */
3350  hair_radius = part->size;
3351 
3352  /* Make vgroup for pin roots etc. */
3353  hair_index = 1;
3355  {
3356  if (!(pa->flag & PARS_UNEXIST)) {
3357  float root_mat[4][4];
3358  float bending_stiffness;
3359  bool use_hair;
3360 
3361  pa->hair_index = hair_index;
3362  use_hair = psys_hair_use_simulation(pa, max_length);
3363 
3364  psys_mat_hair_to_object(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
3365  mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
3366  normalize_m4(root_mat);
3367 
3368  bending_stiffness = CLAMPIS(
3369  1.0f - part->bending_random * psys_frand(psys, p + 666), 0.0f, 1.0f);
3370 
3371  for (k = 0, key = pa->hair; k < pa->totkey; k++, key++) {
3372  ClothHairData *hair;
3373  float *co, *co_next;
3374 
3375  co = key->co;
3376  co_next = (key + 1)->co;
3377 
3378  /* create fake root before actual root to resist bending */
3379  if (k == 0) {
3380  hair = &psys->clmd->hairdata[pa->hair_index - 1];
3381  copy_v3_v3(hair->loc, root_mat[3]);
3382  copy_m3_m4(hair->rot, root_mat);
3383 
3384  hair->radius = hair_radius;
3385  hair->bending_stiffness = bending_stiffness;
3386 
3387  add_v3_v3v3(mvert->co, co, co);
3388  sub_v3_v3(mvert->co, co_next);
3389  mul_m4_v3(hairmat, mvert->co);
3390 
3391  medge->v1 = pa->hair_index - 1;
3392  medge->v2 = pa->hair_index;
3393 
3394  dvert = hair_set_pinning(dvert, 1.0f);
3395 
3396  mvert++;
3397  medge++;
3398  }
3399 
3400  /* store root transform in cloth data */
3401  hair = &psys->clmd->hairdata[pa->hair_index + k];
3402  copy_v3_v3(hair->loc, root_mat[3]);
3403  copy_m3_m4(hair->rot, root_mat);
3404 
3405  hair->radius = hair_radius;
3406  hair->bending_stiffness = bending_stiffness;
3407 
3408  copy_v3_v3(mvert->co, co);
3409  mul_m4_v3(hairmat, mvert->co);
3410 
3411  if (k) {
3412  medge->v1 = pa->hair_index + k - 1;
3413  medge->v2 = pa->hair_index + k;
3414  }
3415 
3416  /* roots and disabled hairs should be 1.0, the rest can be anything from 0.0 to 1.0 */
3417  if (use_hair) {
3418  dvert = hair_set_pinning(dvert, key->weight);
3419  }
3420  else {
3421  dvert = hair_set_pinning(dvert, 1.0f);
3422  }
3423 
3424  mvert++;
3425  if (k) {
3426  medge++;
3427  }
3428  }
3429 
3430  hair_index += pa->totkey + 1;
3431  }
3432  }
3433 }
3434 
3436 {
3437  ParticleSystem *psys = sim->psys;
3438  PARTICLE_P;
3439  EffectorWeights *clmd_effweights;
3440  int totpoint;
3441  int totedge;
3442  float(*deformedVerts)[3];
3443  bool realloc_roots;
3444 
3445  if (!psys->clmd) {
3447  psys->clmd->sim_parms->goalspring = 0.0f;
3450  }
3451 
3452  /* count simulated points */
3453  totpoint = 0;
3454  totedge = 0;
3456  {
3457  if (!(pa->flag & PARS_UNEXIST)) {
3458  /* "out" dm contains all hairs */
3459  totedge += pa->totkey;
3460  totpoint += pa->totkey + 1; /* +1 for virtual root point */
3461  }
3462  }
3463 
3464  /* whether hair root info array has to be reallocated */
3465  realloc_roots = false;
3466  if (psys->hair_in_mesh) {
3467  Mesh *mesh = psys->hair_in_mesh;
3468  if (totpoint != mesh->totvert || totedge != mesh->totedge) {
3469  BKE_id_free(NULL, mesh);
3470  psys->hair_in_mesh = NULL;
3471  realloc_roots = true;
3472  }
3473  }
3474 
3475  if (!psys->hair_in_mesh || !psys->clmd->hairdata || realloc_roots) {
3476  if (psys->clmd->hairdata) {
3477  MEM_freeN(psys->clmd->hairdata);
3478  psys->clmd->hairdata = NULL;
3479  }
3480  }
3481 
3482  hair_create_input_mesh(sim, totpoint, totedge, &psys->hair_in_mesh);
3483 
3484  if (psys->hair_out_mesh) {
3485  BKE_id_free(NULL, psys->hair_out_mesh);
3486  }
3487 
3488  psys->clmd->point_cache = psys->pointcache;
3489  /* for hair sim we replace the internal cloth effector weights temporarily
3490  * to use the particle settings
3491  */
3492  clmd_effweights = psys->clmd->sim_parms->effector_weights;
3494 
3496  deformedVerts = BKE_mesh_vert_coords_alloc(psys->hair_out_mesh, NULL);
3498  psys->clmd, sim->depsgraph, sim->scene, sim->ob, psys->hair_in_mesh, deformedVerts);
3499  BKE_mesh_vert_coords_apply(psys->hair_out_mesh, deformedVerts);
3500 
3501  MEM_freeN(deformedVerts);
3502 
3503  /* restore cloth effector weights */
3504  psys->clmd->sim_parms->effector_weights = clmd_effweights;
3505 }
3506 static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
3507 {
3508  ParticleSystem *psys = sim->psys;
3509  ParticleSettings *part = psys->part;
3510  PARTICLE_P;
3511  float disp = psys_get_current_display_percentage(psys, use_render_params);
3512 
3514  {
3515  pa->size = part->size;
3516  if (part->randsize > 0.0f) {
3517  pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
3518  }
3519 
3520  if (psys_frand(psys, p) > disp) {
3521  pa->flag |= PARS_NO_DISP;
3522  }
3523  else {
3524  pa->flag &= ~PARS_NO_DISP;
3525  }
3526  }
3527 
3528  if (psys->recalc & ID_RECALC_PSYS_RESET) {
3529  /* need this for changing subsurf levels */
3530  psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_original, psys);
3531 
3532  if (psys->clmd) {
3533  cloth_free_modifier(psys->clmd);
3534  }
3535  }
3536 
3537  /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles T25519. */
3538  if (psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS && psys->particles) {
3539  do_hair_dynamics(sim);
3540  }
3541 
3542  /* following lines were removed r29079 but cause bug T22811, see report for details */
3543  psys_update_effectors(sim);
3544  psys_update_path_cache(sim, cfra, use_render_params);
3545 
3546  psys->flag |= PSYS_HAIR_UPDATED;
3547 }
3548 
3549 static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
3550 {
3551  Object *ob = sim->ob;
3552  ParticleSystem *psys = sim->psys;
3553  HairKey *key, *root;
3554  PARTICLE_P;
3555 
3556  invert_m4_m4(ob->imat, ob->obmat);
3557 
3558  if (psys->totpart == 0) {
3559  return;
3560  }
3561 
3562  psys_sim_data_init(sim);
3563 
3564  /* save new keys for elements if needed */
3566  {
3567  /* first time alloc */
3568  if (pa->totkey == 0 || pa->hair == NULL) {
3569  pa->hair = MEM_callocN((psys->part->hair_step + 1) * sizeof(HairKey), "HairKeys");
3570  pa->totkey = 0;
3571  }
3572 
3573  key = root = pa->hair;
3574  key += pa->totkey;
3575 
3576  /* convert from global to geometry space */
3577  copy_v3_v3(key->co, pa->state.co);
3578  mul_m4_v3(ob->imat, key->co);
3579 
3580  if (pa->totkey) {
3581  sub_v3_v3(key->co, root->co);
3582  psys_vec_rot_to_face(sim->psmd->mesh_final, pa, key->co);
3583  }
3584 
3585  key->time = pa->state.time;
3586 
3587  key->weight = 1.0f - key->time / 100.0f;
3588 
3589  pa->totkey++;
3590 
3591  /* Root is always in the origin of hair space
3592  * so we set it to be so after the last key is saved. */
3593  if (pa->totkey == psys->part->hair_step + 1) {
3594  zero_v3(root->co);
3595  }
3596  }
3597 
3598  psys_sim_data_free(sim);
3599 }
3600 
3601 /* Code for an adaptive time step based on the Courant-Friedrichs-Lewy
3602  * condition. */
3603 static const float MIN_TIMESTEP = 1.0f / 101.0f;
3604 /* Tolerance of 1.5 means the last subframe neither favors growing nor
3605  * shrinking (e.g if it were 1.3, the last subframe would tend to be too
3606  * small). */
3607 static const float TIMESTEP_EXPANSION_FACTOR = 0.1f;
3608 static const float TIMESTEP_EXPANSION_TOLERANCE = 1.5f;
3609 
3610 /* Calculate the speed of the particle relative to the local scale of the
3611  * simulation. This should be called once per particle during a simulation
3612  * step, after the velocity has been updated. element_size defines the scale of
3613  * the simulation, and is typically the distance to neighboring particles. */
3615  ParticleSimulationData *sim, ParticleData *pa, float dtime, SPHData *sphdata, SpinLock *spin)
3616 {
3617  float relative_vel[3];
3618 
3619  sub_v3_v3v3(relative_vel, pa->prev_state.vel, sphdata->flow);
3620 
3621  const float courant_num = len_v3(relative_vel) * dtime / sphdata->element_size;
3622  if (sim->courant_num < courant_num) {
3624  if (sim->courant_num < courant_num) {
3625  sim->courant_num = courant_num;
3626  }
3628  }
3629 }
3631 {
3632  return 1.0f / (float)(part->subframes + 1);
3633 }
3634 /* Update time step size to suit current conditions. */
3636 {
3637  float dt_target;
3638  if (sim->courant_num == 0.0f) {
3639  dt_target = 1.0f;
3640  }
3641  else {
3642  dt_target = psys->dt_frac * (psys->part->courant_target / sim->courant_num);
3643  }
3644 
3645  /* Make sure the time step is reasonable. For some reason, the CLAMP macro
3646  * doesn't work here. The time step becomes too large. - z0r */
3647  if (dt_target < MIN_TIMESTEP) {
3648  dt_target = MIN_TIMESTEP;
3649  }
3650  else if (dt_target > get_base_time_step(psys->part)) {
3651  dt_target = get_base_time_step(psys->part);
3652  }
3653 
3654  /* Decrease time step instantly, but increase slowly. */
3655  if (dt_target > psys->dt_frac) {
3656  psys->dt_frac = interpf(dt_target, psys->dt_frac, TIMESTEP_EXPANSION_FACTOR);
3657  }
3658  else {
3659  psys->dt_frac = dt_target;
3660  }
3661 }
3662 
3663 static float sync_timestep(ParticleSystem *psys, float t_frac)
3664 {
3665  /* Sync with frame end if it's close. */
3666  if (t_frac == 1.0f) {
3667  return psys->dt_frac;
3668  }
3669  if (t_frac + (psys->dt_frac * TIMESTEP_EXPANSION_TOLERANCE) >= 1.0f) {
3670  return 1.0f - t_frac;
3671  }
3672 
3673  return psys->dt_frac;
3674 }
3675 
3676 /************************************************/
3677 /* System Core */
3678 /************************************************/
3679 
3682 
3683  float cfra;
3684  float timestep;
3685  float dtime;
3686 
3689 
3690 static void dynamics_step_sphdata_reduce(const void *__restrict UNUSED(userdata),
3691  void *__restrict join_v,
3692  void *__restrict chunk_v)
3693 {
3694  SPHData *sphdata_to = join_v;
3695  SPHData *sphdata_from = chunk_v;
3696 
3697  if (sphdata_from->new_springs.count > 0) {
3698  BLI_buffer_append_array(&sphdata_to->new_springs,
3700  &BLI_buffer_at(&sphdata_from->new_springs, ParticleSpring, 0),
3701  sphdata_from->new_springs.count);
3702  }
3703 
3704  BLI_buffer_field_free(&sphdata_from->new_springs);
3705 }
3706 
3707 static void dynamics_step_sph_ddr_task_cb_ex(void *__restrict userdata,
3708  const int p,
3709  const TaskParallelTLS *__restrict tls)
3710 {
3711  DynamicStepSolverTaskData *data = userdata;
3712  ParticleSimulationData *sim = data->sim;
3713  ParticleSystem *psys = sim->psys;
3714  ParticleSettings *part = psys->part;
3715 
3716  SPHData *sphdata = tls->userdata_chunk;
3717 
3718  ParticleData *pa;
3719 
3720  if ((pa = psys->particles + p)->state.time <= 0.0f) {
3721  return;
3722  }
3723 
3724  /* do global forces & effectors */
3725  basic_integrate(sim, p, pa->state.time, data->cfra);
3726 
3727  /* actual fluids calculations */
3728  sph_integrate(sim, pa, pa->state.time, sphdata);
3729 
3730  if (sim->colliders) {
3731  collision_check(sim, p, pa->state.time, data->cfra);
3732  }
3733 
3734  /* SPH particles are not physical particles, just interpolation
3735  * particles, thus rotation has not a direct sense for them */
3736  basic_rotate(part, pa, pa->state.time, data->timestep);
3737 
3738  if (part->time_flag & PART_TIME_AUTOSF) {
3739  update_courant_num(sim, pa, data->dtime, sphdata, &data->spin);
3740  }
3741 }
3742 
3744  void *__restrict userdata, const int p, const TaskParallelTLS *__restrict UNUSED(tls))
3745 {
3746  DynamicStepSolverTaskData *data = userdata;
3747  ParticleSimulationData *sim = data->sim;
3748  ParticleSystem *psys = sim->psys;
3749 
3750  ParticleData *pa;
3751 
3752  if ((pa = psys->particles + p)->state.time <= 0.0f) {
3753  return;
3754  }
3755 
3756  basic_integrate(sim, p, pa->state.time, data->cfra);
3757 }
3758 
3760  void *__restrict userdata, const int p, const TaskParallelTLS *__restrict tls)
3761 {
3762  DynamicStepSolverTaskData *data = userdata;
3763  ParticleSimulationData *sim = data->sim;
3764  ParticleSystem *psys = sim->psys;
3765 
3766  SPHData *sphdata = tls->userdata_chunk;
3767 
3768  ParticleData *pa;
3769 
3770  if ((pa = psys->particles + p)->state.time <= 0.0f) {
3771  return;
3772  }
3773 
3774  sphclassical_calc_dens(pa, pa->state.time, sphdata);
3775 }
3776 
3777 static void dynamics_step_sph_classical_integrate_task_cb_ex(void *__restrict userdata,
3778  const int p,
3779  const TaskParallelTLS *__restrict tls)
3780 {
3781  DynamicStepSolverTaskData *data = userdata;
3782  ParticleSimulationData *sim = data->sim;
3783  ParticleSystem *psys = sim->psys;
3784  ParticleSettings *part = psys->part;
3785 
3786  SPHData *sphdata = tls->userdata_chunk;
3787 
3788  ParticleData *pa;
3789 
3790  if ((pa = psys->particles + p)->state.time <= 0.0f) {
3791  return;
3792  }
3793 
3794  /* actual fluids calculations */
3795  sph_integrate(sim, pa, pa->state.time, sphdata);
3796 
3797  if (sim->colliders) {
3798  collision_check(sim, p, pa->state.time, data->cfra);
3799  }
3800 
3801  /* SPH particles are not physical particles, just interpolation
3802  * particles, thus rotation has not a direct sense for them */
3803  basic_rotate(part, pa, pa->state.time, data->timestep);
3804 
3805  if (part->time_flag & PART_TIME_AUTOSF) {
3806  update_courant_num(sim, pa, data->dtime, sphdata, &data->spin);
3807  }
3808 }
3809 
3810 /* unbaked particles are calculated dynamically */
3811 static void dynamics_step(ParticleSimulationData *sim, float cfra)
3812 {
3813  ParticleSystem *psys = sim->psys;
3814  ParticleSettings *part = psys->part;
3815  BoidBrainData bbd;
3816  ParticleTexture ptex;
3817  PARTICLE_P;
3818  float timestep;
3819  /* frame & time changes */
3820  float dfra, dtime;
3821  float birthtime, dietime;
3822 
3823  /* where have we gone in time since last time */
3824  dfra = cfra - psys->cfra;
3825 
3826  timestep = psys_get_timestep(sim);
3827  dtime = dfra * timestep;
3828 
3829  if (dfra < 0.0f) {
3831  {
3832  psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
3833  pa->size = part->size * ptex.size;
3834  if (part->randsize > 0.0f) {
3835  pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
3836  }
3837 
3838  reset_particle(sim, pa, dtime, cfra);
3839  }
3840  return;
3841  }
3842 
3843  /* for now do both, boids us 'rng' */
3844  sim->rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed);
3845 
3846  psys_update_effectors(sim);
3847 
3848  if (part->type != PART_HAIR) {
3850  }
3851 
3852  /* initialize physics type specific stuff */
3853  switch (part->phystype) {
3854  case PART_PHYS_BOIDS: {
3855  ParticleTarget *pt = psys->targets.first;
3856  bbd.sim = sim;
3857  bbd.part = part;
3858  bbd.cfra = cfra;
3859  bbd.dfra = dfra;
3860  bbd.timestep = timestep;
3861  bbd.rng = sim->rng;
3862 
3863  psys_update_particle_tree(psys, cfra);
3864 
3865  boids_precalc_rules(part, cfra);
3866 
3867  for (; pt; pt = pt->next) {
3868  ParticleSystem *psys_target = psys_get_target_system(sim->ob, pt);
3869  if (psys_target && psys_target != psys) {
3870  psys_update_particle_tree(psys_target, cfra);
3871  }
3872  }
3873  break;
3874  }
3875  case PART_PHYS_FLUID: {
3876  ParticleTarget *pt = psys->targets.first;
3877  psys_update_particle_bvhtree(psys, cfra);
3878 
3879  for (; pt;
3880  pt = pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */
3881  if (pt->ob) {
3883  }
3884  }
3885  break;
3886  }
3887  }
3888  /* initialize all particles for dynamics */
3890  {
3891  copy_particle_key(&pa->prev_state, &pa->state, 1);
3892 
3893  psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
3894 
3895  pa->size = part->size * ptex.size;
3896  if (part->randsize > 0.0f) {
3897  pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
3898  }
3899 
3900  birthtime = pa->time;
3901  dietime = pa->dietime;
3902 
3903  /* store this, so we can do multiple loops over particles */
3904  pa->state.time = dfra;
3905 
3906  if (dietime <= cfra && psys->cfra < dietime) {
3907  /* particle dies some time between this and last step */
3908  pa->state.time = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra);
3909  pa->alive = PARS_DYING;
3910  }
3911  else if (birthtime <= cfra && birthtime >= psys->cfra) {
3912  /* Particle is born some time between this and last step. */
3913  reset_particle(sim, pa, dfra * timestep, cfra);
3914  pa->alive = PARS_ALIVE;
3915  pa->state.time = cfra - birthtime;
3916  }
3917  else if (dietime < cfra) {
3918  /* nothing to be done when particle is dead */
3919  }
3920 
3921  /* Only reset unborn particles if they're shown or if the particle is born soon. */
3922  if (pa->alive == PARS_UNBORN &&
3923  (part->flag & PART_UNBORN || (cfra + psys->pointcache->step > pa->time))) {
3924  reset_particle(sim, pa, dtime, cfra);
3925  }
3926  else if (part->phystype == PART_PHYS_NO) {
3927  reset_particle(sim, pa, dtime, cfra);
3928  }
3929 
3930  if (ELEM(pa->alive, PARS_ALIVE, PARS_DYING) == 0 ||
3931  (pa->flag & (PARS_UNEXIST | PARS_NO_DISP))) {
3932  pa->state.time = -1.0f;
3933  }
3934  }
3935 
3936  switch (part->phystype) {
3937  case PART_PHYS_NEWTON: {
3939  {
3940  /* do global forces & effectors */
3941  basic_integrate(sim, p, pa->state.time, cfra);
3942 
3943  /* deflection */
3944  if (sim->colliders) {
3945  collision_check(sim, p, pa->state.time, cfra);
3946  }
3947 
3948  /* rotations */
3949  basic_rotate(part, pa, pa->state.time, timestep);
3950  }
3951  break;
3952  }
3953  case PART_PHYS_BOIDS: {
3955  {
3956  bbd.goal_ob = NULL;
3957 
3958  boid_brain(&bbd, p, pa);
3959 
3960  if (pa->alive != PARS_DYING) {
3961  boid_body(&bbd, pa);
3962 
3963  /* deflection */
3964  if (sim->colliders) {
3965  collision_check(sim, p, pa->state.time, cfra);
3966  }
3967  }
3968  }
3969  break;
3970  }
3971  case PART_PHYS_FLUID: {
3972  SPHData sphdata;
3973  psys_sph_init(sim, &sphdata);
3974 
3975  DynamicStepSolverTaskData task_data = {
3976  .sim = sim,
3977  .cfra = cfra,
3978  .timestep = timestep,
3979  .dtime = dtime,
3980  };
3981 
3982  BLI_spin_init(&task_data.spin);
3983 
3984  if (part->fluid->solver == SPH_SOLVER_DDR) {
3985  /* Apply SPH forces using double-density relaxation algorithm
3986  * (Clavat et. al.) */
3987 
3988  TaskParallelSettings settings;
3990  settings.use_threading = (psys->totpart > 100);
3991  settings.userdata_chunk = &sphdata;
3992  settings.userdata_chunk_size = sizeof(sphdata);
3995  0, psys->totpart, &task_data, dynamics_step_sph_ddr_task_cb_ex, &settings);
3996 
3997  sph_springs_modify(psys, timestep);
3998  }
3999  else {
4000  /* SPH_SOLVER_CLASSICAL */
4001  /* Apply SPH forces using classical algorithm (due to Gingold
4002  * and Monaghan). Note that, unlike double-density relaxation,
4003  * this algorithm is separated into distinct loops. */
4004 
4005  {
4006  TaskParallelSettings settings;
4008  settings.use_threading = (psys->totpart > 100);
4010  psys->totpart,
4011  &task_data,
4013  &settings);
4014  }
4015 
4016  /* calculate summation density */
4017  /* Note that we could avoid copying sphdata for each thread here (it's only read here),
4018  * but doubt this would gain us anything except confusion... */
4019  {
4020  TaskParallelSettings settings;
4022  settings.use_threading = (psys->totpart > 100);
4023  settings.userdata_chunk = &sphdata;
4024  settings.userdata_chunk_size = sizeof(sphdata);
4026  psys->totpart,
4027  &task_data,
4029  &settings);
4030  }
4031 
4032  /* do global forces & effectors */
4033  {
4034  TaskParallelSettings settings;
4036  settings.use_threading = (psys->totpart > 100);
4037  settings.userdata_chunk = &sphdata;
4038  settings.userdata_chunk_size = sizeof(sphdata);
4040  psys->totpart,
4041  &task_data,
4043  &settings);
4044  }
4045  }
4046 
4047  BLI_spin_end(&task_data.spin);
4048 
4049  psys_sph_finalize(&sphdata);
4050  break;
4051  }
4052  }
4053 
4054  /* finalize particle state and time after dynamics */
4056  {
4057  if (pa->alive == PARS_DYING) {
4058  pa->alive = PARS_DEAD;
4059  pa->state.time = pa->dietime;
4060  }
4061  else {
4062  pa->state.time = cfra;
4063  }
4064  }
4065 
4067  BLI_rng_free(sim->rng);
4068  sim->rng = NULL;
4069 }
4070 
4071 static void update_children(ParticleSimulationData *sim, const bool use_render_params)
4072 {
4073  if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE) == 0) {
4074  /* don't generate children while growing hair - waste of time */
4075  psys_free_children(sim->psys);
4076  }
4077  else if (sim->psys->part->childtype) {
4078  if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys, use_render_params)) {
4080  }
4081  else {
4082  /* Children are up to date, nothing to do. */
4083  }
4084  }
4085  else {
4086  psys_free_children(sim->psys);
4087  }
4088 }
4089 /* Updates cached particles' alive & other flags etc. */
4090 static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
4091 {
4092  ParticleSystem *psys = sim->psys;
4093  ParticleSettings *part = psys->part;
4094  ParticleTexture ptex;
4095  PARTICLE_P;
4096  float disp, dietime;
4097 
4098  psys_update_effectors(sim);
4099 
4100  disp = psys_get_current_display_percentage(psys, use_render_params);
4101 
4102  psys_sim_data_init(sim);
4103 
4105  {
4106  psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
4107  pa->size = part->size * ptex.size;
4108  if (part->randsize > 0.0f) {
4109  pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
4110  }
4111 
4112  dietime = pa->dietime;
4113 
4114  /* update alive status and push events */
4115  if (pa->time > cfra) {
4116  pa->alive = PARS_UNBORN;
4117  if (part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) {
4118  reset_particle(sim, pa, 0.0f, cfra);
4119  }
4120  }
4121  else if (dietime <= cfra) {
4122  pa->alive = PARS_DEAD;
4123  }
4124  else {
4125  pa->alive = PARS_ALIVE;
4126  }
4127 
4128  if (psys_frand(psys, p) > disp) {
4129  pa->flag |= PARS_NO_DISP;
4130  }
4131  else {
4132  pa->flag &= ~PARS_NO_DISP;
4133  }
4134  }
4135 
4136  psys_sim_data_free(sim);
4137 }
4138 
4139 static bool particles_has_flip(short parttype)
4140 {
4141  return (parttype == PART_FLUID_FLIP);
4142 }
4143 
4144 static bool particles_has_tracer(short parttype)
4145 {
4146  return (parttype == PART_FLUID_TRACER);
4147 }
4148 
4149 static bool particles_has_spray(short parttype)
4150 {
4152 }
4153 
4154 static bool particles_has_bubble(short parttype)
4155 {
4157 }
4158 
4159 static bool particles_has_foam(short parttype)
4160 {
4162 }
4163 
4165  int cfra,
4166  const bool use_render_params)
4167 {
4168  ParticleSystem *psys = sim->psys;
4169  if (psys->particles) {
4170  MEM_freeN(psys->particles);
4171  psys->particles = 0;
4172  psys->totpart = 0;
4173  }
4174 
4175 #ifndef WITH_FLUID
4176  UNUSED_VARS(use_render_params, cfra);
4177 #else
4178  {
4179  Object *ob = sim->ob;
4182 
4183  if (fmd && fmd->domain && fmd->domain->fluid) {
4184  FluidDomainSettings *fds = fmd->domain;
4185 
4186  ParticleSettings *part = psys->part;
4187  ParticleData *pa = NULL;
4188 
4189  int p, totpart = 0, tottypepart = 0;
4190  int flagActivePart, activeParts = 0;
4191  float posX, posY, posZ, velX, velY, velZ;
4192  float resX, resY, resZ;
4193  int upres = 1;
4194  char debugStrBuffer[256];
4195  float tmp[3] = {0}, tmp2[3] = {0};
4196 
4197  /* Helper variables for scaling. */
4198  float min[3], max[3], size[3], cell_size_scaled[3], max_size;
4199 
4200  /* Sanity check: parts also enabled in fluid domain? */
4201  if ((particles_has_flip(part->type) &&
4202  (fds->particle_type & FLUID_DOMAIN_PARTICLE_FLIP) == 0) ||
4203  (particles_has_spray(part->type) &&
4204  (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) == 0) ||
4205  (particles_has_bubble(part->type) &&
4207  (particles_has_foam(part->type) &&
4208  (fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) == 0) ||
4209  (particles_has_tracer(part->type) &&
4211  BLI_snprintf(debugStrBuffer,
4212  sizeof(debugStrBuffer),
4213  "particles_fluid_step::error - found particle system that is not enabled in "
4214  "fluid domain\n");
4215  return;
4216  }
4217 
4218  /* Count particle amount. tottypepart is only important for snd particles. */
4219  if (part->type == PART_FLUID_FLIP) {
4220  tottypepart = totpart = manta_liquid_get_num_flip_particles(fds->fluid);
4221  }
4222  if (particles_has_spray(part->type) || particles_has_bubble(part->type) ||
4223  particles_has_foam(part->type) || particles_has_tracer(part->type)) {
4224  totpart = manta_liquid_get_num_snd_particles(fds->fluid);
4225 
4226  /* tottypepart is the amount of particles of a snd particle type. */
4227  for (p = 0; p < totpart; p++) {
4228  flagActivePart = manta_liquid_get_snd_particle_flag_at(fds->fluid, p);
4229  if (particles_has_spray(part->type) && (flagActivePart & PARTICLE_TYPE_SPRAY)) {
4230  tottypepart++;
4231  }
4232  if (particles_has_bubble(part->type) && (flagActivePart & PARTICLE_TYPE_BUBBLE)) {
4233  tottypepart++;
4234  }
4235  if (particles_has_foam(part->type) && (flagActivePart & PARTICLE_TYPE_FOAM)) {
4236  tottypepart++;
4237  }
4238  if (particles_has_tracer(part->type) && (flagActivePart & PARTICLE_TYPE_TRACER)) {
4239  tottypepart++;
4240  }
4241  }
4242  }
4243  /* Sanity check: no particles present. */
4244  if (!totpart || !tottypepart) {
4245  return;
4246  }
4247 
4248  /* How many particles to display? */
4249  tottypepart = (use_render_params) ? tottypepart : (part->disp * tottypepart) / 100;
4250 
4251  part->totpart = tottypepart;
4252  part->sta = part->end = 1.0f;
4253  part->lifetime = sim->scene->r.efra + 1;
4254 
4255  /* Allocate particles. */
4256  realloc_particles(sim, part->totpart);
4257 
4258  /* Set some randomness when choosing which particles to display. */
4259  sim->rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed);
4260  double r, dispProb = (double)part->disp / 100.0;
4261 
4262  /* Loop over *all* particles. Will break out of loop before tottypepart amount exceeded. */
4263  for (p = 0, pa = psys->particles; p < totpart; p++) {
4264 
4265  /* Apply some randomness and determine which particles to skip. */
4266  r = BLI_rng_get_double(sim->rng);
4267  if (r > dispProb) {
4268  continue;
4269  }
4270 
4271  /* flag, res, upres, pos, vel for FLIP and snd particles have different getters. */
4272  if (part->type == PART_FLUID_FLIP) {
4273  flagActivePart = manta_liquid_get_flip_particle_flag_at(fds->fluid, p);
4274 
4275  resX = (float)manta_get_res_x(fds->fluid);
4276  resY = (float)manta_get_res_y(fds->fluid);
4277  resZ = (float)manta_get_res_z(fds->fluid);
4278 
4279  upres = 1;
4280 
4284 
4288  }
4289  else if (particles_has_spray(part->type) || particles_has_bubble(part->type) ||
4290  particles_has_foam(part->type) || particles_has_tracer(part->type)) {
4291  flagActivePart = manta_liquid_get_snd_particle_flag_at(fds->fluid, p);
4292 
4296 
4297  upres = manta_liquid_get_particle_upres(fds->fluid);
4298 
4302 
4306  }
4307  else {
4308  BLI_snprintf(debugStrBuffer,
4309  sizeof(debugStrBuffer),
4310  "particles_fluid_step::error - unknown particle system type\n");
4311  return;
4312  }
4313 # if 0
4314  /* Debugging: Print type of particle system and current particles. */
4315  printf("system type is %d and particle type is %d\n", part->type, flagActivePart);
4316 # endif
4317 
4318  /* Type of particle must match current particle system type
4319  * (only important for snd particles). */
4320  if ((flagActivePart & PARTICLE_TYPE_SPRAY) && !particles_has_spray(part->type)) {
4321  continue;
4322  }
4323  if ((flagActivePart & PARTICLE_TYPE_BUBBLE) && !particles_has_bubble(part->type)) {
4324  continue;
4325  }
4326  if ((flagActivePart & PARTICLE_TYPE_FOAM) && !particles_has_foam(part->type)) {
4327  continue;
4328  }
4329  if ((flagActivePart & PARTICLE_TYPE_TRACER) && !particles_has_tracer(part->type)) {
4330  continue;
4331  }
4332 # if 0
4333  /* Debugging: Print type of particle system and current particles. */
4334  printf("system type is %d and particle type is %d\n", part->type, flagActivePart);
4335 # endif
4336  /* Particle system has allocated 'tottypepart' particles - so break early before exceeded.
4337  */
4338  if (activeParts >= tottypepart) {
4339  break;
4340  }
4341 
4342  /* Only show active particles, i.e. filter out dead particles that just Mantaflow needs.
4343  * Mantaflow convention: PARTICLE_TYPE_DELETE == inactive particle. */
4344  if ((flagActivePart & PARTICLE_TYPE_DELETE) == 0) {
4345  activeParts++;
4346 
4347  /* Use particle system settings for particle size. */
4348  pa->size = part->size;
4349  if (part->randsize > 0.0f) {
4350  pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
4351  }
4352 
4353  /* Get size (dimension) but considering scaling */
4354  copy_v3_v3(cell_size_scaled, fds->cell_size);
4355  mul_v3_v3(cell_size_scaled, ob->scale);
4356  madd_v3fl_v3fl_v3fl_v3i(min, fds->p0, cell_size_scaled, fds->res_min);
4357  madd_v3fl_v3fl_v3fl_v3i(max, fds->p0, cell_size_scaled, fds->res_max);
4358  sub_v3_v3v3(size, max, min);
4359 
4360  /* Biggest dimension will be used for up-scaling. */
4361  max_size = MAX3(size[0] / (float)upres, size[1] / (float)upres, size[2] / (float)upres);
4362 
4363  /* Set particle position. */
4364  const float posParticle[3] = {posX, posY, posZ};
4365  copy_v3_v3(pa->state.co, posParticle);
4366 
4367  /* Normalize to unit cube around 0. */
4368  float resDomain[3] = {resX, resY, resZ};
4369  mul_v3_fl(resDomain, 0.5f);
4370  sub_v3_v3(pa->state.co, resDomain);
4371  mul_v3_fl(pa->state.co, fds->dx);
4372 
4373  /* Match domain dimension / size. */
4374  float scaleAbs[3] = {
4375  1. / fabsf(ob->scale[0]), 1. / fabsf(ob->scale[1]), 1. / fabsf(ob->scale[2])};
4376  mul_v3_fl(scaleAbs, max_size);
4377  mul_v3_v3(pa->state.co, scaleAbs);
4378 
4379  /* Match domain scale. */
4380  mul_m4_v3(ob->obmat, pa->state.co);
4381 
4382  /* Add origin offset to particle position. */
4383  zero_v3(tmp);
4384  zero_v3(tmp2);
4385  sub_v3_v3v3(tmp2, fds->p1, fds->p0);
4386  mul_v3_fl(tmp2, 0.5f);
4387  add_v3_v3v3(tmp, tmp, fds->p1);
4388  sub_v3_v3(tmp, tmp2);
4389  mul_v3_v3(tmp, ob->scale);
4390  add_v3_v3(pa->state.co, tmp);
4391 # if 0
4392  /* Debugging: Print particle coordinates. */
4393  printf("pa->state.co[0]: %f, pa->state.co[1]: %f, pa->state.co[2]: %f\n",
4394  pa->state.co[0], pa->state.co[1], pa->state.co[2]);
4395 # endif
4396  /* Set particle velocity. */
4397  const float velParticle[3] = {velX, velY, velZ};
4398  copy_v3_v3(pa->state.vel, velParticle);
4399  mul_v3_fl(pa->state.vel, fds->dx);
4400 # if 0
4401  /* Debugging: Print particle velocity. */
4402  printf("pa->state.vel[0]: %f, pa->state.vel[1]: %f, pa->state.vel[2]: %f\n",
4403  pa->state.vel[0], pa->state.vel[1], pa->state.vel[2]);
4404 # endif
4405  /* Set default angular velocity and particle rotation. */
4406  zero_v3(pa->state.ave);
4407  unit_qt(pa->state.rot);
4408 
4409  pa->time = 1.0f;
4410  pa->dietime = sim->scene->r.efra + 1;
4411  pa->lifetime = sim->scene->r.efra;
4412  pa->alive = PARS_ALIVE;
4413 
4414  /* Increasing particle settings pointer only for active particles. */
4415  pa++;
4416  }
4417  }
4418 # if 0
4419  /* Debugging: Print number of active particles. */
4420  printf("active parts: %d\n", activeParts);
4421 # endif
4422  totpart = psys->totpart = part->totpart = activeParts;
4423 
4424  BLI_rng_free(sim->rng);
4425  sim->rng = NULL;
4426 
4427  } /* Fluid sim particles done. */
4428  }
4429 #endif /* WITH_FLUID */
4430 }
4431 
4432 static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra))
4433 {
4434  ParticleSystem *psys = sim->psys;
4435  int oldtotpart = psys->totpart;
4436  int totpart = tot_particles(psys, pid);
4437 
4438  if (totpart != oldtotpart) {
4439  realloc_particles(sim, totpart);
4440  }
4441 
4442  return totpart - oldtotpart;
4443 }
4444 
4455 static void system_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
4456 {
4457  ParticleSystem *psys = sim->psys;
4458  ParticleSettings *part = psys->part;
4459  PointCache *cache = psys->pointcache;
4460  PTCacheID ptcacheid, *pid = NULL;
4461  PARTICLE_P;
4462  float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */
4463  int startframe = 0, endframe = 100, oldtotpart = 0;
4464 
4465  /* cache shouldn't be used for hair or "continue physics" */
4466  if (part->type != PART_HAIR) {
4468 
4469  /* set suitable cache range automatically */
4470  if ((cache->flag & (PTCACHE_BAKING | PTCACHE_BAKED)) == 0) {
4471  psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe);
4472  }
4473 
4474  pid = &ptcacheid;
4475  BKE_ptcache_id_from_particles(pid, sim->ob, psys);
4476 
4477  BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL);
4478 
4479  /* clear everything on start frame, or when psys needs full reset! */
4480  if ((cfra == startframe) || (psys->recalc & ID_RECALC_PSYS_RESET)) {
4482  BKE_ptcache_validate(cache, startframe);
4483  cache->flag &= ~PTCACHE_REDO_NEEDED;
4484  }
4485 
4486  CLAMP(cache_cfra, startframe, endframe);
4487  }
4488 
4489  /* 1. emit particles and redo particles if needed */
4490  oldtotpart = psys->totpart;
4491  if (emit_particles(sim, pid, cfra) || psys->recalc & ID_RECALC_PSYS_RESET) {
4492  distribute_particles(sim, part->from);
4494  /* reset only just created particles (on startframe all particles are recreated) */
4495  reset_all_particles(sim, 0.0, cfra, oldtotpart);
4497 
4499 
4500  psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
4501 
4502  /* flag for possible explode modifiers after this system */
4504 
4506  }
4507 
4508  /* 2. try to read from the cache */
4509  if (pid) {
4510  int cache_result = BKE_ptcache_read(pid, cache_cfra, true);
4511 
4512  if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
4513  cached_step(sim, cfra, use_render_params);
4514  update_children(sim, use_render_params);
4515  psys_update_path_cache(sim, cfra, use_render_params);
4516 
4517  BKE_ptcache_validate(cache, (int)cache_cfra);
4518 
4519  if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) {
4520  BKE_ptcache_write(pid, (int)cache_cfra);
4521  }
4522 
4523  return;
4524  }
4525  /* Cache is supposed to be baked, but no data was found so bail out */
4526  if (cache->flag & PTCACHE_BAKED) {
4528  return;
4529  }
4530  if (cache_result == PTCACHE_READ_OLD) {
4531  psys->cfra = (float)cache->simframe;
4532  cached_step(sim, psys->cfra, use_render_params);
4533  }
4534 
4535  /* if on second frame, write cache for first frame */
4536  if (psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
4537  BKE_ptcache_write(pid, startframe);
4538  }
4539  }
4540  else {
4541  BKE_ptcache_invalidate(cache);
4542  }
4543 
4544  /* 3. do dynamics */
4545  /* set particles to be not calculated TODO: can't work with pointcache */
4546  disp = psys_get_current_display_percentage(psys, use_render_params);
4547 
4549  {
4550  if (psys_frand(psys, p) > disp) {
4551  pa->flag |= PARS_NO_DISP;
4552  }
4553  else {
4554  pa->flag &= ~PARS_NO_DISP;
4555  }
4556  }
4557 
4558  if (psys->totpart) {
4559  int dframe, totframesback = 0;
4560  float t_frac, dt_frac;
4561 
4562  /* handle negative frame start at the first frame by doing
4563  * all the steps before the first frame */
4564  if ((int)cfra == startframe && part->sta < startframe) {
4565  totframesback = (startframe - (int)part->sta);
4566  }
4567 
4568  if (!(part->time_flag & PART_TIME_AUTOSF)) {
4569  /* Constant time step */
4570  psys->dt_frac = get_base_time_step(part);
4571  }
4572  else if ((int)cfra == startframe) {
4573  /* Variable time step; initialize to sub-frames. */
4574  psys->dt_frac = get_base_time_step(part);
4575  }
4576  else if (psys->dt_frac < MIN_TIMESTEP) {
4577  /* Variable time step; subsequent frames */
4578  psys->dt_frac = MIN_TIMESTEP;
4579  }
4580 
4581  for (dframe = -totframesback; dframe <= 0; dframe++) {
4582  /* simulate each subframe */
4583  dt_frac = psys->dt_frac;
4584  for (t_frac = dt_frac; t_frac <= 1.0f; t_frac += dt_frac) {
4585  sim->courant_num = 0.0f;
4586  dynamics_step(sim, cfra + dframe + t_frac - 1.0f);
4587  psys->cfra = cfra + dframe + t_frac - 1.0f;
4588 
4589  if (part->time_flag & PART_TIME_AUTOSF) {
4590  update_timestep(psys, sim);
4591  }
4592  /* Even without AUTOSF dt_frac may not add up to 1.0 due to float precision. */
4593  dt_frac = sync_timestep(psys, t_frac);
4594  }
4595  }
4596  }
4597 
4598  /* 4. only write cache starting from second frame */
4599  if (pid) {
4600  BKE_ptcache_validate(cache, (int)cache_cfra);
4601  if ((int)cache_cfra != startframe) {
4602  BKE_ptcache_write(pid, (int)cache_cfra);
4603  }
4604  }
4605 
4606  update_children(sim, use_render_params);
4607 
4608  /* cleanup */
4609  psys_sim_data_free(sim);
4610 }
4611 
4613 {
4614  ParticleSettings *part = psys->part;
4615  PTCacheID pid;
4616 
4617  BKE_ptcache_id_from_particles(&pid, ob, psys);
4618 
4619  if (part->phystype != PART_PHYS_KEYED) {
4620  psys->flag &= ~PSYS_KEYED;
4621  }
4622 
4623  if (part->type == PART_HAIR) {
4625  part->ren_as = PART_DRAW_PATH;
4626  }
4627 
4628  if (part->distr == PART_DISTR_GRID) {
4629  part->distr = PART_DISTR_JIT;
4630  }
4631 
4633  part->draw_as = PART_DRAW_REND;
4634  }
4635 
4636  CLAMP(part->path_start, 0.0f, 100.0f);
4637  CLAMP(part->path_end, 0.0f, 100.0f);
4638 
4640  }
4641  else {
4642  free_hair(ob, psys, 1);
4643 
4644  CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime));
4645  CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime));
4646  }
4647 
4648  psys_reset(psys, PSYS_RESET_ALL);
4649 }
4651 {
4652  BoidParticle *bpa;
4653  PARTICLE_P;
4654 
4655  pa = psys->particles;
4656 
4657  if (!pa) {
4658  return;
4659  }
4660 
4661  if (psys->part && psys->part->phystype == PART_PHYS_BOIDS) {
4662  if (!pa->boid) {
4663  bpa = MEM_callocN(psys->totpart * sizeof(BoidParticle), "Boid Data");
4664 
4666  {
4667  pa->boid = bpa++;
4668  }
4669  }
4670  }
4671  else if (pa->boid) {
4672  MEM_freeN(pa->boid);
4674  {
4675  pa->boid = NULL;
4676  }
4677  }
4678 }
4679 
4681 {
4682  SPHFluidSettings *fluid = part->fluid;
4683 
4684  fluid->spring_k = 0.0f;
4685  fluid->plasticity_constant = 0.1f;
4686  fluid->yield_ratio = 0.1f;
4687  fluid->rest_length = 1.0f;
4688  fluid->viscosity_omega = 2.0f;
4689  fluid->viscosity_beta = 0.1f;
4690  fluid->stiffness_k = 1.0f;
4691  fluid->stiffness_knear = 1.0f;
4692  fluid->rest_density = 1.0f;
4693  fluid->buoyancy = 0.0f;
4694  fluid->radius = 1.0f;
4697 }
4698 
4700 {
4701  ParticleSettings *part = sim->psys->part;
4702 
4703  if (ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
4704  PTCacheID pid;
4705  BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys);
4707  }
4708  else {
4709  free_keyed_keys(sim->psys);
4710  sim->psys->flag &= ~PSYS_KEYED;
4711  }
4712 
4713  /* RNA Update must ensure this is true. */
4714  if (part->phystype == PART_PHYS_BOIDS) {
4715  BLI_assert(part->boids != NULL);
4716  }
4717  else if (part->phystype == PART_PHYS_FLUID) {
4718  BLI_assert(part->fluid != NULL);
4719  }
4720 
4721  psys_check_boid_data(sim->psys);
4722 }
4724 {
4725  if (!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) &&
4726  ((psys->flag & PSYS_HAIR_DONE) == 0 || psys->recalc & ID_RECALC_PSYS_RESET ||
4727  (psys->part->flag & PART_HAIR_REGROW && !psys->edit))) {
4728  return 1;
4729  }
4730 
4731  return 0;
4732 }
4733 
4735 {
4736  ParticleSettings *particle_settings_local = (ParticleSettings *)BKE_id_copy_ex(
4737  NULL, (ID *)&particle_settings->id, NULL, LIB_ID_COPY_LOCALIZE);
4738  return particle_settings_local;
4739 }
4740 
4741 static void particle_settings_free_local(ParticleSettings *particle_settings)
4742 {
4743  BKE_libblock_free_datablock(&particle_settings->id, 0);
4744  BKE_libblock_free_data(&particle_settings->id, false);
4745  BLI_assert(!particle_settings->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
4746  MEM_freeN(particle_settings);
4747 }
4748 
4750  Scene *scene,
4751  Object *ob,
4752  ParticleSystem *psys,
4753  const bool use_render_params)
4754 {
4755  ParticleSimulationData sim = {0};
4756  ParticleSettings *part = psys->part;
4757  ParticleSystem *psys_orig = psys_orig_get(psys);
4758  float cfra;
4760 
4761  /* drawdata is outdated after ANY change */
4762  if (psys->pdd) {
4763  psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
4764  }
4765 
4766  if (!psys_check_enabled(ob, psys, use_render_params)) {
4767  return;
4768  }
4769 
4770  cfra = DEG_get_ctime(depsgraph);
4771 
4772  sim.depsgraph = depsgraph;
4773  sim.scene = scene;
4774  sim.ob = ob;
4775  sim.psys = psys;
4776  sim.psmd = psmd;
4777 
4778  /* system was already updated from modifier stack */
4781  /* make sure it really was updated to cfra */
4782  if (psys->cfra == cfra) {
4783  return;
4784  }
4785  }
4786 
4787  if (!sim.psmd->mesh_final) {
4788  return;
4789  }
4790 
4791  if (part->from != PART_FROM_VERT) {
4793  }
4794 
4795  /* to verify if we need to restore object afterwards */
4796  psys->flag &= ~PSYS_OB_ANIM_RESTORE;
4797 
4798  if (psys->recalc & ID_RECALC_PSYS_RESET) {
4799  psys->totunexist = 0;
4800  }
4801 
4802  /* setup necessary physics type dependent additional data if it doesn't yet exist */
4803  psys_prepare_physics(&sim);
4804 
4805  if (part->type == PART_HAIR) {
4806  /* nothing to do so bail out early */
4807  if (psys->totpart == 0 && part->totpart == 0) {
4808  psys_free_path_cache(psys, NULL);
4809  free_hair(ob, psys, 0);
4810  psys->flag |= PSYS_HAIR_DONE;
4811  }
4812  /* (re-)create hair */
4813  else if (hair_needs_recalc(psys)) {
4814  float hcfra = 0.0f;
4815  int i, recalc = psys->recalc;
4816 
4817  free_hair(ob, psys, 0);
4818 
4819  if (psys_orig->edit && psys_orig->free_edit) {
4820  psys_orig->free_edit(psys_orig->edit);
4821  psys_orig->edit = NULL;
4822  psys_orig->free_edit = NULL;
4823  }
4824 
4825  /* first step is negative so particles get killed and reset */
4826  psys->cfra = 1.0f;
4827 
4828  ParticleSettings *part_local = part;
4829  if ((part->flag & PART_HAIR_REGROW) == 0) {
4830  part_local = particle_settings_localize(part);
4831  psys->part = part_local;
4832  }
4833 
4834  for (i = 0; i <= part->hair_step; i++) {
4835  hcfra = 100.0f * (float)i / (float)psys->part->hair_step;
4836  if ((part->flag & PART_HAIR_REGROW) == 0) {
4837  const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
4838  depsgraph, hcfra);
4840  &part_local->id, part_local->adt, &anim_eval_context, ADT_RECALC_ANIM, false);
4841  }
4842  system_step(&sim, hcfra, use_render_params);
4843  psys->cfra = hcfra;
4844  psys->recalc = 0;
4845  save_hair(&sim, hcfra);
4846  }
4847 
4848  if (part_local != part) {
4849  particle_settings_free_local(part_local);
4850  psys->part = part;
4851  }
4852 
4853  psys->flag |= PSYS_HAIR_DONE;
4854  psys->recalc = recalc;
4855  }
4856  else if (psys->flag & PSYS_EDITED) {
4857  psys->flag |= PSYS_HAIR_DONE;
4858  }
4859 
4860  if (psys->flag & PSYS_HAIR_DONE) {
4861  hair_step(&sim, cfra, use_render_params);
4862  }
4863  }
4864  else if (particles_has_flip(part->type) || particles_has_spray(part->type) ||
4865  particles_has_bubble(part->type) || particles_has_foam(part->type) ||
4866  particles_has_tracer(part->type)) {
4867  particles_fluid_step(&sim, (int)cfra, use_render_params);
4868  }
4869  else {
4870  switch (part->phystype) {
4871  case PART_PHYS_NO:
4872  case PART_PHYS_KEYED: {
4873  PARTICLE_P;
4874  float disp = psys_get_current_display_percentage(psys, use_render_params);
4875  bool free_unexisting = false;
4876 
4877  /* Particles without dynamics haven't been reset yet because they don't use pointcache */
4878  if (psys->recalc & ID_RECALC_PSYS_RESET) {
4879  psys_reset(psys, PSYS_RESET_ALL);
4880  }
4881 
4882  if (emit_particles(&sim, NULL, cfra) || (psys->recalc & ID_RECALC_PSYS_RESET)) {
4883  free_keyed_keys(psys);
4884  distribute_particles(&sim, part->from);
4886  free_unexisting = true;
4887 
4888  /* flag for possible explode modifiers after this system */
4890  }
4891 
4892  ParticleTexture ptex;
4893 
4895  {
4896  psys_get_texture(&sim, pa, &ptex, PAMAP_SIZE, cfra);
4897  pa->size = part->size * ptex.size;
4898  if (part->randsize > 0.0f) {
4899  pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
4900  }
4901 
4902  reset_particle(&sim, pa, 0.0, cfra);
4903 
4904  if (psys_frand(psys, p) > disp) {
4905  pa->flag |= PARS_NO_DISP;
4906  }
4907  else {
4908  pa->flag &= ~PARS_NO_DISP;
4909  }
4910  }
4911 
4912  /* free unexisting after resetting particles */
4913  if (free_unexisting) {
4915  }
4916 
4917  if (part->phystype == PART_PHYS_KEYED) {
4919  set_keyed_keys(&sim);
4920  psys_update_path_cache(&sim, (int)cfra, use_render_params);
4921  }
4922  break;
4923  }
4924  default: {
4925  /* the main dynamic particle system step */
4926  system_step(&sim, cfra, use_render_params);
4927  break;
4928  }
4929  }
4930  }
4931 
4932  /* make sure emitter is left at correct time (particle emission can change this) */
4933  if (psys->flag & PSYS_OB_ANIM_RESTORE) {
4935  psys->flag &= ~PSYS_OB_ANIM_RESTORE;
4936  }
4937 
4938  if (psys_orig->edit) {
4940  }
4941 
4942  psys->cfra = cfra;
4943  psys->recalc = 0;
4944 
4945  if (DEG_is_active(depsgraph)) {
4946  if (psys_orig != psys) {
4947  if (psys_orig->edit != NULL && psys_orig->edit->psys == psys_orig) {
4948  psys_orig->edit->psys_eval = psys;
4949  psys_orig->edit->psmd_eval = psmd;
4950  }
4951  psys_orig->flag = (psys->flag & ~PSYS_SHARED_CACHES);
4952  psys_orig->cfra = psys->cfra;
4953  psys_orig->recalc = psys->recalc;
4954  psys_orig->part->totpart = part->totpart;
4955  }
4956  }
4957 
4958  /* Save matrix for duplicators,
4959  * at render-time the actual dupli-object's matrix is used so don't update! */
4960  invert_m4_m4(psys->imat, ob->obmat);
4961 
4963 }
4964 
4965 /* ID looper */
4966 
4967 /* unfortunately PSys and modifier ID loopers are not directly compatible, so we need this struct
4968  * and the callback below to map the former to the latter (thanks to psys embedding a Cloth
4969  * modifier data struct now, for Hair physics simulations). */
4973  void *userdata;
4975 
4977  Object *UNUSED(object),
4978  ID **id_pointer,
4979  int cb_flag)
4980 {
4982  data->func(data->psys, id_pointer, data->userdata, cb_flag);
4983 }
4984 
4986 {
4987  ParticleTarget *pt;
4988 
4989  func(psys, (ID **)&psys->part, userdata, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
4990  func(psys, (ID **)&psys->target_ob, userdata, IDWALK_CB_NOP);
4991  func(psys, (ID **)&psys->parent, userdata, IDWALK_CB_NOP);
4992 
4993  if (psys->clmd != NULL) {
4995 
4996  if (mti->foreachIDLink != NULL) {
4997  ParticleSystemIDLoopForModifier data = {.psys = psys, .func = func, .userdata = userdata};
4998  mti->foreachIDLink(
5000  }
5001  }
5002 
5003  for (pt = psys->targets.first; pt; pt = pt->next) {
5004  func(psys, (ID **)&pt->ob, userdata, IDWALK_CB_NOP);
5005  }
5006 
5007  /* Even though psys->part should never be NULL, this can happen as an exception during deletion.
5008  * See ID_REMAP_SKIP/FORCE/FLAG_NEVER_NULL_USAGE in BKE_library_remap. */
5009  if (psys->part && psys->part->phystype == PART_PHYS_BOIDS) {
5010  ParticleData *pa;
5011  int p;
5012 
5013  for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
5014  func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_CB_NOP);
5015  }
5016  }
5017 }
5018 
5020 {
5021  for (ModifierData *md = object->modifiers.first; md != NULL; md = md->next) {
5022  if (md->type != eModifierType_ParticleSystem) {
5023  continue;
5024  }
5026  ParticleSystem *psys = psmd->psys;
5027  psys->recalc |= ID_RECALC_PSYS_RESET;
5028  }
5029 }
5030 
5031 /* **** Depsgraph evaluation **** */
5032 
5034  ParticleSettings *particle_settings)
5035 {
5036  DEG_debug_print_eval(depsgraph, __func__, particle_settings->id.name, particle_settings);
5037  particle_settings->id.recalc |= ID_RECALC_PSYS_RESET;
5038 }
5039 
5041 {
5042  DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
5043  for (ParticleSystem *psys = object->particlesystem.first; psys != NULL; psys = psys->next) {
5044  psys->recalc |= (psys->part->id.recalc & ID_RECALC_PSYS_ALL);
5045  }
5046 }
typedef float(TangentPoint)[2]
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time)
Definition: anim_sys.c:761
@ ADT_RECALC_ANIM
Definition: BKE_animsys.h:290
void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, bool flush_to_original)
void boid_brain(BoidBrainData *bbd, int p, struct ParticleData *pa)
Definition: boids.c:1048
void boid_body(BoidBrainData *bbd, struct ParticleData *pa)
Definition: boids.c:1204
void boids_precalc_rules(struct ParticleSettings *part, float cfra)
Definition: boids.c:950
void cloth_free_modifier(struct ClothModifierData *clmd)
Definition: cloth.c:421
void clothModifier_do(struct ClothModifierData *clmd, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Mesh *me, float(*vertexCos)[3])
Definition: cloth.c:314
void BKE_collider_cache_free(struct ListBase **colliders)
Definition: collision.c:1359
struct ListBase * BKE_collider_cache_create(struct Depsgraph *depsgraph, struct Object *self, struct Collection *collection)
Definition: collision.c:1322
void BKE_curvemapping_free(struct CurveMapping *cumap)
Definition: colortools.c:103
@ CD_CALLOC
#define ORIGINDEX_NONE
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void BKE_effectors_free(struct ListBase *lb)
Definition: effect.c:369
void BKE_effectors_apply(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *wind_force, float *impulse)
Definition: effect.c:1114
void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point)
Definition: effect.c:383
struct ListBase * BKE_effectors_create(struct Depsgraph *depsgraph, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool use_rotation)
Definition: effect.c:314
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:187
void BKE_libblock_free_data(struct ID *id, bool do_id_user) ATTR_NONNULL()
Definition: lib_id_delete.c:44
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_libblock_free_datablock(struct ID *id, int flag) ATTR_NONNULL()
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
@ IDWALK_CB_NEVER_NULL
Definition: BKE_lib_query.h:34
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float(*vert_coords)[3])
Definition: mesh.cc:1834
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.cc:991
void BKE_mesh_update_customdata_pointers(struct Mesh *me, bool do_ensure_tess_cd)
Definition: mesh.cc:874
float(* BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3]
void BKE_mesh_tessface_ensure(struct Mesh *mesh)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
struct ModifierData * BKE_modifiers_findby_type(const struct Object *ob, ModifierType type)
struct ModifierData * BKE_modifier_new(int type)
General operations, lookup, etc. for blender objects.
void BKE_object_where_is_calc_time(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, float ctime)
Definition: object.cc:3467
void distribute_particles(struct ParticleSimulationData *sim, int from)
bool do_guides(struct Depsgraph *depsgraph, struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int index, float time)
Definition: particle.c:2414
#define PARTICLE_DRAW_DATA_UPDATED
Definition: BKE_particle.h:239
void psys_vec_rot_to_face(struct Mesh *mesh, struct ParticleData *pa, float vec[3])
Definition: particle.c:3926
void psys_cache_paths(struct ParticleSimulationData *sim, float cfra, bool use_render_params)
Definition: particle.c:3306
#define DMCACHE_NOTFOUND
Definition: BKE_particle.h:672
void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors)
Definition: particle.c:2358
#define LOOP_SHOWN_PARTICLES
Definition: BKE_particle.h:55
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, bool use_render_params)
Definition: particle.c:801
struct ParticleSystem * psys_orig_get(struct ParticleSystem *psys)
Definition: particle.c:753
void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time)
Definition: particle.c:3790
void psys_mat_hair_to_object(struct Object *ob, struct Mesh *mesh, short from, struct ParticleData *pa, float hairmat[4][4])
bool psys_in_edit_mode(struct Depsgraph *depsgraph, const struct ParticleSystem *psys)
float psys_get_timestep(struct ParticleSimulationData *sim)
Definition: particle.c:4490
void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3])
Definition: particle.c:2322
float psys_get_dietime_from_cache(struct PointCache *cache, int index)
Definition: particle.c:1366
void psys_free_particles(struct ParticleSystem *psys)
Definition: particle.c:1022
void psys_free_children(struct ParticleSystem *psys)
Definition: particle.c:1012
void free_keyed_keys(struct ParticleSystem *psys)
Definition: particle.c:971
#define PSYS_RESET_CACHE_MISS
Definition: BKE_particle.h:669
int psys_uses_gravity(struct ParticleSimulationData *sim)
Definition: particle.c:919
float psys_particle_value_from_verts(struct Mesh *mesh, short from, struct ParticleData *pa, float *values)
Definition: particle.c:2217
#define LOOP_PARTICLES
Definition: BKE_particle.h:51
void psys_sim_data_free(struct ParticleSimulationData *sim)
Definition: particle.c:726
#define PSYS_RESET_ALL
Definition: BKE_particle.h:666
#define LOOP_DYNAMIC_PARTICLES
Definition: BKE_particle.h:59
struct ParticleSystemModifierData * psys_get_modifier(struct Object *ob, struct ParticleSystem *psys)
Definition: particle.c:2230
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
Definition: particle.c:997
void psys_free_pdd(struct ParticleSystem *psys)
Definition: particle.c:1052
@ BKE_PARTICLE_BATCH_DIRTY_ALL
Definition: BKE_particle.h:686
#define DMCACHE_ISCHILD
Definition: BKE_particle.h:673
#define PARTICLE_COLLISION_MAX_COLLISIONS
Definition: BKE_particle.h:46
int psys_particle_dm_face_lookup(struct Mesh *mesh_final, struct Mesh *mesh_original, int findex_orig, const float fw[4], struct LinkNode **poly_nodes)
Definition: particle.c:1923
void psys_get_texture(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleTexture *ptex, int event, float cfra)
Definition: particle.c:4355
#define LOOP_EXISTING_PARTICLES
Definition: BKE_particle.h:52
void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics)
Definition: particle.c:936
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode)
Definition: particle.c:5274
#define PSYS_RESET_DEPSGRAPH
Definition: BKE_particle.h:667
void(* ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cb_flag)
Definition: BKE_particle.h:527
void psys_find_parents(struct ParticleSimulationData *sim, bool use_render_params)
Definition: particle.c:2678
void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, bool editupdate, bool use_render_params)
Definition: particle.c:3198
void psys_sim_data_init(struct ParticleSimulationData *sim)
Definition: particle.c:685
#define PARTICLE_P
Definition: BKE_particle.h:48
BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
Definition: BKE_particle.h:248
bool psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, bool always)
Definition: particle.c:4884
void BKE_ptcache_free_mem(struct ListBase *mem_cache)
Definition: pointcache.c:3029
void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
Definition: pointcache.c:2773
#define PTCACHE_CLEAR_AFTER
void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys)
Definition: pointcache.c:900
void BKE_ptcache_validate(struct PointCache *cache, int framenr)
Definition: pointcache.c:3789
void BKE_ptcache_id_clear(PTCacheID *id, int mode, unsigned int cfra)
Definition: pointcache.c:2592
void BKE_ptcache_disk_to_mem(struct PTCacheID *pid)
Definition: pointcache.c:3421
#define PTCACHE_CLEAR_ALL
#define PTCACHE_READ_INTERPOLATED
int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode)
Definition: pointcache.c:2870
@ PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL
#define PTCACHE_READ_OLD
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
Definition: pointcache.c:2280
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
Definition: pointcache.c:2540
#define PTCACHE_RESET_OUTDATED
void BKE_ptcache_invalidate(struct PointCache *cache)
Definition: pointcache.c:3796
#define PTCACHE_READ_EXACT
int get_render_child_particle_number(const struct RenderData *r, int child_num, bool for_render)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_buffer_append(buffer_, type_, val_)
Definition: BLI_buffer.h:50
#define BLI_buffer_field_init(name_, type_)
Definition: BLI_buffer.h:104
#define BLI_buffer_append_array(buffer_, type_, data_, count_)
Definition: BLI_buffer.h:80
#define BLI_buffer_at(buffer_, type_, index_)
Definition: BLI_buffer.h:36
#define BLI_buffer_field_free(name_)
Definition: BLI_buffer.h:111
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value)
Definition: edgehash.c:230
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
Definition: edgehash.c:261
EdgeHash * BLI_edgehash_new_ex(const char *info, unsigned int nentries_reserve)
Definition: edgehash.c:212
void * BLI_edgehash_lookup(const EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:295
int BLI_bvhtree_range_query(BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata)
Definition: BLI_kdopbvh.c:2080
#define BVH_RAYCAST_DEFAULT
Definition: BLI_kdopbvh.h:88
@ BVH_RAYCAST_WATERTIGHT
Definition: BLI_kdopbvh.h:86
void BLI_bvhtree_balance(BVHTree *tree)
Definition: BLI_kdopbvh.c:937
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
Definition: BLI_kdopbvh.c:854
int BLI_bvhtree_ray_cast_ex(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata, int flag)
Definition: BLI_kdopbvh.c:1897
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:926
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
Definition: BLI_kdopbvh.c:979
void(* BVHTree_RangeQuery)(void *userdata, int index, const float co[3], float dist_sq)
Definition: BLI_kdopbvh.h:115
A KD-tree for nearest neighbor search.
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float saacos(float fac)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float pow2f(float x)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE float interpf(float a, float b, float t)
MINLINE float pow3f(float x)
#define M_PI
Definition: BLI_math_base.h:20
MINLINE float pow4f(float x)
MINLINE float pow7f(float x)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:790
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void normalize_m4(float R[4][4]) ATTR_NONNULL()
Definition: math_matrix.c:1945
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 mat3_to_quat(float q[4], const float mat[3][3])
void vec_to_quat(float q[4], const float vec[3], short axis, short upflag)
float normalize_qt(float q[4])
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 invert_qt_qt_normalized(float q1[4], const float q2[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
Definition: math_rotation.c:46
void mat4_to_quat(float q[4], const float mat[4][4])
void mat3_to_quat_is_ok(float q[4], const float mat[3][3])
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
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 madd_v3fl_v3fl_v3fl_v3i(float r[3], const float a[3], const float b[3], const int c[3])
MINLINE float normalize_v3(float r[3])
MINLINE void mul_v3_v3(float r[3], const float a[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_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_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 madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
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 len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition: rand.cc:58
double BLI_rng_get_double(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: rand.cc:88
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition: rand.cc:46
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: rand.cc:93
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_len)
Definition: string_utils.c:309
void BLI_task_isolate(void(*func)(void *userdata), void *userdata)
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:110
pthread_rwlock_t ThreadRWMutex
Definition: BLI_threads.h:125
#define THREAD_LOCK_READ
Definition: BLI_threads.h:120
#define THREAD_LOCK_WRITE
Definition: BLI_threads.h:121
#define BLI_RWLOCK_INITIALIZER
Definition: BLI_threads.h:123
int BLI_system_thread_count(void)
Definition: threads.cc:281
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
Definition: threads.cc:488
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
Definition: threads.cc:498
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:467
#define MAX3(a, b, c)
#define UNUSED_VARS(...)
#define CLAMPIS(a, b, c)
#define POINTER_FROM_INT(i)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define MAX2(a, b)
#define ELEM(...)
#define MIN2(a, b)
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:312
@ DAG_EVAL_RENDER
Definition: DEG_depsgraph.h:46
void DEG_debug_print_eval(struct Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
float DEG_get_ctime(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
@ ID_RECALC_PSYS_CHILD
Definition: DNA_ID.h:802
@ ID_RECALC_PSYS_ALL
Definition: DNA_ID.h:893
@ ID_RECALC_PSYS_RESET
Definition: DNA_ID.h:800
@ eBoidMode_OnLand
@ eBoidMode_InAir
#define BOID_ALLOW_LAND
@ CLOTH_COLLSETTINGS_FLAG_SELF
@ CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS
@ CD_MDEFORMVERT
@ CD_ORIGINDEX
@ FLUID_DOMAIN_PARTICLE_SPRAY
@ FLUID_DOMAIN_PARTICLE_FOAM
@ FLUID_DOMAIN_PARTICLE_TRACER
@ FLUID_DOMAIN_PARTICLE_FLIP
@ FLUID_DOMAIN_PARTICLE_BUBBLE
These structs are the foundation for all linked lists in the library system.
@ eParticleSystemFlag_Pars
@ eParticleSystemFlag_psys_updated
@ eModifierType_ParticleSystem
@ eModifierType_Cloth
@ eModifierType_Fluid
@ OB_MODE_WEIGHT_PAINT
#define EFF_WEIGHT_DO_HAIR
#define PDEFLE_KILL_PART
Object is a sort of wrapper for general info.
@ OB_POSX
@ OB_POSZ
#define PART_PHYS_KEYED
#define PART_SIZE_DEFL
#define PART_DRAW_PATH
#define PART_INT_VERLET
#define PSYS_OB_ANIM_RESTORE
#define PART_DRAW_OB
#define PART_FROM_VERT
#define PART_INT_MIDPOINT
#define PART_TIME_AUTOSF
#define PART_FROM_CHILD
#define SPH_CURRENT_REST_LENGTH
#define PART_ROT_GLOB_X
#define PARS_UNEXIST
#define SPH_SOLVER_DDR
#define PART_ROT_GLOB_Z
#define PART_DRAW_REND
#define SPH_VISCOELASTIC_SPRINGS
#define PARS_NO_DISP
#define PART_DRAW_NOT
#define PART_AVE_GLOBAL_X
#define PART_PHYS_FLUID
#define PART_PHYS_BOIDS
#define PSYS_HAIR_DYNAMICS
#define PART_DIE_ON_COL
#define SPH_FAC_RADIUS
#define PART_DISTR_JIT
#define PSYS_KEYED
#define PART_ROT_GLOB_Y
#define PART_CHILD_FACES
#define PART_INT_EULER
#define PART_ROT_OB_X
#define SPH_FAC_DENSITY
#define PART_ROT_OB_Z
#define PART_UNBORN
#define PART_ROT_NOR_TAN
@ PAMAP_PHYSICS
@ PAMAP_SIZE
@ PAMAP_IVEL
@ PAMAP_INIT
@ PAMAP_LIFE
#define SPH_FAC_VISCOSITY
@ PART_FLUID_FLIP
@ PART_EMITTER
@ PART_FLUID_BUBBLE
@ PART_FLUID_TRACER
@ PART_FLUID_FOAM
@ PART_FLUID_SPRAYFOAMBUBBLE
@ PART_FLUID_SPRAYFOAM
@ PART_HAIR
@ PART_FLUID_SPRAY
@ PART_FLUID_FOAMBUBBLE
#define PTARGET_VALID
#define PSYS_SHARED_CACHES
#define SPH_FAC_REPULSION
#define PART_DISTR_GRID
#define SPH_FAC_REST_LENGTH
#define PART_ROT_OB_Y
#define PARS_DEAD
#define PSYS_VG_DENSITY
#define PART_ROT_NOR
#define PART_PHYS_NO
#define PART_AVE_VELOCITY
#define PART_SIZEMASS
#define PART_AVE_GLOBAL_Y
#define PART_HAIR_REGROW
@ PARTICLE_TYPE_BUBBLE
@ PARTICLE_TYPE_DELETE
@ PARTICLE_TYPE_TRACER
@ PARTICLE_TYPE_FOAM
@ PARTICLE_TYPE_SPRAY
#define PART_PHYS_NEWTON
#define PART_DRAW_GR
#define PARS_ALIVE
#define PART_ROTATIONS
#define PART_ROT_VEL
#define PART_AVE_HORIZONTAL
#define PART_ROT_DYN
#define PART_AVE_VERTICAL
#define PSYS_EDITED
#define PART_AVE_GLOBAL_Z
#define PARS_UNBORN
#define PARS_DYING
#define PSYS_HAIR_UPDATED
#define PSYS_KEYED_TIMING
#define PSYS_HAIR_DONE
#define PART_INT_RK4
#define PART_AVE_RAND
@ PTCACHE_EXTERNAL
@ PTCACHE_BAKED
@ PTCACHE_BAKING
@ PTCACHE_OUTDATED
@ PTCACHE_DISK_CACHE
@ PTCACHE_REDO_NEEDED
#define PE_DRAW_PART
#define PHYS_GLOBAL_GRAVITY
_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 GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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
_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 v1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
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
Platform independent time functions.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static void mul(btAlignedObjectArray< T > &items, const Q &value)
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
static SpinLock spin
Definition: cachefile.c:162
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
OperationNode * node
StackEntry * from
double time
Scene scene
const Depsgraph * depsgraph
void * user_data
DEGForeachIDComponentCallback callback
void * tree
#define rot(x, k)
uint nor
uint col
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
const int state
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
int manta_liquid_get_flip_particle_flag_at(struct MANTA *liquid, int i)
int manta_liquid_get_snd_particle_flag_at(struct MANTA *liquid, int i)
float manta_liquid_get_flip_particle_velocity_z_at(struct MANTA *liquid, int i)
float manta_liquid_get_snd_particle_velocity_z_at(struct MANTA *liquid, int i)
float manta_liquid_get_flip_particle_velocity_y_at(struct MANTA *liquid, int i)
float manta_liquid_get_flip_particle_position_y_at(struct MANTA *liquid, int i)
int manta_liquid_get_particle_res_y(struct MANTA *liquid)
int manta_liquid_get_particle_upres(struct MANTA *liquid)
float manta_liquid_get_flip_particle_position_z_at(struct MANTA *liquid, int i)
int manta_get_res_x(struct MANTA *fluid)
int manta_get_res_z(struct MANTA *fluid)
int manta_get_res_y(struct MANTA *fluid)
float manta_liquid_get_snd_particle_position_z_at(struct MANTA *liquid, int i)
float manta_liquid_get_snd_particle_velocity_y_at(struct MANTA *liquid, int i)
int manta_liquid_get_num_flip_particles(struct MANTA *liquid)
int manta_liquid_get_particle_res_x(struct MANTA *liquid)
float manta_liquid_get_flip_particle_position_x_at(struct MANTA *liquid, int i)
float manta_liquid_get_snd_particle_position_x_at(struct MANTA *liquid, int i)
float manta_liquid_get_snd_particle_position_y_at(struct MANTA *liquid, int i)
float manta_liquid_get_snd_particle_velocity_x_at(struct MANTA *liquid, int i)
int manta_liquid_get_particle_res_z(struct MANTA *liquid)
int manta_liquid_get_num_snd_particles(struct MANTA *liquid)
float manta_liquid_get_flip_particle_velocity_x_at(struct MANTA *liquid, int i)
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned c
Definition: RandGen.cpp:83
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T length(const vec_base< T, Size > &a)
T distance(const T &a, const T &b)
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
void BKE_particlesettings_fluid_default_settings(ParticleSettings *part)
static void dynamics_step_sph_classical_calc_density_task_cb_ex(void *__restrict userdata, const int p, const TaskParallelTLS *__restrict tls)
static void get_angular_velocity_vector(short avemode, ParticleKey *state, float vec[3])
static float nr_distance_to_vert(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor))
static float collision_point_distance_with_normal(float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *nor)
#define COLLISION_ZERO
static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
static float nr_distance_to_edge(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor))
static void sphclassical_calc_dens(ParticleData *pa, float UNUSED(dfra), SPHData *sphdata)
void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, ParticleSystem *psys)
static void dynamics_step_sphdata_reduce(const void *__restrict UNUSED(userdata), void *__restrict join_v, void *__restrict chunk_v)
static float collision_newton_rhapson(ParticleCollision *col, float radius, ParticleCollisionElement *pce, NRDistanceFunc distance_func)
static void dynamics_step(ParticleSimulationData *sim, float cfra)
static ThreadRWMutex psys_bvhtree_rwlock
struct ParticleSystemIDLoopForModifier ParticleSystemIDLoopForModifier
static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
static void collision_point_on_surface(const float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *co)
static const float MIN_TIMESTEP
static void psys_prepare_physics(ParticleSimulationData *sim)
static bool particles_has_bubble(short parttype)
void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata)
static int collision_response(ParticleSimulationData *sim, ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation)
static void dynamics_step_sph_ddr_task_cb_ex(void *__restrict userdata, const int p, const TaskParallelTLS *__restrict tls)
static void sph_evaluate_func(BVHTree *tree, ParticleSystem **psys, const float co[3], SPHRangeData *pfr, float interaction_radius, BVHTree_RangeQuery callback)
static void update_timestep(ParticleSystem *psys, ParticleSimulationData *sim)
static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, float cfra)
static void init_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)
static void sphclassical_density_accum_cb(void *userdata, int index, const float co[3], float UNUSED(squared_dist))
struct EfData EfData
static float sync_timestep(ParticleSystem *psys, float t_frac)
static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
static void psys_sph_flush_springs(SPHData *sphdata)
static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration, void(*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse), void *forcedata)
static int tot_particles(ParticleSystem *psys, PTCacheID *pid)
static const float TIMESTEP_EXPANSION_FACTOR
static void bvhtree_balance_isolated(void *userdata)
float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_render_params)
#define SPH_NEIGHBORS
static bool particles_has_tracer(short parttype)
void psys_count_keyed_targets(ParticleSimulationData *sim)
void psys_unique_name(Object *object, ParticleSystem *psys, const char *defname)
float(* NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor)
static void collision_interpolate_element(ParticleCollisionElement *pce, float t, float fac, ParticleCollision *col)
static bool particles_has_foam(short parttype)
void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData *sim)
void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
static void sph_spring_delete(ParticleSystem *psys, int j)
static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, float timestep)
static void dynamics_step_sph_classical_basic_integrate_task_cb_ex(void *__restrict userdata, const int p, const TaskParallelTLS *__restrict UNUSED(tls))
static void free_unexisting_particles(ParticleSimulationData *sim)
void psys_sph_init(ParticleSimulationData *sim, SPHData *sphdata)
static void sph_density_accum_cb(void *userdata, int index, const float co[3], float squared_dist)
void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
static float nr_signed_distance_to_plane(float *p, float radius, ParticleCollisionElement *pce, float *nor)
void BKE_particlesystem_reset_all(struct Object *object)
static EdgeHash * sph_springhash_build(ParticleSystem *psys)
static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params)
static bool particles_has_flip(short parttype)
static const float TIMESTEP_EXPANSION_TOLERANCE
static bool particles_has_spray(short parttype)
#define ZERO_F43
void psys_tasks_create(ParticleThreadContext *ctx, int startpart, int endpart, ParticleTask **r_tasks, int *r_numtasks)
void psys_reset(ParticleSystem *psys, int mode)
static void system_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
struct SPHNeighbor SPHNeighbor
static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
static ParticleSpring * sph_spring_add(ParticleSystem *psys, ParticleSpring *spring)
static void collision_check(ParticleSimulationData *sim, int p, float dfra, float cfra)
#define PSYS_FLUID_SPRINGS_INITIAL_SIZE
void psys_changed_type(Object *ob, ParticleSystem *psys)
void psys_sph_finalize(SPHData *sphdata)
static void set_keyed_keys(ParticleSimulationData *sim)
static void sph_springs_modify(ParticleSystem *psys, float dtime)
void particle_system_update(struct Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
static float get_base_time_step(ParticleSettings *part)
static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, float dtime, SPHData *sphdata, SpinLock *spin)
static void psys_update_effectors(ParticleSimulationData *sim)
static void collision_fail(ParticleData *pa, ParticleCollision *col)
static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from)
static ParticleSettings * particle_settings_localize(ParticleSettings *particle_settings)
static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, float *impulse)
static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, SPHData *sphdata)
int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params)
void psys_update_particle_tree(ParticleSystem *psys, float cfra)
static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra)
struct SPHRangeData SPHRangeData
static int particles_are_dynamic(ParticleSystem *psys)
struct DynamicStepSolverTaskData DynamicStepSolverTaskData
static int collision_sphere_to_verts(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
static void particle_settings_free_local(ParticleSettings *particle_settings)
void init_particle(ParticleSimulationData *sim, ParticleData *pa)
void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2])
static void particles_fluid_step(ParticleSimulationData *sim, int cfra, const bool use_render_params)
static void do_hair_dynamics(ParticleSimulationData *sim)
static void sphclassical_neighbor_accum_cb(void *userdata, int index, const float co[3], float UNUSED(squared_dist))
void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
static void psys_clear_temp_pointcache(ParticleSystem *psys)
void BKE_particle_settings_eval_reset(struct Depsgraph *depsgraph, ParticleSettings *particle_settings)
static int collision_sphere_to_edges(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
#define COLLISION_MIN_RADIUS
static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra))
static void initialize_all_particles(ParticleSimulationData *sim)
static int hair_needs_recalc(ParticleSystem *psys)
static void particlesystem_modifiersForeachIDLink(void *user_data, Object *UNUSED(object), ID **id_pointer, int cb_flag)
static void update_children(ParticleSimulationData *sim, const bool use_render_params)
static int collision_sphere_to_tri(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
static MDeformVert * hair_set_pinning(MDeformVert *dvert, float weight)
static void collision_point_velocity(ParticleCollisionElement *pce)
void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static void dynamics_step_sph_classical_integrate_task_cb_ex(void *__restrict userdata, const int p, const TaskParallelTLS *__restrict tls)
void psys_check_boid_data(ParticleSystem *psys)
void BKE_particle_system_eval_init(struct Depsgraph *depsgraph, Object *object)
#define COLLISION_INIT_STEP
void psys_thread_context_free(ParticleThreadContext *ctx)
static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, const bool use_render_params)
static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, ListBase *colliders)
static void evaluate_emitter_anim(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float cfra)
static bool psys_hair_use_simulation(ParticleData *pa, float max_length)
static void hair_create_input_mesh(ParticleSimulationData *sim, int totpoint, int totedge, Mesh **r_mesh)
void psys_tasks_free(ParticleTask *tasks, int numtasks)
void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra)
ParticleSystem * psys_get_target_system(Object *ob, ParticleTarget *pt)
#define COLLISION_MIN_DISTANCE
static const int steps
Definition: sky_nishita.cpp:19
#define min(a, b)
Definition: sort.c:35
size_t count
Definition: BLI_buffer.h:16
float co[3]
Definition: bmesh_class.h:87
float radius
Definition: BLI_kdopbvh.h:58
float cfra
Definition: BKE_boids.h:25
float dfra
Definition: BKE_boids.h:25
struct ParticleSettings * part
Definition: BKE_boids.h:24
struct Object * goal_ob
Definition: BKE_boids.h:29
struct RNG * rng
Definition: BKE_boids.h:34
float timestep
Definition: BKE_boids.h:25
struct ParticleSimulationData * sim
Definition: BKE_boids.h:23
short state_id
float health
float acc[3]
struct Object * ground
struct BoidData data
struct ListBase states
float bending_stiffness
Definition: BKE_cloth.h:45
float rot[3][3]
Definition: BKE_cloth.h:42
float loc[3]
Definition: BKE_cloth.h:41
float radius
Definition: BKE_cloth.h:44
struct ClothHairData * hairdata
struct PointCache * point_cache
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
struct EffectorWeights * effector_weights
struct Object * ob
struct CollisionModifierData * collmd
struct ColliderCache * next
ParticleSimulationData * sim
ParticleTexture ptex
ParticleData * pa
ParticleSimulationData * sim
float * ave
Definition: BKE_effect.h:31
struct MANTA * fluid
struct FluidDomainSettings * domain
float co[3]
Definition: DNA_ID.h:368
void * py_instance
Definition: DNA_ID.h:435
int recalc
Definition: DNA_ID.h:390
char name[66]
Definition: DNA_ID.h:378
void * link
Definition: BLI_linklist.h:24
void * first
Definition: DNA_listBase.h:31
struct MDeformWeight * dw
unsigned int v1
unsigned int v2
unsigned int tri[3]
float co[3]
struct MEdge * medge
CustomData vdata
struct MVert * mvert
struct MDeformVert * dvert
int totedge
int totvert
int totface
Mesh_Runtime runtime
CustomData pdata
CustomData fdata
void(* foreachIDLink)(struct ModifierData *md, struct Object *ob, IDWalkFunc walk, void *userData)
Definition: BKE_modifier.h:326
ListBase particlesystem
ListBase modifiers
float scale[3]
float imat[4][4]
float obmat[4][4]
struct Object * parent
void * data
struct ParticleSystem * psys
struct ParticleSystemModifierData * psmd_eval
struct ParticleSystem * psys_eval
struct PointCache * cache
BoidParticle * boid
ParticleKey state
ParticleKey prev_state
ParticleKey * keys
struct Collection * collision_group
struct AnimData * adt
struct BoidSettings * boids
struct EffectorWeights * effector_weights
struct SPHFluidSettings * fluid
struct Depsgraph * depsgraph
Definition: BKE_particle.h:69
struct ParticleSystemModifierData * psmd
Definition: BKE_particle.h:73
struct Scene * scene
Definition: BKE_particle.h:70
struct ParticleSystem * psys
Definition: BKE_particle.h:72
struct Object * ob
Definition: BKE_particle.h:71
struct ListBase * colliders
Definition: BKE_particle.h:74
unsigned int delete_flag
unsigned int particle_index[2]
struct ParticleSystem * psys
ParticleSpring * fluid_springs
ChildParticle * child
struct PTCacheEdit * edit
ParticleData * particles
struct ListBase targets
ParticleSettings * part
struct ListBase * effectors
struct PointCache * pointcache
struct BVHTree * bvhtree
struct ClothModifierData * clmd
struct Object * target_ob
struct Mesh * hair_in_mesh
struct KDTree_3d * tree
struct Object * parent
struct Mesh * hair_out_mesh
struct ParticleDrawData * pdd
struct ParticleCacheKey ** pathcache
void(* free_edit)(struct PTCacheEdit *edit)
struct Object * ob
struct ParticleTarget * next
ParticleThreadContext * ctx
Definition: BKE_particle.h:166
struct CurveMapping * roughcurve
Definition: BKE_particle.h:161
struct Mesh * mesh
Definition: BKE_particle.h:131
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 ParticleSeam * seams
Definition: BKE_particle.h:137
struct ParticleSimulationData sim
Definition: BKE_particle.h:130
struct KDTree_3d * tree
Definition: BKE_particle.h:135
struct ListBase mem_cache
Definition: rand.cc:33
BLI_Buffer new_springs
Definition: BKE_particle.h:97
struct EdgeHash * eh
Definition: BKE_particle.h:87
void(* force_cb)(void *sphdata_v, ParticleKey *state, float *force, float *impulse)
Definition: BKE_particle.h:100
ParticleData * pa
Definition: BKE_particle.h:85
ParticleSystem * psys[10]
Definition: BKE_particle.h:84
void(* density_cb)(void *rangedata_v, int index, const float co[3], float squared_dist)
Definition: BKE_particle.h:101
float * gravity
Definition: BKE_particle.h:88
float element_size
Definition: BKE_particle.h:93
float flow[3]
Definition: BKE_particle.h:94
int pass
Definition: BKE_particle.h:92
float mass
Definition: BKE_particle.h:86
float hfac
Definition: BKE_particle.h:89
ParticleSystem * psys
SPHNeighbor neighbors[SPH_NEIGHBORS]
ParticleSystem * npsys
ParticleData * pa
struct PhysicsSettings physics_settings
struct ToolSettings * toolsettings
struct RenderData r
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:181
size_t userdata_chunk_size
Definition: BLI_task.h:169
struct ParticleEditSettings particle
float max