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