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) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup bke
22  */
23 
24 #include <stdarg.h>
25 #include <stddef.h>
26 
27 #include <math.h>
28 #include <stdlib.h>
29 
30 #include "MEM_guardedalloc.h"
31 
32 #include "DNA_collection_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_listBase.h"
35 #include "DNA_mesh_types.h"
36 #include "DNA_meshdata_types.h"
37 #include "DNA_object_force_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_particle_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_texture_types.h"
42 
43 #include "BLI_blenlib.h"
44 #include "BLI_ghash.h"
45 #include "BLI_math.h"
46 #include "BLI_noise.h"
47 #include "BLI_rand.h"
48 #include "BLI_utildefines.h"
49 
50 #include "PIL_time.h"
51 
52 #include "BKE_anim_path.h" /* needed for where_on_path */
53 #include "BKE_bvhutils.h"
54 #include "BKE_collection.h"
55 #include "BKE_collision.h"
56 #include "BKE_curve.h"
57 #include "BKE_displist.h"
58 #include "BKE_effect.h"
59 #include "BKE_fluid.h"
60 #include "BKE_global.h"
61 #include "BKE_layer.h"
62 #include "BKE_modifier.h"
63 #include "BKE_object.h"
64 #include "BKE_particle.h"
65 #include "BKE_scene.h"
66 
67 #include "DEG_depsgraph.h"
68 #include "DEG_depsgraph_physics.h"
69 #include "DEG_depsgraph_query.h"
70 
71 #include "RE_render_ext.h"
72 #include "RE_shader_ext.h"
73 
BKE_effector_add_weights(Collection * collection)74 EffectorWeights *BKE_effector_add_weights(Collection *collection)
75 {
76   EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights");
77   for (int i = 0; i < NUM_PFIELD_TYPES; i++) {
78     weights->weight[i] = 1.0f;
79   }
80 
81   weights->global_gravity = 1.0f;
82 
83   weights->group = collection;
84 
85   return weights;
86 }
BKE_partdeflect_new(int type)87 PartDeflect *BKE_partdeflect_new(int type)
88 {
89   PartDeflect *pd;
90 
91   pd = MEM_callocN(sizeof(PartDeflect), "PartDeflect");
92 
93   pd->forcefield = type;
94   pd->pdef_sbdamp = 0.1f;
95   pd->pdef_sbift = 0.2f;
96   pd->pdef_sboft = 0.02f;
97   pd->pdef_cfrict = 5.0f;
98   pd->seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128;
99   pd->f_strength = 1.0f;
100   pd->f_damp = 1.0f;
101 
102   /* set sensible defaults based on type */
103   switch (type) {
104     case PFIELD_VORTEX:
105       pd->shape = PFIELD_SHAPE_PLANE;
106       break;
107     case PFIELD_WIND:
108       pd->shape = PFIELD_SHAPE_PLANE;
109       pd->f_flow = 1.0f;        /* realistic wind behavior */
110       pd->f_wind_factor = 1.0f; /* only act perpendicularly to a surface */
111       break;
112     case PFIELD_TEXTURE:
113       pd->f_size = 1.0f;
114       break;
115     case PFIELD_FLUIDFLOW:
116       pd->f_flow = 1.0f;
117       break;
118   }
119   pd->flag = PFIELD_DO_LOCATION | PFIELD_DO_ROTATION | PFIELD_CLOTH_USE_CULLING;
120 
121   return pd;
122 }
123 
124 /************************ PARTICLES ***************************/
125 
BKE_partdeflect_copy(const struct PartDeflect * pd_src)126 PartDeflect *BKE_partdeflect_copy(const struct PartDeflect *pd_src)
127 {
128   if (pd_src == NULL) {
129     return NULL;
130   }
131   PartDeflect *pd_dst = MEM_dupallocN(pd_src);
132   if (pd_dst->rng != NULL) {
133     pd_dst->rng = BLI_rng_copy(pd_dst->rng);
134   }
135   return pd_dst;
136 }
137 
BKE_partdeflect_free(PartDeflect * pd)138 void BKE_partdeflect_free(PartDeflect *pd)
139 {
140   if (!pd) {
141     return;
142   }
143   if (pd->rng) {
144     BLI_rng_free(pd->rng);
145   }
146   MEM_freeN(pd);
147 }
148 
149 /******************** EFFECTOR RELATIONS ***********************/
150 
precalculate_effector(struct Depsgraph * depsgraph,EffectorCache * eff)151 static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *eff)
152 {
153   float ctime = DEG_get_ctime(depsgraph);
154   uint cfra = (uint)(ctime >= 0 ? ctime : -ctime);
155   if (!eff->pd->rng) {
156     eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra);
157   }
158   else {
159     BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra);
160   }
161 
162   if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type == OB_CURVE) {
163     Curve *cu = eff->ob->data;
164     if (cu->flag & CU_PATH) {
165       if (eff->ob->runtime.curve_cache == NULL || eff->ob->runtime.curve_cache->path == NULL ||
166           eff->ob->runtime.curve_cache->path->data == NULL) {
167         BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false);
168       }
169 
170       if (eff->ob->runtime.curve_cache->path && eff->ob->runtime.curve_cache->path->data) {
171         where_on_path(
172             eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
173         mul_m4_v3(eff->ob->obmat, eff->guide_loc);
174         mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
175       }
176     }
177   }
178   else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) {
179     eff->surmd = (SurfaceModifierData *)BKE_modifiers_findby_type(eff->ob, eModifierType_Surface);
180     if (eff->ob->type == OB_CURVE) {
181       eff->flag |= PE_USE_NORMAL_DATA;
182     }
183   }
184   else if (eff->psys) {
185     psys_update_particle_tree(eff->psys, ctime);
186   }
187 }
188 
add_effector_relation(ListBase * relations,Object * ob,ParticleSystem * psys,PartDeflect * pd)189 static void add_effector_relation(ListBase *relations,
190                                   Object *ob,
191                                   ParticleSystem *psys,
192                                   PartDeflect *pd)
193 {
194   EffectorRelation *relation = MEM_callocN(sizeof(EffectorRelation), "EffectorRelation");
195   relation->ob = ob;
196   relation->psys = psys;
197   relation->pd = pd;
198 
199   BLI_addtail(relations, relation);
200 }
201 
add_effector_evaluation(ListBase ** effectors,Depsgraph * depsgraph,Scene * scene,Object * ob,ParticleSystem * psys,PartDeflect * pd)202 static void add_effector_evaluation(ListBase **effectors,
203                                     Depsgraph *depsgraph,
204                                     Scene *scene,
205                                     Object *ob,
206                                     ParticleSystem *psys,
207                                     PartDeflect *pd)
208 {
209   if (*effectors == NULL) {
210     *effectors = MEM_callocN(sizeof(ListBase), "effector effectors");
211   }
212 
213   EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache");
214   eff->depsgraph = depsgraph;
215   eff->scene = scene;
216   eff->ob = ob;
217   eff->psys = psys;
218   eff->pd = pd;
219   eff->frame = -1;
220   BLI_addtail(*effectors, eff);
221 
222   precalculate_effector(depsgraph, eff);
223 }
224 
225 /* Create list of effector relations in the collection or entire scene.
226  * This is used by the depsgraph to build relations, as well as faster
227  * lookup of effectors during evaluation. */
BKE_effector_relations_create(Depsgraph * depsgraph,ViewLayer * view_layer,Collection * collection)228 ListBase *BKE_effector_relations_create(Depsgraph *depsgraph,
229                                         ViewLayer *view_layer,
230                                         Collection *collection)
231 {
232   Base *base = BKE_collection_or_layer_objects(view_layer, collection);
233   const bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
234   const int base_flag = (for_render) ? BASE_ENABLED_RENDER : BASE_ENABLED_VIEWPORT;
235 
236   ListBase *relations = MEM_callocN(sizeof(ListBase), "effector relations");
237 
238   for (; base; base = base->next) {
239     if (!(base->flag & base_flag)) {
240       continue;
241     }
242 
243     Object *ob = base->object;
244 
245     if (ob->pd && ob->pd->forcefield) {
246       add_effector_relation(relations, ob, NULL, ob->pd);
247     }
248 
249     LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
250       ParticleSettings *part = psys->part;
251 
252       if (psys_check_enabled(ob, psys, for_render)) {
253         if (part->pd && part->pd->forcefield) {
254           add_effector_relation(relations, ob, psys, part->pd);
255         }
256         if (part->pd2 && part->pd2->forcefield) {
257           add_effector_relation(relations, ob, psys, part->pd2);
258         }
259       }
260     }
261   }
262 
263   return relations;
264 }
265 
BKE_effector_relations_free(ListBase * lb)266 void BKE_effector_relations_free(ListBase *lb)
267 {
268   if (lb) {
269     BLI_freelistN(lb);
270     MEM_freeN(lb);
271   }
272 }
273 
274 /* Create effective list of effectors from relations built beforehand. */
BKE_effectors_create(Depsgraph * depsgraph,Object * ob_src,ParticleSystem * psys_src,EffectorWeights * weights)275 ListBase *BKE_effectors_create(Depsgraph *depsgraph,
276                                Object *ob_src,
277                                ParticleSystem *psys_src,
278                                EffectorWeights *weights)
279 {
280   Scene *scene = DEG_get_evaluated_scene(depsgraph);
281   ListBase *relations = DEG_get_effector_relations(depsgraph, weights->group);
282   ListBase *effectors = NULL;
283 
284   if (!relations) {
285     return NULL;
286   }
287 
288   LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
289     /* Get evaluated object. */
290     Object *ob = (Object *)DEG_get_evaluated_id(depsgraph, &relation->ob->id);
291 
292     if (relation->psys) {
293       /* Get evaluated particle system. */
294       ParticleSystem *psys = BLI_findstring(
295           &ob->particlesystem, relation->psys->name, offsetof(ParticleSystem, name));
296       ParticleSettings *part = psys->part;
297 
298       if (psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0) {
299         continue;
300       }
301 
302       PartDeflect *pd = (relation->pd == relation->psys->part->pd) ? part->pd : part->pd2;
303       if (weights->weight[pd->forcefield] == 0.0f) {
304         continue;
305       }
306 
307       add_effector_evaluation(&effectors, depsgraph, scene, ob, psys, pd);
308     }
309     else {
310       /* Object effector. */
311       if (ob == ob_src) {
312         continue;
313       }
314       if (weights->weight[ob->pd->forcefield] == 0.0f) {
315         continue;
316       }
317       if (ob->pd->shape == PFIELD_SHAPE_POINTS && BKE_object_get_evaluated_mesh(ob) == NULL) {
318         continue;
319       }
320 
321       add_effector_evaluation(&effectors, depsgraph, scene, ob, NULL, ob->pd);
322     }
323   }
324 
325   return effectors;
326 }
327 
BKE_effectors_free(ListBase * lb)328 void BKE_effectors_free(ListBase *lb)
329 {
330   if (lb) {
331     LISTBASE_FOREACH (EffectorCache *, eff, lb) {
332       if (eff->guide_data) {
333         MEM_freeN(eff->guide_data);
334       }
335     }
336 
337     BLI_freelistN(lb);
338     MEM_freeN(lb);
339   }
340 }
341 
pd_point_from_particle(ParticleSimulationData * sim,ParticleData * pa,ParticleKey * state,EffectedPoint * point)342 void pd_point_from_particle(ParticleSimulationData *sim,
343                             ParticleData *pa,
344                             ParticleKey *state,
345                             EffectedPoint *point)
346 {
347   ParticleSettings *part = sim->psys->part;
348   point->loc = state->co;
349   point->vel = state->vel;
350   point->index = pa - sim->psys->particles;
351   point->size = pa->size;
352   point->charge = 0.0f;
353 
354   if (part->pd && part->pd->forcefield == PFIELD_CHARGE) {
355     point->charge += part->pd->f_strength;
356   }
357 
358   if (part->pd2 && part->pd2->forcefield == PFIELD_CHARGE) {
359     point->charge += part->pd2->f_strength;
360   }
361 
362   point->vel_to_sec = 1.0f;
363   point->vel_to_frame = psys_get_timestep(sim);
364 
365   point->flag = 0;
366 
367   if (sim->psys->part->flag & PART_ROT_DYN) {
368     point->ave = state->ave;
369     point->rot = state->rot;
370   }
371   else {
372     point->ave = point->rot = NULL;
373   }
374 
375   point->psys = sim->psys;
376 }
377 
pd_point_from_loc(Scene * scene,float * loc,float * vel,int index,EffectedPoint * point)378 void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
379 {
380   point->loc = loc;
381   point->vel = vel;
382   point->index = index;
383   point->size = 0.0f;
384 
385   point->vel_to_sec = (float)scene->r.frs_sec;
386   point->vel_to_frame = 1.0f;
387 
388   point->flag = 0;
389 
390   point->ave = point->rot = NULL;
391   point->psys = NULL;
392 }
pd_point_from_soft(Scene * scene,float * loc,float * vel,int index,EffectedPoint * point)393 void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
394 {
395   point->loc = loc;
396   point->vel = vel;
397   point->index = index;
398   point->size = 0.0f;
399 
400   point->vel_to_sec = (float)scene->r.frs_sec;
401   point->vel_to_frame = 1.0f;
402 
403   point->flag = PE_WIND_AS_SPEED;
404 
405   point->ave = point->rot = NULL;
406 
407   point->psys = NULL;
408 }
409 /************************************************/
410 /*          Effectors       */
411 /************************************************/
412 
413 // triangle - ray callback function
eff_tri_ray_hit(void * UNUSED (userData),int UNUSED (index),const BVHTreeRay * UNUSED (ray),BVHTreeRayHit * hit)414 static void eff_tri_ray_hit(void *UNUSED(userData),
415                             int UNUSED(index),
416                             const BVHTreeRay *UNUSED(ray),
417                             BVHTreeRayHit *hit)
418 {
419   /* whenever we hit a bounding box, we don't check further */
420   hit->dist = -1;
421   hit->index = 1;
422 }
423 
424 // get visibility of a wind ray
eff_calc_visibility(ListBase * colliders,EffectorCache * eff,EffectorData * efd,EffectedPoint * point)425 static float eff_calc_visibility(ListBase *colliders,
426                                  EffectorCache *eff,
427                                  EffectorData *efd,
428                                  EffectedPoint *point)
429 {
430   const int raycast_flag = BVH_RAYCAST_DEFAULT & ~BVH_RAYCAST_WATERTIGHT;
431   ListBase *colls = colliders;
432   ColliderCache *col;
433   float norm[3], len = 0.0;
434   float visibility = 1.0, absorption = 0.0;
435 
436   if (!(eff->pd->flag & PFIELD_VISIBILITY)) {
437     return visibility;
438   }
439   if (!colls) {
440     colls = BKE_collider_cache_create(eff->depsgraph, eff->ob, NULL);
441   }
442   if (!colls) {
443     return visibility;
444   }
445 
446   negate_v3_v3(norm, efd->vec_to_point);
447   len = normalize_v3(norm);
448 
449   /* check all collision objects */
450   for (col = colls->first; col; col = col->next) {
451     CollisionModifierData *collmd = col->collmd;
452 
453     if (col->ob == eff->ob) {
454       continue;
455     }
456     if (collmd->bvhtree) {
457       BVHTreeRayHit hit;
458 
459       hit.index = -1;
460       hit.dist = len + FLT_EPSILON;
461 
462       /* check if the way is blocked */
463       if (BLI_bvhtree_ray_cast_ex(collmd->bvhtree,
464                                   point->loc,
465                                   norm,
466                                   0.0f,
467                                   &hit,
468                                   eff_tri_ray_hit,
469                                   NULL,
470                                   raycast_flag) != -1) {
471         absorption = col->ob->pd->absorption;
472 
473         /* visibility is only between 0 and 1, calculated from 1-absorption */
474         visibility *= CLAMPIS(1.0f - absorption, 0.0f, 1.0f);
475 
476         if (visibility <= 0.0f) {
477           break;
478         }
479       }
480     }
481   }
482 
483   if (!colliders) {
484     BKE_collider_cache_free(&colls);
485   }
486 
487   return visibility;
488 }
489 
490 // noise function for wind e.g.
wind_func(struct RNG * rng,float strength)491 static float wind_func(struct RNG *rng, float strength)
492 {
493   int random = (BLI_rng_get_int(rng) + 1) % 128; /* max 2357 */
494   float force = BLI_rng_get_float(rng) + 1.0f;
495   float ret;
496   float sign = 0;
497 
498   /* Dividing by 2 is not giving equal sign distribution. */
499   sign = ((float)random > 64.0f) ? 1.0f : -1.0f;
500 
501   ret = sign * ((float)random / force) * strength / 128.0f;
502 
503   return ret;
504 }
505 
506 /* maxdist: zero effect from this distance outwards (if usemax) */
507 /* mindist: full effect up to this distance (if usemin) */
508 /* power: falloff with formula 1/r^power */
falloff_func(float fac,int usemin,float mindist,int usemax,float maxdist,float power)509 static float falloff_func(
510     float fac, int usemin, float mindist, int usemax, float maxdist, float power)
511 {
512   /* first quick checks */
513   if (usemax && fac > maxdist) {
514     return 0.0f;
515   }
516 
517   if (usemin && fac < mindist) {
518     return 1.0f;
519   }
520 
521   if (!usemin) {
522     mindist = 0.0;
523   }
524 
525   return pow((double)(1.0f + fac - mindist), (double)(-power));
526 }
527 
falloff_func_dist(PartDeflect * pd,float fac)528 static float falloff_func_dist(PartDeflect *pd, float fac)
529 {
530   return falloff_func(fac,
531                       pd->flag & PFIELD_USEMIN,
532                       pd->mindist,
533                       pd->flag & PFIELD_USEMAX,
534                       pd->maxdist,
535                       pd->f_power);
536 }
537 
falloff_func_rad(PartDeflect * pd,float fac)538 static float falloff_func_rad(PartDeflect *pd, float fac)
539 {
540   return falloff_func(fac,
541                       pd->flag & PFIELD_USEMINR,
542                       pd->minrad,
543                       pd->flag & PFIELD_USEMAXR,
544                       pd->maxrad,
545                       pd->f_power_r);
546 }
547 
effector_falloff(EffectorCache * eff,EffectorData * efd,EffectedPoint * UNUSED (point),EffectorWeights * weights)548 float effector_falloff(EffectorCache *eff,
549                        EffectorData *efd,
550                        EffectedPoint *UNUSED(point),
551                        EffectorWeights *weights)
552 {
553   float temp[3];
554   float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f;
555   float fac, r_fac;
556 
557   fac = dot_v3v3(efd->nor, efd->vec_to_point2);
558 
559   if (eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f) {
560     falloff = 0.0f;
561   }
562   else if (eff->pd->zdir == PFIELD_Z_NEG && fac > 0.0f) {
563     falloff = 0.0f;
564   }
565   else {
566     switch (eff->pd->falloff) {
567       case PFIELD_FALL_SPHERE:
568         falloff *= falloff_func_dist(eff->pd, efd->distance);
569         break;
570 
571       case PFIELD_FALL_TUBE:
572         falloff *= falloff_func_dist(eff->pd, fabsf(fac));
573         if (falloff == 0.0f) {
574           break;
575         }
576 
577         madd_v3_v3v3fl(temp, efd->vec_to_point2, efd->nor, -fac);
578         r_fac = len_v3(temp);
579         falloff *= falloff_func_rad(eff->pd, r_fac);
580         break;
581       case PFIELD_FALL_CONE:
582         falloff *= falloff_func_dist(eff->pd, fabsf(fac));
583         if (falloff == 0.0f) {
584           break;
585         }
586 
587         r_fac = RAD2DEGF(saacos(fac / len_v3(efd->vec_to_point2)));
588         falloff *= falloff_func_rad(eff->pd, r_fac);
589 
590         break;
591     }
592   }
593 
594   return falloff;
595 }
596 
closest_point_on_surface(SurfaceModifierData * surmd,const float co[3],float surface_co[3],float surface_nor[3],float surface_vel[3])597 int closest_point_on_surface(SurfaceModifierData *surmd,
598                              const float co[3],
599                              float surface_co[3],
600                              float surface_nor[3],
601                              float surface_vel[3])
602 {
603   BVHTreeNearest nearest;
604 
605   nearest.index = -1;
606   nearest.dist_sq = FLT_MAX;
607 
608   BLI_bvhtree_find_nearest(
609       surmd->bvhtree->tree, co, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree);
610 
611   if (nearest.index != -1) {
612     copy_v3_v3(surface_co, nearest.co);
613 
614     if (surface_nor) {
615       copy_v3_v3(surface_nor, nearest.no);
616     }
617 
618     if (surface_vel) {
619       const MLoop *mloop = surmd->bvhtree->loop;
620       const MLoopTri *lt = &surmd->bvhtree->looptri[nearest.index];
621 
622       copy_v3_v3(surface_vel, surmd->v[mloop[lt->tri[0]].v].co);
623       add_v3_v3(surface_vel, surmd->v[mloop[lt->tri[1]].v].co);
624       add_v3_v3(surface_vel, surmd->v[mloop[lt->tri[2]].v].co);
625 
626       mul_v3_fl(surface_vel, (1.0f / 3.0f));
627     }
628     return 1;
629   }
630 
631   return 0;
632 }
get_effector_data(EffectorCache * eff,EffectorData * efd,EffectedPoint * point,int real_velocity)633 int get_effector_data(EffectorCache *eff,
634                       EffectorData *efd,
635                       EffectedPoint *point,
636                       int real_velocity)
637 {
638   float cfra = DEG_get_ctime(eff->depsgraph);
639   int ret = 0;
640 
641   /* In case surface object is in Edit mode when loading the .blend,
642    * surface modifier is never executed and bvhtree never built, see T48415. */
643   if (eff->pd && eff->pd->shape == PFIELD_SHAPE_SURFACE && eff->surmd && eff->surmd->bvhtree) {
644     /* closest point in the object surface is an effector */
645     float vec[3];
646 
647     /* using velocity corrected location allows for easier sliding over effector surface */
648     copy_v3_v3(vec, point->vel);
649     mul_v3_fl(vec, point->vel_to_frame);
650     add_v3_v3(vec, point->loc);
651 
652     ret = closest_point_on_surface(
653         eff->surmd, vec, efd->loc, efd->nor, real_velocity ? efd->vel : NULL);
654 
655     efd->size = 0.0f;
656   }
657   else if (eff->pd && eff->pd->shape == PFIELD_SHAPE_POINTS) {
658     /* TODO: hair and points object support */
659     Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
660     if (me_eval != NULL) {
661       copy_v3_v3(efd->loc, me_eval->mvert[*efd->index].co);
662       normal_short_to_float_v3(efd->nor, me_eval->mvert[*efd->index].no);
663 
664       mul_m4_v3(eff->ob->obmat, efd->loc);
665       mul_mat3_m4_v3(eff->ob->obmat, efd->nor);
666 
667       normalize_v3(efd->nor);
668 
669       efd->size = 0.0f;
670 
671       ret = 1;
672     }
673   }
674   else if (eff->psys) {
675     ParticleData *pa = eff->psys->particles + *efd->index;
676     ParticleKey state;
677 
678     /* exclude the particle itself for self effecting particles */
679     if (eff->psys == point->psys && *efd->index == point->index) {
680       /* pass */
681     }
682     else {
683       ParticleSimulationData sim = {NULL};
684       sim.depsgraph = eff->depsgraph;
685       sim.scene = eff->scene;
686       sim.ob = eff->ob;
687       sim.psys = eff->psys;
688 
689       /* TODO: time from actual previous calculated frame (step might not be 1) */
690       state.time = cfra - 1.0f;
691       ret = psys_get_particle_state(&sim, *efd->index, &state, 0);
692 
693       /* TODO */
694       // if (eff->pd->forcefiled == PFIELD_HARMONIC && ret==0) {
695       //  if (pa->dietime < eff->psys->cfra)
696       //      eff->flag |= PE_VELOCITY_TO_IMPULSE;
697       //}
698 
699       copy_v3_v3(efd->loc, state.co);
700 
701       /* rather than use the velocity use rotated x-axis (defaults to velocity) */
702       efd->nor[0] = 1.f;
703       efd->nor[1] = efd->nor[2] = 0.f;
704       mul_qt_v3(state.rot, efd->nor);
705 
706       if (real_velocity) {
707         copy_v3_v3(efd->vel, state.vel);
708       }
709       efd->size = pa->size;
710     }
711   }
712   else {
713     /* use center of object for distance calculus */
714     const Object *ob = eff->ob;
715 
716     /* use z-axis as normal*/
717     normalize_v3_v3(efd->nor, ob->obmat[2]);
718 
719     if (eff->pd && ELEM(eff->pd->shape, PFIELD_SHAPE_PLANE, PFIELD_SHAPE_LINE)) {
720       float temp[3], translate[3];
721       sub_v3_v3v3(temp, point->loc, ob->obmat[3]);
722       project_v3_v3v3(translate, temp, efd->nor);
723 
724       /* for vortex the shape chooses between old / new force */
725       if (eff->pd->forcefield == PFIELD_VORTEX || eff->pd->shape == PFIELD_SHAPE_LINE) {
726         add_v3_v3v3(efd->loc, ob->obmat[3], translate);
727       }
728       else { /* normally efd->loc is closest point on effector xy-plane */
729         sub_v3_v3v3(efd->loc, point->loc, translate);
730       }
731     }
732     else {
733       copy_v3_v3(efd->loc, ob->obmat[3]);
734     }
735 
736     zero_v3(efd->vel);
737     efd->size = 0.0f;
738 
739     ret = 1;
740   }
741 
742   if (ret) {
743     sub_v3_v3v3(efd->vec_to_point, point->loc, efd->loc);
744     efd->distance = len_v3(efd->vec_to_point);
745 
746     /* Rest length for harmonic effector,
747      * will have to see later if this could be extended to other effectors. */
748     if (eff->pd && eff->pd->forcefield == PFIELD_HARMONIC && eff->pd->f_size) {
749       mul_v3_fl(efd->vec_to_point, (efd->distance - eff->pd->f_size) / efd->distance);
750     }
751 
752     if (eff->flag & PE_USE_NORMAL_DATA) {
753       copy_v3_v3(efd->vec_to_point2, efd->vec_to_point);
754       copy_v3_v3(efd->nor2, efd->nor);
755     }
756     else {
757       /* for some effectors we need the object center every time */
758       sub_v3_v3v3(efd->vec_to_point2, point->loc, eff->ob->obmat[3]);
759       normalize_v3_v3(efd->nor2, eff->ob->obmat[2]);
760     }
761   }
762 
763   return ret;
764 }
get_effector_tot(EffectorCache * eff,EffectorData * efd,EffectedPoint * point,int * tot,int * p,int * step)765 static void get_effector_tot(
766     EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step)
767 {
768   *p = 0;
769   efd->index = p;
770 
771   if (eff->pd->shape == PFIELD_SHAPE_POINTS) {
772     /* TODO: hair and points object support */
773     Mesh *me_eval = BKE_object_get_evaluated_mesh(eff->ob);
774     *tot = me_eval != NULL ? me_eval->totvert : 1;
775 
776     if (*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) {
777       *p = point->index % *tot;
778       *tot = *p + 1;
779     }
780   }
781   else if (eff->psys) {
782     *tot = eff->psys->totpart;
783 
784     if (eff->pd->forcefield == PFIELD_CHARGE) {
785       /* Only the charge of the effected particle is used for
786        * interaction, not fall-offs. If the fall-offs aren't the
787        * same this will be unphysical, but for animation this
788        * could be the wanted behavior. If you want physical
789        * correctness the fall-off should be spherical 2.0 anyways.
790        */
791       efd->charge = eff->pd->f_strength;
792     }
793     else if (eff->pd->forcefield == PFIELD_HARMONIC &&
794              (eff->pd->flag & PFIELD_MULTIPLE_SPRINGS) == 0) {
795       /* every particle is mapped to only one harmonic effector particle */
796       *p = point->index % eff->psys->totpart;
797       *tot = *p + 1;
798     }
799 
800     if (eff->psys->part->effector_amount) {
801       int totpart = eff->psys->totpart;
802       int amount = eff->psys->part->effector_amount;
803 
804       *step = (totpart > amount) ? totpart / amount : 1;
805     }
806   }
807   else {
808     *tot = 1;
809   }
810 }
do_texture_effector(EffectorCache * eff,EffectorData * efd,EffectedPoint * point,float * total_force)811 static void do_texture_effector(EffectorCache *eff,
812                                 EffectorData *efd,
813                                 EffectedPoint *point,
814                                 float *total_force)
815 {
816   TexResult result[4];
817   float tex_co[3], strength, force[3];
818   float nabla = eff->pd->tex_nabla;
819   int hasrgb;
820   short mode = eff->pd->tex_mode;
821   bool scene_color_manage;
822 
823   if (!eff->pd->tex) {
824     return;
825   }
826 
827   result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL;
828 
829   strength = eff->pd->f_strength * efd->falloff;
830 
831   copy_v3_v3(tex_co, point->loc);
832 
833   if (eff->pd->flag & PFIELD_TEX_OBJECT) {
834     mul_m4_v3(eff->ob->imat, tex_co);
835 
836     if (eff->pd->flag & PFIELD_TEX_2D) {
837       tex_co[2] = 0.0f;
838     }
839   }
840   else if (eff->pd->flag & PFIELD_TEX_2D) {
841     float fac = -dot_v3v3(tex_co, efd->nor);
842     madd_v3_v3fl(tex_co, efd->nor, fac);
843   }
844 
845   scene_color_manage = BKE_scene_check_color_management_enabled(eff->scene);
846 
847   hasrgb = multitex_ext(
848       eff->pd->tex, tex_co, NULL, NULL, 0, result, 0, NULL, scene_color_manage, false);
849 
850   if (hasrgb && mode == PFIELD_TEX_RGB) {
851     force[0] = (0.5f - result->tr) * strength;
852     force[1] = (0.5f - result->tg) * strength;
853     force[2] = (0.5f - result->tb) * strength;
854   }
855   else if (nabla != 0) {
856     strength /= nabla;
857 
858     tex_co[0] += nabla;
859     multitex_ext(
860         eff->pd->tex, tex_co, NULL, NULL, 0, result + 1, 0, NULL, scene_color_manage, false);
861 
862     tex_co[0] -= nabla;
863     tex_co[1] += nabla;
864     multitex_ext(
865         eff->pd->tex, tex_co, NULL, NULL, 0, result + 2, 0, NULL, scene_color_manage, false);
866 
867     tex_co[1] -= nabla;
868     tex_co[2] += nabla;
869     multitex_ext(
870         eff->pd->tex, tex_co, NULL, NULL, 0, result + 3, 0, NULL, scene_color_manage, false);
871 
872     if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
873       /* generate intensity if texture only has rgb value */
874       if (hasrgb & TEX_RGB) {
875         for (int i = 0; i < 4; i++) {
876           result[i].tin = (1.0f / 3.0f) * (result[i].tr + result[i].tg + result[i].tb);
877         }
878       }
879       force[0] = (result[0].tin - result[1].tin) * strength;
880       force[1] = (result[0].tin - result[2].tin) * strength;
881       force[2] = (result[0].tin - result[3].tin) * strength;
882     }
883     else { /*PFIELD_TEX_CURL*/
884       float dbdy, dgdz, drdz, dbdx, dgdx, drdy;
885 
886       dbdy = result[2].tb - result[0].tb;
887       dgdz = result[3].tg - result[0].tg;
888       drdz = result[3].tr - result[0].tr;
889       dbdx = result[1].tb - result[0].tb;
890       dgdx = result[1].tg - result[0].tg;
891       drdy = result[2].tr - result[0].tr;
892 
893       force[0] = (dbdy - dgdz) * strength;
894       force[1] = (drdz - dbdx) * strength;
895       force[2] = (dgdx - drdy) * strength;
896     }
897   }
898   else {
899     zero_v3(force);
900   }
901 
902   if (eff->pd->flag & PFIELD_TEX_2D) {
903     float fac = -dot_v3v3(force, efd->nor);
904     madd_v3_v3fl(force, efd->nor, fac);
905   }
906 
907   add_v3_v3(total_force, force);
908 }
do_physical_effector(EffectorCache * eff,EffectorData * efd,EffectedPoint * point,float * total_force)909 static void do_physical_effector(EffectorCache *eff,
910                                  EffectorData *efd,
911                                  EffectedPoint *point,
912                                  float *total_force)
913 {
914   PartDeflect *pd = eff->pd;
915   RNG *rng = pd->rng;
916   float force[3] = {0, 0, 0};
917   float temp[3];
918   float fac;
919   float strength = pd->f_strength;
920   float damp = pd->f_damp;
921   float noise_factor = pd->f_noise;
922 
923   if (noise_factor > 0.0f) {
924     strength += wind_func(rng, noise_factor);
925 
926     if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)) {
927       damp += wind_func(rng, noise_factor);
928     }
929   }
930 
931   copy_v3_v3(force, efd->vec_to_point);
932 
933   switch (pd->forcefield) {
934     case PFIELD_WIND:
935       copy_v3_v3(force, efd->nor);
936       mul_v3_fl(force, strength * efd->falloff);
937       break;
938     case PFIELD_FORCE:
939       normalize_v3(force);
940       if (pd->flag & PFIELD_GRAVITATION) { /* Option: Multiply by 1/distance^2 */
941         if (efd->distance < FLT_EPSILON) {
942           strength = 0.0f;
943         }
944         else {
945           strength *= powf(efd->distance, -2.0f);
946         }
947       }
948       mul_v3_fl(force, strength * efd->falloff);
949       break;
950     case PFIELD_VORTEX:
951       /* old vortex force */
952       if (pd->shape == PFIELD_SHAPE_POINT) {
953         cross_v3_v3v3(force, efd->nor, efd->vec_to_point);
954         normalize_v3(force);
955         mul_v3_fl(force, strength * efd->distance * efd->falloff);
956       }
957       else {
958         /* new vortex force */
959         cross_v3_v3v3(temp, efd->nor2, efd->vec_to_point2);
960         mul_v3_fl(temp, strength * efd->falloff);
961 
962         cross_v3_v3v3(force, efd->nor2, temp);
963         mul_v3_fl(force, strength * efd->falloff);
964 
965         madd_v3_v3fl(temp, point->vel, -point->vel_to_sec);
966         add_v3_v3(force, temp);
967       }
968       break;
969     case PFIELD_MAGNET:
970       if (ELEM(eff->pd->shape, PFIELD_SHAPE_POINT, PFIELD_SHAPE_LINE)) {
971         /* magnetic field of a moving charge */
972         cross_v3_v3v3(temp, efd->nor, efd->vec_to_point);
973       }
974       else {
975         copy_v3_v3(temp, efd->nor);
976       }
977 
978       normalize_v3(temp);
979       mul_v3_fl(temp, strength * efd->falloff);
980       cross_v3_v3v3(force, point->vel, temp);
981       mul_v3_fl(force, point->vel_to_sec);
982       break;
983     case PFIELD_HARMONIC:
984       mul_v3_fl(force, -strength * efd->falloff);
985       copy_v3_v3(temp, point->vel);
986       mul_v3_fl(temp, -damp * 2.0f * sqrtf(fabsf(strength)) * point->vel_to_sec);
987       add_v3_v3(force, temp);
988       break;
989     case PFIELD_CHARGE:
990       mul_v3_fl(force, point->charge * strength * efd->falloff);
991       break;
992     case PFIELD_LENNARDJ:
993       fac = pow((efd->size + point->size) / efd->distance, 6.0);
994 
995       fac = -fac * (1.0f - fac) / efd->distance;
996 
997       /* limit the repulsive term drastically to avoid huge forces */
998       fac = ((fac > 2.0f) ? 2.0f : fac);
999 
1000       mul_v3_fl(force, strength * fac);
1001       break;
1002     case PFIELD_BOID:
1003       /* Boid field is handled completely in boids code. */
1004       return;
1005     case PFIELD_TURBULENCE:
1006       if (pd->flag & PFIELD_GLOBAL_CO) {
1007         copy_v3_v3(temp, point->loc);
1008       }
1009       else {
1010         add_v3_v3v3(temp, efd->vec_to_point2, efd->nor2);
1011       }
1012       force[0] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[0], temp[1], temp[2], 2, 0, 2);
1013       force[1] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[1], temp[2], temp[0], 2, 0, 2);
1014       force[2] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[2], temp[0], temp[1], 2, 0, 2);
1015       mul_v3_fl(force, strength * efd->falloff);
1016       break;
1017     case PFIELD_DRAG:
1018       copy_v3_v3(force, point->vel);
1019       fac = normalize_v3(force) * point->vel_to_sec;
1020 
1021       strength = MIN2(strength, 2.0f);
1022       damp = MIN2(damp, 2.0f);
1023 
1024       mul_v3_fl(force, -efd->falloff * fac * (strength * fac + damp));
1025       break;
1026     case PFIELD_FLUIDFLOW:
1027       zero_v3(force);
1028 #ifdef WITH_FLUID
1029       if (pd->f_source) {
1030         float density;
1031         if ((density = BKE_fluid_get_velocity_at(pd->f_source, point->loc, force)) >= 0.0f) {
1032           float influence = strength * efd->falloff;
1033           if (pd->flag & PFIELD_SMOKE_DENSITY) {
1034             influence *= density;
1035           }
1036           mul_v3_fl(force, influence);
1037           /* apply flow */
1038           madd_v3_v3fl(total_force, point->vel, -pd->f_flow * influence);
1039         }
1040       }
1041 #endif
1042       break;
1043   }
1044 
1045   if (pd->flag & PFIELD_DO_LOCATION) {
1046     madd_v3_v3fl(total_force, force, 1.0f / point->vel_to_sec);
1047 
1048     if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_FLUIDFLOW) == 0 &&
1049         pd->f_flow != 0.0f) {
1050       madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff);
1051     }
1052   }
1053 
1054   if (pd->flag & PFIELD_DO_ROTATION && point->ave && point->rot) {
1055     float xvec[3] = {1.0f, 0.0f, 0.0f};
1056     float dave[3];
1057     mul_qt_v3(point->rot, xvec);
1058     cross_v3_v3v3(dave, xvec, force);
1059     if (pd->f_flow != 0.0f) {
1060       madd_v3_v3fl(dave, point->ave, -pd->f_flow * efd->falloff);
1061     }
1062     add_v3_v3(point->ave, dave);
1063   }
1064 }
1065 
1066 /*  -------- BKE_effectors_apply() --------
1067  * generic force/speed system, now used for particles and softbodies
1068  * scene       = scene where it runs in, for time and stuff
1069  * lb           = listbase with objects that take part in effecting
1070  * opco     = global coord, as input
1071  * force        = accumulator for force
1072  * wind_force   = accumulator for force only acting perpendicular to a surface
1073  * speed        = actual current speed which can be altered
1074  * cur_time = "external" time in frames, is constant for static particles
1075  * loc_time = "local" time in frames, range <0-1> for the lifetime of particle
1076  * par_layer    = layer the caller is in
1077  * flags        = only used for softbody wind now
1078  * guide        = old speed of particle
1079  */
BKE_effectors_apply(ListBase * effectors,ListBase * colliders,EffectorWeights * weights,EffectedPoint * point,float * force,float * wind_force,float * impulse)1080 void BKE_effectors_apply(ListBase *effectors,
1081                          ListBase *colliders,
1082                          EffectorWeights *weights,
1083                          EffectedPoint *point,
1084                          float *force,
1085                          float *wind_force,
1086                          float *impulse)
1087 {
1088   /*
1089    * Modifies the force on a particle according to its
1090    * relation with the effector object
1091    * Different kind of effectors include:
1092    *     Force-fields: Gravity-like attractor
1093    *     (force power is related to the inverse of distance to the power of a falloff value)
1094    *     Vortex fields: swirling effectors
1095    *     (particles rotate around Z-axis of the object. otherwise, same relation as)
1096    *     (Force-fields, but this is not done through a force/acceleration)
1097    *     Guide: particles on a path
1098    *     (particles are guided along a curve bezier or old nurbs)
1099    *     (is independent of other effectors)
1100    */
1101   EffectorCache *eff;
1102   EffectorData efd;
1103   int p = 0, tot = 1, step = 1;
1104 
1105   /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
1106   /* Check for min distance here? (yes would be cool to add that, ton) */
1107 
1108   if (effectors) {
1109     for (eff = effectors->first; eff; eff = eff->next) {
1110       /* object effectors were fully checked to be OK to evaluate! */
1111 
1112       get_effector_tot(eff, &efd, point, &tot, &p, &step);
1113 
1114       for (; p < tot; p += step) {
1115         if (get_effector_data(eff, &efd, point, 0)) {
1116           efd.falloff = effector_falloff(eff, &efd, point, weights);
1117 
1118           if (efd.falloff > 0.0f) {
1119             efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point);
1120           }
1121           if (efd.falloff > 0.0f) {
1122             float out_force[3] = {0, 0, 0};
1123 
1124             if (eff->pd->forcefield == PFIELD_TEXTURE) {
1125               do_texture_effector(eff, &efd, point, out_force);
1126             }
1127             else {
1128               do_physical_effector(eff, &efd, point, out_force);
1129 
1130               /* for softbody backward compatibility */
1131               if (point->flag & PE_WIND_AS_SPEED && impulse) {
1132                 sub_v3_v3v3(impulse, impulse, out_force);
1133               }
1134             }
1135 
1136             if (wind_force) {
1137               madd_v3_v3fl(force, out_force, 1.0f - eff->pd->f_wind_factor);
1138               madd_v3_v3fl(wind_force, out_force, eff->pd->f_wind_factor);
1139             }
1140             else {
1141               add_v3_v3(force, out_force);
1142             }
1143           }
1144         }
1145         else if (eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) {
1146           /* special case for harmonic effector */
1147           add_v3_v3v3(impulse, impulse, efd.vel);
1148         }
1149       }
1150     }
1151   }
1152 }
1153 
1154 /* ======== Simulation Debugging ======== */
1155 
1156 SimDebugData *_sim_debug_data = NULL;
1157 
BKE_sim_debug_data_hash(int i)1158 uint BKE_sim_debug_data_hash(int i)
1159 {
1160   return BLI_ghashutil_uinthash((uint)i);
1161 }
1162 
BKE_sim_debug_data_hash_combine(uint kx,uint ky)1163 uint BKE_sim_debug_data_hash_combine(uint kx, uint ky)
1164 {
1165 #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
1166 
1167   uint a, b, c;
1168 
1169   a = b = c = 0xdeadbeef + (2 << 2) + 13;
1170   a += kx;
1171   b += ky;
1172 
1173   c ^= b;
1174   c -= rot(b, 14);
1175   a ^= c;
1176   a -= rot(c, 11);
1177   b ^= a;
1178   b -= rot(a, 25);
1179   c ^= b;
1180   c -= rot(b, 16);
1181   a ^= c;
1182   a -= rot(c, 4);
1183   b ^= a;
1184   b -= rot(a, 14);
1185   c ^= b;
1186   c -= rot(b, 24);
1187 
1188   return c;
1189 
1190 #undef rot
1191 }
1192 
debug_element_hash(const void * key)1193 static uint debug_element_hash(const void *key)
1194 {
1195   const SimDebugElement *elem = key;
1196   return elem->hash;
1197 }
1198 
debug_element_compare(const void * a,const void * b)1199 static bool debug_element_compare(const void *a, const void *b)
1200 {
1201   const SimDebugElement *elem1 = a;
1202   const SimDebugElement *elem2 = b;
1203 
1204   if (elem1->hash == elem2->hash) {
1205     return false;
1206   }
1207   return true;
1208 }
1209 
debug_element_free(void * val)1210 static void debug_element_free(void *val)
1211 {
1212   SimDebugElement *elem = val;
1213   MEM_freeN(elem);
1214 }
1215 
BKE_sim_debug_data_set_enabled(bool enable)1216 void BKE_sim_debug_data_set_enabled(bool enable)
1217 {
1218   if (enable) {
1219     if (!_sim_debug_data) {
1220       _sim_debug_data = MEM_callocN(sizeof(SimDebugData), "sim debug data");
1221       _sim_debug_data->gh = BLI_ghash_new(
1222           debug_element_hash, debug_element_compare, "sim debug element hash");
1223     }
1224   }
1225   else {
1226     BKE_sim_debug_data_free();
1227   }
1228 }
1229 
BKE_sim_debug_data_get_enabled(void)1230 bool BKE_sim_debug_data_get_enabled(void)
1231 {
1232   return _sim_debug_data != NULL;
1233 }
1234 
BKE_sim_debug_data_free(void)1235 void BKE_sim_debug_data_free(void)
1236 {
1237   if (_sim_debug_data) {
1238     if (_sim_debug_data->gh) {
1239       BLI_ghash_free(_sim_debug_data->gh, NULL, debug_element_free);
1240     }
1241     MEM_freeN(_sim_debug_data);
1242   }
1243 }
1244 
debug_data_insert(SimDebugData * debug_data,SimDebugElement * elem)1245 static void debug_data_insert(SimDebugData *debug_data, SimDebugElement *elem)
1246 {
1247   SimDebugElement *old_elem = BLI_ghash_lookup(debug_data->gh, elem);
1248   if (old_elem) {
1249     *old_elem = *elem;
1250     MEM_freeN(elem);
1251   }
1252   else {
1253     BLI_ghash_insert(debug_data->gh, elem, elem);
1254   }
1255 }
1256 
BKE_sim_debug_data_add_element(int type,const float v1[3],const float v2[3],const char * str,float r,float g,float b,const char * category,uint hash)1257 void BKE_sim_debug_data_add_element(int type,
1258                                     const float v1[3],
1259                                     const float v2[3],
1260                                     const char *str,
1261                                     float r,
1262                                     float g,
1263                                     float b,
1264                                     const char *category,
1265                                     uint hash)
1266 {
1267   uint category_hash = BLI_ghashutil_strhash_p(category);
1268   SimDebugElement *elem;
1269 
1270   if (!_sim_debug_data) {
1271     if (G.debug & G_DEBUG_SIMDATA) {
1272       BKE_sim_debug_data_set_enabled(true);
1273     }
1274     else {
1275       return;
1276     }
1277   }
1278 
1279   elem = MEM_callocN(sizeof(SimDebugElement), "sim debug data element");
1280   elem->type = type;
1281   elem->category_hash = category_hash;
1282   elem->hash = hash;
1283   elem->color[0] = r;
1284   elem->color[1] = g;
1285   elem->color[2] = b;
1286   if (v1) {
1287     copy_v3_v3(elem->v1, v1);
1288   }
1289   else {
1290     zero_v3(elem->v1);
1291   }
1292   if (v2) {
1293     copy_v3_v3(elem->v2, v2);
1294   }
1295   else {
1296     zero_v3(elem->v2);
1297   }
1298   if (str) {
1299     BLI_strncpy(elem->str, str, sizeof(elem->str));
1300   }
1301   else {
1302     elem->str[0] = '\0';
1303   }
1304 
1305   debug_data_insert(_sim_debug_data, elem);
1306 }
1307 
BKE_sim_debug_data_remove_element(uint hash)1308 void BKE_sim_debug_data_remove_element(uint hash)
1309 {
1310   SimDebugElement dummy;
1311   if (!_sim_debug_data) {
1312     return;
1313   }
1314   dummy.hash = hash;
1315   BLI_ghash_remove(_sim_debug_data->gh, &dummy, NULL, debug_element_free);
1316 }
1317 
BKE_sim_debug_data_clear(void)1318 void BKE_sim_debug_data_clear(void)
1319 {
1320   if (!_sim_debug_data) {
1321     return;
1322   }
1323   if (_sim_debug_data->gh) {
1324     BLI_ghash_clear(_sim_debug_data->gh, NULL, debug_element_free);
1325   }
1326 }
1327 
BKE_sim_debug_data_clear_category(const char * category)1328 void BKE_sim_debug_data_clear_category(const char *category)
1329 {
1330   int category_hash = (int)BLI_ghashutil_strhash_p(category);
1331 
1332   if (!_sim_debug_data) {
1333     return;
1334   }
1335 
1336   if (_sim_debug_data->gh) {
1337     GHashIterator iter;
1338     BLI_ghashIterator_init(&iter, _sim_debug_data->gh);
1339     while (!BLI_ghashIterator_done(&iter)) {
1340       const SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
1341 
1342       /* Removing invalidates the current iterator, so step before removing. */
1343       BLI_ghashIterator_step(&iter);
1344 
1345       if (elem->category_hash == category_hash) {
1346         BLI_ghash_remove(_sim_debug_data->gh, elem, NULL, debug_element_free);
1347       }
1348     }
1349   }
1350 }
1351