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