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 */
19
20 /** \file
21 * \ingroup bke
22 */
23
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "DNA_defaults.h"
31
32 #include "DNA_collection_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_dynamicpaint_types.h"
35 #include "DNA_fluid_types.h"
36 #include "DNA_key_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_particle_types.h"
41 #include "DNA_scene_types.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_kdopbvh.h"
45 #include "BLI_kdtree.h"
46 #include "BLI_linklist.h"
47 #include "BLI_math.h"
48 #include "BLI_rand.h"
49 #include "BLI_task.h"
50 #include "BLI_threads.h"
51 #include "BLI_utildefines.h"
52
53 #include "BLT_translation.h"
54
55 #include "BKE_anim_path.h"
56 #include "BKE_boids.h"
57 #include "BKE_cloth.h"
58 #include "BKE_collection.h"
59 #include "BKE_colortools.h"
60 #include "BKE_deform.h"
61 #include "BKE_displist.h"
62 #include "BKE_effect.h"
63 #include "BKE_idtype.h"
64 #include "BKE_key.h"
65 #include "BKE_lattice.h"
66 #include "BKE_lib_id.h"
67 #include "BKE_lib_query.h"
68 #include "BKE_main.h"
69 #include "BKE_material.h"
70 #include "BKE_mesh.h"
71 #include "BKE_modifier.h"
72 #include "BKE_particle.h"
73 #include "BKE_pointcache.h"
74 #include "BKE_scene.h"
75 #include "BKE_texture.h"
76
77 #include "DEG_depsgraph.h"
78 #include "DEG_depsgraph_build.h"
79 #include "DEG_depsgraph_query.h"
80
81 #include "RE_render_ext.h"
82
83 #include "particle_private.h"
84
85 static void fluid_free_settings(SPHFluidSettings *fluid);
86
particle_settings_init(ID * id)87 static void particle_settings_init(ID *id)
88 {
89 ParticleSettings *particle_settings = (ParticleSettings *)id;
90 BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(particle_settings, id));
91
92 MEMCPY_STRUCT_AFTER(particle_settings, DNA_struct_default_get(ParticleSettings), id);
93
94 particle_settings->effector_weights = BKE_effector_add_weights(NULL);
95 }
96
particle_settings_copy_data(Main * UNUSED (bmain),ID * id_dst,const ID * id_src,const int UNUSED (flag))97 static void particle_settings_copy_data(Main *UNUSED(bmain),
98 ID *id_dst,
99 const ID *id_src,
100 const int UNUSED(flag))
101 {
102 ParticleSettings *particle_settings_dst = (ParticleSettings *)id_dst;
103 const ParticleSettings *partticle_settings_src = (const ParticleSettings *)id_src;
104
105 particle_settings_dst->pd = BKE_partdeflect_copy(partticle_settings_src->pd);
106 particle_settings_dst->pd2 = BKE_partdeflect_copy(partticle_settings_src->pd2);
107 particle_settings_dst->effector_weights = MEM_dupallocN(
108 partticle_settings_src->effector_weights);
109 particle_settings_dst->fluid = MEM_dupallocN(partticle_settings_src->fluid);
110
111 if (partticle_settings_src->clumpcurve) {
112 particle_settings_dst->clumpcurve = BKE_curvemapping_copy(partticle_settings_src->clumpcurve);
113 }
114 if (partticle_settings_src->roughcurve) {
115 particle_settings_dst->roughcurve = BKE_curvemapping_copy(partticle_settings_src->roughcurve);
116 }
117 if (partticle_settings_src->twistcurve) {
118 particle_settings_dst->twistcurve = BKE_curvemapping_copy(partticle_settings_src->twistcurve);
119 }
120
121 particle_settings_dst->boids = boid_copy_settings(partticle_settings_src->boids);
122
123 for (int a = 0; a < MAX_MTEX; a++) {
124 if (partticle_settings_src->mtex[a]) {
125 particle_settings_dst->mtex[a] = MEM_dupallocN(partticle_settings_src->mtex[a]);
126 }
127 }
128
129 BLI_duplicatelist(&particle_settings_dst->instance_weights,
130 &partticle_settings_src->instance_weights);
131 }
132
particle_settings_free_data(ID * id)133 static void particle_settings_free_data(ID *id)
134 {
135 ParticleSettings *particle_settings = (ParticleSettings *)id;
136
137 for (int a = 0; a < MAX_MTEX; a++) {
138 MEM_SAFE_FREE(particle_settings->mtex[a]);
139 }
140
141 if (particle_settings->clumpcurve) {
142 BKE_curvemapping_free(particle_settings->clumpcurve);
143 }
144 if (particle_settings->roughcurve) {
145 BKE_curvemapping_free(particle_settings->roughcurve);
146 }
147 if (particle_settings->twistcurve) {
148 BKE_curvemapping_free(particle_settings->twistcurve);
149 }
150
151 BKE_partdeflect_free(particle_settings->pd);
152 BKE_partdeflect_free(particle_settings->pd2);
153
154 MEM_SAFE_FREE(particle_settings->effector_weights);
155
156 BLI_freelistN(&particle_settings->instance_weights);
157
158 boid_free_settings(particle_settings->boids);
159 fluid_free_settings(particle_settings->fluid);
160 }
161
particle_settings_foreach_id(ID * id,LibraryForeachIDData * data)162 static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data)
163 {
164 ParticleSettings *psett = (ParticleSettings *)id;
165 BKE_LIB_FOREACHID_PROCESS(data, psett->instance_collection, IDWALK_CB_USER);
166 BKE_LIB_FOREACHID_PROCESS(data, psett->instance_object, IDWALK_CB_NOP);
167 BKE_LIB_FOREACHID_PROCESS(data, psett->bb_ob, IDWALK_CB_NOP);
168 BKE_LIB_FOREACHID_PROCESS(data, psett->collision_group, IDWALK_CB_NOP);
169
170 for (int i = 0; i < MAX_MTEX; i++) {
171 if (psett->mtex[i]) {
172 BKE_texture_mtex_foreach_id(data, psett->mtex[i]);
173 }
174 }
175
176 if (psett->effector_weights) {
177 BKE_LIB_FOREACHID_PROCESS(data, psett->effector_weights->group, IDWALK_CB_NOP);
178 }
179
180 if (psett->pd) {
181 BKE_LIB_FOREACHID_PROCESS(data, psett->pd->tex, IDWALK_CB_USER);
182 BKE_LIB_FOREACHID_PROCESS(data, psett->pd->f_source, IDWALK_CB_NOP);
183 }
184 if (psett->pd2) {
185 BKE_LIB_FOREACHID_PROCESS(data, psett->pd2->tex, IDWALK_CB_USER);
186 BKE_LIB_FOREACHID_PROCESS(data, psett->pd2->f_source, IDWALK_CB_NOP);
187 }
188
189 if (psett->boids) {
190 LISTBASE_FOREACH (BoidState *, state, &psett->boids->states) {
191 LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
192 if (rule->type == eBoidRuleType_Avoid) {
193 BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
194 BKE_LIB_FOREACHID_PROCESS(data, gabr->ob, IDWALK_CB_NOP);
195 }
196 else if (rule->type == eBoidRuleType_FollowLeader) {
197 BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
198 BKE_LIB_FOREACHID_PROCESS(data, flbr->ob, IDWALK_CB_NOP);
199 }
200 }
201 }
202 }
203
204 LISTBASE_FOREACH (ParticleDupliWeight *, dw, &psett->instance_weights) {
205 BKE_LIB_FOREACHID_PROCESS(data, dw->ob, IDWALK_CB_NOP);
206 }
207 }
208
209 IDTypeInfo IDType_ID_PA = {
210 .id_code = ID_PA,
211 .id_filter = FILTER_ID_PA,
212 .main_listbase_index = INDEX_ID_PA,
213 .struct_size = sizeof(ParticleSettings),
214 .name = "ParticleSettings",
215 .name_plural = "particles",
216 .translation_context = BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
217 .flags = 0,
218
219 .init_data = particle_settings_init,
220 .copy_data = particle_settings_copy_data,
221 .free_data = particle_settings_free_data,
222 .make_local = NULL,
223 .foreach_id = particle_settings_foreach_id,
224 .foreach_cache = NULL,
225
226 .blend_write = NULL,
227 .blend_read_data = NULL,
228 .blend_read_lib = NULL,
229 .blend_read_expand = NULL,
230 };
231
232 unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
233 unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
234 float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];
235
psys_init_rng(void)236 void psys_init_rng(void)
237 {
238 RNG *rng = BLI_rng_new_srandom(5831); /* arbitrary */
239 for (int i = 0; i < PSYS_FRAND_COUNT; i++) {
240 PSYS_FRAND_BASE[i] = BLI_rng_get_float(rng);
241 PSYS_FRAND_SEED_OFFSET[i] = (unsigned int)BLI_rng_get_int(rng);
242 PSYS_FRAND_SEED_MULTIPLIER[i] = (unsigned int)BLI_rng_get_int(rng);
243 }
244 BLI_rng_free(rng);
245 }
246
247 static void get_child_modifier_parameters(ParticleSettings *part,
248 ParticleThreadContext *ctx,
249 ChildParticle *cpa,
250 short cpa_from,
251 int cpa_num,
252 float *cpa_fuv,
253 float *orco,
254 ParticleTexture *ptex);
255 static void get_cpa_texture(Mesh *mesh,
256 ParticleSystem *psys,
257 ParticleSettings *part,
258 ParticleData *par,
259 int child_index,
260 int face_index,
261 const float fw[4],
262 float *orco,
263 ParticleTexture *ptex,
264 int event,
265 float cfra);
266
267 /* few helpers for countall etc. */
count_particles(ParticleSystem * psys)268 int count_particles(ParticleSystem *psys)
269 {
270 ParticleSettings *part = psys->part;
271 PARTICLE_P;
272 int tot = 0;
273
274 LOOP_SHOWN_PARTICLES
275 {
276 if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {
277 }
278 else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {
279 }
280 else {
281 tot++;
282 }
283 }
284 return tot;
285 }
count_particles_mod(ParticleSystem * psys,int totgr,int cur)286 int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
287 {
288 ParticleSettings *part = psys->part;
289 PARTICLE_P;
290 int tot = 0;
291
292 LOOP_SHOWN_PARTICLES
293 {
294 if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {
295 }
296 else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {
297 }
298 else if (p % totgr == cur) {
299 tot++;
300 }
301 }
302 return tot;
303 }
304 /* We allocate path cache memory in chunks instead of a big contiguous
305 * chunk, windows' memory allocator fails to find big blocks of memory often. */
306
307 #define PATH_CACHE_BUF_SIZE 1024
308
pcache_key_segment_endpoint_safe(ParticleCacheKey * key)309 static ParticleCacheKey *pcache_key_segment_endpoint_safe(ParticleCacheKey *key)
310 {
311 return (key->segments > 0) ? (key + (key->segments - 1)) : key;
312 }
313
psys_alloc_path_cache_buffers(ListBase * bufs,int tot,int totkeys)314 static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int totkeys)
315 {
316 LinkData *buf;
317 ParticleCacheKey **cache;
318 int i, totkey, totbufkey;
319
320 tot = MAX2(tot, 1);
321 totkey = 0;
322 cache = MEM_callocN(tot * sizeof(void *), "PathCacheArray");
323
324 while (totkey < tot) {
325 totbufkey = MIN2(tot - totkey, PATH_CACHE_BUF_SIZE);
326 buf = MEM_callocN(sizeof(LinkData), "PathCacheLinkData");
327 buf->data = MEM_callocN(sizeof(ParticleCacheKey) * totbufkey * totkeys, "ParticleCacheKey");
328
329 for (i = 0; i < totbufkey; i++) {
330 cache[totkey + i] = ((ParticleCacheKey *)buf->data) + i * totkeys;
331 }
332
333 totkey += totbufkey;
334 BLI_addtail(bufs, buf);
335 }
336
337 return cache;
338 }
339
psys_free_path_cache_buffers(ParticleCacheKey ** cache,ListBase * bufs)340 static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *bufs)
341 {
342 LinkData *buf;
343
344 if (cache) {
345 MEM_freeN(cache);
346 }
347
348 for (buf = bufs->first; buf; buf = buf->next) {
349 MEM_freeN(buf->data);
350 }
351 BLI_freelistN(bufs);
352 }
353
354 /************************************************/
355 /* Getting stuff */
356 /************************************************/
357 /* get object's active particle system safely */
psys_get_current(Object * ob)358 ParticleSystem *psys_get_current(Object *ob)
359 {
360 ParticleSystem *psys;
361 if (ob == NULL) {
362 return NULL;
363 }
364
365 for (psys = ob->particlesystem.first; psys; psys = psys->next) {
366 if (psys->flag & PSYS_CURRENT) {
367 return psys;
368 }
369 }
370
371 return NULL;
372 }
psys_get_current_num(Object * ob)373 short psys_get_current_num(Object *ob)
374 {
375 ParticleSystem *psys;
376 short i;
377
378 if (ob == NULL) {
379 return 0;
380 }
381
382 for (psys = ob->particlesystem.first, i = 0; psys; psys = psys->next, i++) {
383 if (psys->flag & PSYS_CURRENT) {
384 return i;
385 }
386 }
387
388 return i;
389 }
psys_set_current_num(Object * ob,int index)390 void psys_set_current_num(Object *ob, int index)
391 {
392 ParticleSystem *psys;
393 short i;
394
395 if (ob == NULL) {
396 return;
397 }
398
399 for (psys = ob->particlesystem.first, i = 0; psys; psys = psys->next, i++) {
400 if (i == index) {
401 psys->flag |= PSYS_CURRENT;
402 }
403 else {
404 psys->flag &= ~PSYS_CURRENT;
405 }
406 }
407 }
408
psys_create_lattice_deform_data(ParticleSimulationData * sim)409 struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim)
410 {
411 struct LatticeDeformData *lattice_deform_data = NULL;
412
413 if (psys_in_edit_mode(sim->depsgraph, sim->psys) == 0) {
414 Object *lattice = NULL;
415 ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
416 bool for_render = DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER;
417 int mode = for_render ? eModifierMode_Render : eModifierMode_Realtime;
418
419 for (; md; md = md->next) {
420 if (md->type == eModifierType_Lattice) {
421 if (md->mode & mode) {
422 LatticeModifierData *lmd = (LatticeModifierData *)md;
423 lattice = lmd->object;
424 sim->psys->lattice_strength = lmd->strength;
425 }
426
427 break;
428 }
429 }
430 if (lattice) {
431 lattice_deform_data = BKE_lattice_deform_data_create(lattice, NULL);
432 }
433 }
434
435 return lattice_deform_data;
436 }
psys_disable_all(Object * ob)437 void psys_disable_all(Object *ob)
438 {
439 ParticleSystem *psys = ob->particlesystem.first;
440
441 for (; psys; psys = psys->next) {
442 psys->flag |= PSYS_DISABLED;
443 }
444 }
psys_enable_all(Object * ob)445 void psys_enable_all(Object *ob)
446 {
447 ParticleSystem *psys = ob->particlesystem.first;
448
449 for (; psys; psys = psys->next) {
450 psys->flag &= ~PSYS_DISABLED;
451 }
452 }
453
psys_orig_get(ParticleSystem * psys)454 ParticleSystem *psys_orig_get(ParticleSystem *psys)
455 {
456 if (psys->orig_psys == NULL) {
457 return psys;
458 }
459 return psys->orig_psys;
460 }
461
psys_eval_get(Depsgraph * depsgraph,Object * object,ParticleSystem * psys)462 struct ParticleSystem *psys_eval_get(Depsgraph *depsgraph, Object *object, ParticleSystem *psys)
463 {
464 Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
465 if (object_eval == object) {
466 return psys;
467 }
468 ParticleSystem *psys_eval = object_eval->particlesystem.first;
469 while (psys_eval != NULL) {
470 if (psys_eval->orig_psys == psys) {
471 return psys_eval;
472 }
473 psys_eval = psys_eval->next;
474 }
475 return psys_eval;
476 }
477
psys_orig_edit_get(ParticleSystem * psys)478 static PTCacheEdit *psys_orig_edit_get(ParticleSystem *psys)
479 {
480 if (psys->orig_psys == NULL) {
481 return psys->edit;
482 }
483 return psys->orig_psys->edit;
484 }
485
psys_in_edit_mode(Depsgraph * depsgraph,const ParticleSystem * psys)486 bool psys_in_edit_mode(Depsgraph *depsgraph, const ParticleSystem *psys)
487 {
488 const ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
489 if (view_layer->basact == NULL) {
490 /* TODO(sergey): Needs double-check with multi-object edit. */
491 return false;
492 }
493 const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
494 const Object *object = view_layer->basact->object;
495 if (object->mode != OB_MODE_PARTICLE_EDIT) {
496 return false;
497 }
498 const ParticleSystem *psys_orig = psys_orig_get((ParticleSystem *)psys);
499 return (psys_orig->edit || psys->pointcache->edit) && (use_render_params == false);
500 }
501
psys_check_enabled(Object * ob,ParticleSystem * psys,const bool use_render_params)502 bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
503 {
504 ParticleSystemModifierData *psmd;
505
506 if (psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part) {
507 return 0;
508 }
509
510 psmd = psys_get_modifier(ob, psys);
511
512 if (!psmd) {
513 return 0;
514 }
515
516 if (use_render_params) {
517 if (!(psmd->modifier.mode & eModifierMode_Render)) {
518 return 0;
519 }
520 }
521 else if (!(psmd->modifier.mode & eModifierMode_Realtime)) {
522 return 0;
523 }
524
525 return 1;
526 }
527
psys_check_edited(ParticleSystem * psys)528 bool psys_check_edited(ParticleSystem *psys)
529 {
530 if (psys->part && psys->part->type == PART_HAIR) {
531 return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited));
532 }
533
534 return (psys->pointcache->edit && psys->pointcache->edit->edited);
535 }
536
psys_find_group_weights(ParticleSettings * part)537 void psys_find_group_weights(ParticleSettings *part)
538 {
539 /* Find object pointers based on index. If the collection is linked from
540 * another library linking may not have the object pointers available on
541 * file load, so we have to retrieve them later. See T49273. */
542 ListBase instance_collection_objects = {NULL, NULL};
543
544 if (part->instance_collection) {
545 instance_collection_objects = BKE_collection_object_cache_get(part->instance_collection);
546 }
547
548 LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
549 if (dw->ob == NULL) {
550 Base *base = BLI_findlink(&instance_collection_objects, dw->index);
551 if (base != NULL) {
552 dw->ob = base->object;
553 }
554 }
555 }
556 }
557
psys_check_group_weights(ParticleSettings * part)558 void psys_check_group_weights(ParticleSettings *part)
559 {
560 ParticleDupliWeight *dw, *tdw;
561
562 if (part->ren_as != PART_DRAW_GR || !part->instance_collection) {
563 BLI_freelistN(&part->instance_weights);
564 return;
565 }
566
567 /* Find object pointers. */
568 psys_find_group_weights(part);
569
570 /* Remove NULL objects, that were removed from the collection. */
571 dw = part->instance_weights.first;
572 while (dw) {
573 if (dw->ob == NULL ||
574 !BKE_collection_has_object_recursive(part->instance_collection, dw->ob)) {
575 tdw = dw->next;
576 BLI_freelinkN(&part->instance_weights, dw);
577 dw = tdw;
578 }
579 else {
580 dw = dw->next;
581 }
582 }
583
584 /* Add new objects in the collection. */
585 int index = 0;
586 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
587 dw = part->instance_weights.first;
588 while (dw && dw->ob != object) {
589 dw = dw->next;
590 }
591
592 if (!dw) {
593 dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
594 dw->ob = object;
595 dw->count = 1;
596 BLI_addtail(&part->instance_weights, dw);
597 }
598
599 dw->index = index++;
600 }
601 FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
602
603 /* Ensure there is an element marked as current. */
604 int current = 0;
605 for (dw = part->instance_weights.first; dw; dw = dw->next) {
606 if (dw->flag & PART_DUPLIW_CURRENT) {
607 current = 1;
608 break;
609 }
610 }
611
612 if (!current) {
613 dw = part->instance_weights.first;
614 if (dw) {
615 dw->flag |= PART_DUPLIW_CURRENT;
616 }
617 }
618 }
619
psys_uses_gravity(ParticleSimulationData * sim)620 int psys_uses_gravity(ParticleSimulationData *sim)
621 {
622 return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part &&
623 sim->psys->part->effector_weights->global_gravity != 0.0f;
624 }
625 /************************************************/
626 /* Freeing stuff */
627 /************************************************/
fluid_free_settings(SPHFluidSettings * fluid)628 static void fluid_free_settings(SPHFluidSettings *fluid)
629 {
630 if (fluid) {
631 MEM_freeN(fluid);
632 }
633 }
634
free_hair(Object * object,ParticleSystem * psys,int dynamics)635 void free_hair(Object *object, ParticleSystem *psys, int dynamics)
636 {
637 PARTICLE_P;
638
639 LOOP_PARTICLES
640 {
641 if (pa->hair) {
642 MEM_freeN(pa->hair);
643 }
644 pa->hair = NULL;
645 pa->totkey = 0;
646 }
647
648 psys->flag &= ~PSYS_HAIR_DONE;
649
650 if (psys->clmd) {
651 if (dynamics) {
652 BKE_modifier_free((ModifierData *)psys->clmd);
653 psys->clmd = NULL;
654 PTCacheID pid;
655 BKE_ptcache_id_from_particles(&pid, object, psys);
656 BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
657 }
658 else {
659 cloth_free_modifier(psys->clmd);
660 }
661 }
662
663 if (psys->hair_in_mesh) {
664 BKE_id_free(NULL, psys->hair_in_mesh);
665 }
666 psys->hair_in_mesh = NULL;
667
668 if (psys->hair_out_mesh) {
669 BKE_id_free(NULL, psys->hair_out_mesh);
670 }
671 psys->hair_out_mesh = NULL;
672 }
free_keyed_keys(ParticleSystem * psys)673 void free_keyed_keys(ParticleSystem *psys)
674 {
675 PARTICLE_P;
676
677 if (psys->part->type == PART_HAIR) {
678 return;
679 }
680
681 if (psys->particles && psys->particles->keys) {
682 MEM_freeN(psys->particles->keys);
683
684 LOOP_PARTICLES
685 {
686 if (pa->keys) {
687 pa->keys = NULL;
688 pa->totkey = 0;
689 }
690 }
691 }
692 }
free_child_path_cache(ParticleSystem * psys)693 static void free_child_path_cache(ParticleSystem *psys)
694 {
695 psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs);
696 psys->childcache = NULL;
697 psys->totchildcache = 0;
698 }
psys_free_path_cache(ParticleSystem * psys,PTCacheEdit * edit)699 void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit)
700 {
701 if (edit) {
702 psys_free_path_cache_buffers(edit->pathcache, &edit->pathcachebufs);
703 edit->pathcache = NULL;
704 edit->totcached = 0;
705 }
706 if (psys) {
707 psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs);
708 psys->pathcache = NULL;
709 psys->totcached = 0;
710
711 free_child_path_cache(psys);
712 }
713 }
psys_free_children(ParticleSystem * psys)714 void psys_free_children(ParticleSystem *psys)
715 {
716 if (psys->child) {
717 MEM_freeN(psys->child);
718 psys->child = NULL;
719 psys->totchild = 0;
720 }
721
722 free_child_path_cache(psys);
723 }
psys_free_particles(ParticleSystem * psys)724 void psys_free_particles(ParticleSystem *psys)
725 {
726 PARTICLE_P;
727
728 if (psys->particles) {
729 /* Even though psys->part should never be NULL,
730 * this can happen as an exception during deletion.
731 * See ID_REMAP_SKIP/FORCE/FLAG_NEVER_NULL_USAGE in BKE_library_remap. */
732 if (psys->part && psys->part->type == PART_HAIR) {
733 LOOP_PARTICLES
734 {
735 if (pa->hair) {
736 MEM_freeN(pa->hair);
737 }
738 }
739 }
740
741 if (psys->particles->keys) {
742 MEM_freeN(psys->particles->keys);
743 }
744
745 if (psys->particles->boid) {
746 MEM_freeN(psys->particles->boid);
747 }
748
749 MEM_freeN(psys->particles);
750 psys->particles = NULL;
751 psys->totpart = 0;
752 }
753 }
psys_free_pdd(ParticleSystem * psys)754 void psys_free_pdd(ParticleSystem *psys)
755 {
756 if (psys->pdd) {
757 if (psys->pdd->cdata) {
758 MEM_freeN(psys->pdd->cdata);
759 }
760 psys->pdd->cdata = NULL;
761
762 if (psys->pdd->vdata) {
763 MEM_freeN(psys->pdd->vdata);
764 }
765 psys->pdd->vdata = NULL;
766
767 if (psys->pdd->ndata) {
768 MEM_freeN(psys->pdd->ndata);
769 }
770 psys->pdd->ndata = NULL;
771
772 if (psys->pdd->vedata) {
773 MEM_freeN(psys->pdd->vedata);
774 }
775 psys->pdd->vedata = NULL;
776
777 psys->pdd->totpoint = 0;
778 psys->pdd->totpart = 0;
779 psys->pdd->partsize = 0;
780 }
781 }
782 /* free everything */
psys_free(Object * ob,ParticleSystem * psys)783 void psys_free(Object *ob, ParticleSystem *psys)
784 {
785 if (psys) {
786 int nr = 0;
787 ParticleSystem *tpsys;
788
789 psys_free_path_cache(psys, NULL);
790
791 /* NOTE: We pass dynamics=0 to free_hair() to prevent it from doing an
792 * unneeded clear of the cache. But for historical reason that code path
793 * was only clearing cloth part of modifier data.
794 *
795 * Part of the story there is that particle evaluation is trying to not
796 * re-allocate thew ModifierData itself, and limits all allocations to
797 * the cloth part of it.
798 *
799 * Why evaluation is relying on hair_free() and in some specific code
800 * paths there is beyond me.
801 */
802 free_hair(ob, psys, 0);
803 if (psys->clmd != NULL) {
804 BKE_modifier_free((ModifierData *)psys->clmd);
805 }
806
807 psys_free_particles(psys);
808
809 if (psys->edit && psys->free_edit) {
810 psys->free_edit(psys->edit);
811 }
812
813 if (psys->child) {
814 MEM_freeN(psys->child);
815 psys->child = NULL;
816 psys->totchild = 0;
817 }
818
819 /* check if we are last non-visible particle system */
820 for (tpsys = ob->particlesystem.first; tpsys; tpsys = tpsys->next) {
821 if (tpsys->part) {
822 if (ELEM(tpsys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
823 nr++;
824 break;
825 }
826 }
827 }
828 /* clear do-not-draw-flag */
829 if (!nr) {
830 ob->transflag &= ~OB_DUPLIPARTS;
831 }
832
833 psys->part = NULL;
834
835 if ((psys->flag & PSYS_SHARED_CACHES) == 0) {
836 BKE_ptcache_free_list(&psys->ptcaches);
837 }
838 psys->pointcache = NULL;
839
840 BLI_freelistN(&psys->targets);
841
842 BLI_bvhtree_free(psys->bvhtree);
843 BLI_kdtree_3d_free(psys->tree);
844
845 if (psys->fluid_springs) {
846 MEM_freeN(psys->fluid_springs);
847 }
848
849 BKE_effectors_free(psys->effectors);
850
851 if (psys->pdd) {
852 psys_free_pdd(psys);
853 MEM_freeN(psys->pdd);
854 }
855
856 BKE_particle_batch_cache_free(psys);
857
858 MEM_freeN(psys);
859 }
860 }
861
psys_copy_particles(ParticleSystem * psys_dst,ParticleSystem * psys_src)862 void psys_copy_particles(ParticleSystem *psys_dst, ParticleSystem *psys_src)
863 {
864 /* Free existing particles. */
865 if (psys_dst->particles != psys_src->particles) {
866 psys_free_particles(psys_dst);
867 }
868 if (psys_dst->child != psys_src->child) {
869 psys_free_children(psys_dst);
870 }
871 /* Restore counters. */
872 psys_dst->totpart = psys_src->totpart;
873 psys_dst->totchild = psys_src->totchild;
874 /* Copy particles and children. */
875 psys_dst->particles = MEM_dupallocN(psys_src->particles);
876 psys_dst->child = MEM_dupallocN(psys_src->child);
877 if (psys_dst->part->type == PART_HAIR) {
878 ParticleData *pa;
879 int p;
880 for (p = 0, pa = psys_dst->particles; p < psys_dst->totpart; p++, pa++) {
881 pa->hair = MEM_dupallocN(pa->hair);
882 }
883 }
884 if (psys_dst->particles && (psys_dst->particles->keys || psys_dst->particles->boid)) {
885 ParticleKey *key = psys_dst->particles->keys;
886 BoidParticle *boid = psys_dst->particles->boid;
887 ParticleData *pa;
888 int p;
889 if (key != NULL) {
890 key = MEM_dupallocN(key);
891 }
892 if (boid != NULL) {
893 boid = MEM_dupallocN(boid);
894 }
895 for (p = 0, pa = psys_dst->particles; p < psys_dst->totpart; p++, pa++) {
896 if (boid != NULL) {
897 pa->boid = boid++;
898 }
899 if (key != NULL) {
900 pa->keys = key;
901 key += pa->totkey;
902 }
903 }
904 }
905 }
906
907 /************************************************/
908 /* Interpolation */
909 /************************************************/
interpolate_particle_value(float v1,float v2,float v3,float v4,const float w[4],int four)910 static float interpolate_particle_value(
911 float v1, float v2, float v3, float v4, const float w[4], int four)
912 {
913 float value;
914
915 value = w[0] * v1 + w[1] * v2 + w[2] * v3;
916 if (four) {
917 value += w[3] * v4;
918 }
919
920 CLAMP(value, 0.f, 1.f);
921
922 return value;
923 }
924
psys_interpolate_particle(short type,ParticleKey keys[4],float dt,ParticleKey * result,bool velocity)925 void psys_interpolate_particle(
926 short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity)
927 {
928 float t[4];
929
930 if (type < 0) {
931 interp_cubic_v3(result->co, result->vel, keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt);
932 }
933 else {
934 key_curve_position_weights(dt, t, type);
935
936 interp_v3_v3v3v3v3(result->co, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
937
938 if (velocity) {
939 float temp[3];
940
941 if (dt > 0.999f) {
942 key_curve_position_weights(dt - 0.001f, t, type);
943 interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
944 sub_v3_v3v3(result->vel, result->co, temp);
945 }
946 else {
947 key_curve_position_weights(dt + 0.001f, t, type);
948 interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
949 sub_v3_v3v3(result->vel, temp, result->co);
950 }
951 }
952 }
953 }
954
955 typedef struct ParticleInterpolationData {
956 HairKey *hkey[2];
957
958 Mesh *mesh;
959 MVert *mvert[2];
960
961 int keyed;
962 ParticleKey *kkey[2];
963
964 PointCache *cache;
965 PTCacheMem *pm;
966
967 PTCacheEditPoint *epoint;
968 PTCacheEditKey *ekey[2];
969
970 float birthtime, dietime;
971 int bspline;
972 } ParticleInterpolationData;
973 /**
974 * Assumes pointcache->mem_cache exists, so for disk cached particles
975 * call #psys_make_temp_pointcache() before use.
976 * It uses #ParticleInterpolationData.pm to store the current memory cache frame
977 * so it's thread safe.
978 */
get_pointcache_keys_for_time(Object * UNUSED (ob),PointCache * cache,PTCacheMem ** cur,int index,float t,ParticleKey * key1,ParticleKey * key2)979 static void get_pointcache_keys_for_time(Object *UNUSED(ob),
980 PointCache *cache,
981 PTCacheMem **cur,
982 int index,
983 float t,
984 ParticleKey *key1,
985 ParticleKey *key2)
986 {
987 static PTCacheMem *pm = NULL;
988 int index1, index2;
989
990 if (index < 0) { /* initialize */
991 *cur = cache->mem_cache.first;
992
993 if (*cur) {
994 *cur = (*cur)->next;
995 }
996 }
997 else {
998 if (*cur) {
999 while (*cur && (*cur)->next && (float)(*cur)->frame < t) {
1000 *cur = (*cur)->next;
1001 }
1002
1003 pm = *cur;
1004
1005 index2 = BKE_ptcache_mem_index_find(pm, index);
1006 index1 = BKE_ptcache_mem_index_find(pm->prev, index);
1007 if (index2 < 0) {
1008 return;
1009 }
1010
1011 BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
1012 if (index1 < 0) {
1013 copy_particle_key(key1, key2, 1);
1014 }
1015 else {
1016 BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame);
1017 }
1018 }
1019 else if (cache->mem_cache.first) {
1020 pm = cache->mem_cache.first;
1021 index2 = BKE_ptcache_mem_index_find(pm, index);
1022 if (index2 < 0) {
1023 return;
1024 }
1025 BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
1026 copy_particle_key(key1, key2, 1);
1027 }
1028 }
1029 }
get_pointcache_times_for_particle(PointCache * cache,int index,float * start,float * end)1030 static int get_pointcache_times_for_particle(PointCache *cache,
1031 int index,
1032 float *start,
1033 float *end)
1034 {
1035 PTCacheMem *pm;
1036 int ret = 0;
1037
1038 for (pm = cache->mem_cache.first; pm; pm = pm->next) {
1039 if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
1040 *start = pm->frame;
1041 ret++;
1042 break;
1043 }
1044 }
1045
1046 for (pm = cache->mem_cache.last; pm; pm = pm->prev) {
1047 if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
1048 *end = pm->frame;
1049 ret++;
1050 break;
1051 }
1052 }
1053
1054 return ret == 2;
1055 }
1056
psys_get_dietime_from_cache(PointCache * cache,int index)1057 float psys_get_dietime_from_cache(PointCache *cache, int index)
1058 {
1059 PTCacheMem *pm;
1060 int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
1061
1062 for (pm = cache->mem_cache.last; pm; pm = pm->prev) {
1063 if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
1064 return (float)pm->frame;
1065 }
1066 }
1067
1068 return (float)dietime;
1069 }
1070
init_particle_interpolation(Object * ob,ParticleSystem * psys,ParticleData * pa,ParticleInterpolationData * pind)1071 static void init_particle_interpolation(Object *ob,
1072 ParticleSystem *psys,
1073 ParticleData *pa,
1074 ParticleInterpolationData *pind)
1075 {
1076
1077 if (pind->epoint) {
1078 PTCacheEditPoint *point = pind->epoint;
1079
1080 pind->ekey[0] = point->keys;
1081 pind->ekey[1] = point->totkey > 1 ? point->keys + 1 : NULL;
1082
1083 pind->birthtime = *(point->keys->time);
1084 pind->dietime = *((point->keys + point->totkey - 1)->time);
1085 }
1086 else if (pind->keyed) {
1087 ParticleKey *key = pa->keys;
1088 pind->kkey[0] = key;
1089 pind->kkey[1] = pa->totkey > 1 ? key + 1 : NULL;
1090
1091 pind->birthtime = key->time;
1092 pind->dietime = (key + pa->totkey - 1)->time;
1093 }
1094 else if (pind->cache) {
1095 float start = 0.0f, end = 0.0f;
1096 get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL);
1097 pind->birthtime = pa ? pa->time : pind->cache->startframe;
1098 pind->dietime = pa ? pa->dietime : pind->cache->endframe;
1099
1100 if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &end)) {
1101 pind->birthtime = MAX2(pind->birthtime, start);
1102 pind->dietime = MIN2(pind->dietime, end);
1103 }
1104 }
1105 else {
1106 HairKey *key = pa->hair;
1107 pind->hkey[0] = key;
1108 pind->hkey[1] = key + 1;
1109
1110 pind->birthtime = key->time;
1111 pind->dietime = (key + pa->totkey - 1)->time;
1112
1113 if (pind->mesh) {
1114 pind->mvert[0] = &pind->mesh->mvert[pa->hair_index];
1115 pind->mvert[1] = pind->mvert[0] + 1;
1116 }
1117 }
1118 }
edit_to_particle(ParticleKey * key,PTCacheEditKey * ekey)1119 static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey)
1120 {
1121 copy_v3_v3(key->co, ekey->co);
1122 if (ekey->vel) {
1123 copy_v3_v3(key->vel, ekey->vel);
1124 }
1125 key->time = *(ekey->time);
1126 }
hair_to_particle(ParticleKey * key,HairKey * hkey)1127 static void hair_to_particle(ParticleKey *key, HairKey *hkey)
1128 {
1129 copy_v3_v3(key->co, hkey->co);
1130 key->time = hkey->time;
1131 }
1132
mvert_to_particle(ParticleKey * key,MVert * mvert,HairKey * hkey)1133 static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey)
1134 {
1135 copy_v3_v3(key->co, mvert->co);
1136 key->time = hkey->time;
1137 }
1138
do_particle_interpolation(ParticleSystem * psys,int p,ParticleData * pa,float t,ParticleInterpolationData * pind,ParticleKey * result)1139 static void do_particle_interpolation(ParticleSystem *psys,
1140 int p,
1141 ParticleData *pa,
1142 float t,
1143 ParticleInterpolationData *pind,
1144 ParticleKey *result)
1145 {
1146 PTCacheEditPoint *point = pind->epoint;
1147 ParticleKey keys[4];
1148 int point_vel = (point && point->keys->vel);
1149 float real_t, dfra, keytime, invdt = 1.f;
1150
1151 /* billboards wont fill in all of these, so start cleared */
1152 memset(keys, 0, sizeof(keys));
1153
1154 /* interpret timing and find keys */
1155 if (point) {
1156 if (result->time < 0.0f) {
1157 real_t = -result->time;
1158 }
1159 else {
1160 real_t = *(pind->ekey[0]->time) +
1161 t * (*(pind->ekey[0][point->totkey - 1].time) - *(pind->ekey[0]->time));
1162 }
1163
1164 while (*(pind->ekey[1]->time) < real_t) {
1165 pind->ekey[1]++;
1166 }
1167
1168 pind->ekey[0] = pind->ekey[1] - 1;
1169 }
1170 else if (pind->keyed) {
1171 /* we have only one key, so let's use that */
1172 if (pind->kkey[1] == NULL) {
1173 copy_particle_key(result, pind->kkey[0], 1);
1174 return;
1175 }
1176
1177 if (result->time < 0.0f) {
1178 real_t = -result->time;
1179 }
1180 else {
1181 real_t = pind->kkey[0]->time +
1182 t * (pind->kkey[0][pa->totkey - 1].time - pind->kkey[0]->time);
1183 }
1184
1185 if (psys->part->phystype == PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) {
1186 ParticleTarget *pt = psys->targets.first;
1187
1188 pt = pt->next;
1189
1190 while (pt && pa->time + pt->time < real_t) {
1191 pt = pt->next;
1192 }
1193
1194 if (pt) {
1195 pt = pt->prev;
1196
1197 if (pa->time + pt->time + pt->duration > real_t) {
1198 real_t = pa->time + pt->time;
1199 }
1200 }
1201 else {
1202 real_t = pa->time + ((ParticleTarget *)psys->targets.last)->time;
1203 }
1204 }
1205
1206 CLAMP(real_t, pa->time, pa->dietime);
1207
1208 while (pind->kkey[1]->time < real_t) {
1209 pind->kkey[1]++;
1210 }
1211
1212 pind->kkey[0] = pind->kkey[1] - 1;
1213 }
1214 else if (pind->cache) {
1215 if (result->time < 0.0f) { /* flag for time in frames */
1216 real_t = -result->time;
1217 }
1218 else {
1219 real_t = pa->time + t * (pa->dietime - pa->time);
1220 }
1221 }
1222 else {
1223 if (result->time < 0.0f) {
1224 real_t = -result->time;
1225 }
1226 else {
1227 real_t = pind->hkey[0]->time +
1228 t * (pind->hkey[0][pa->totkey - 1].time - pind->hkey[0]->time);
1229 }
1230
1231 while (pind->hkey[1]->time < real_t) {
1232 pind->hkey[1]++;
1233 pind->mvert[1]++;
1234 }
1235
1236 pind->hkey[0] = pind->hkey[1] - 1;
1237 }
1238
1239 /* set actual interpolation keys */
1240 if (point) {
1241 edit_to_particle(keys + 1, pind->ekey[0]);
1242 edit_to_particle(keys + 2, pind->ekey[1]);
1243 }
1244 else if (pind->mesh) {
1245 pind->mvert[0] = pind->mvert[1] - 1;
1246 mvert_to_particle(keys + 1, pind->mvert[0], pind->hkey[0]);
1247 mvert_to_particle(keys + 2, pind->mvert[1], pind->hkey[1]);
1248 }
1249 else if (pind->keyed) {
1250 memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey));
1251 memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey));
1252 }
1253 else if (pind->cache) {
1254 get_pointcache_keys_for_time(NULL, pind->cache, &pind->pm, p, real_t, keys + 1, keys + 2);
1255 }
1256 else {
1257 hair_to_particle(keys + 1, pind->hkey[0]);
1258 hair_to_particle(keys + 2, pind->hkey[1]);
1259 }
1260
1261 /* set secondary interpolation keys for hair */
1262 if (!pind->keyed && !pind->cache && !point_vel) {
1263 if (point) {
1264 if (pind->ekey[0] != point->keys) {
1265 edit_to_particle(keys, pind->ekey[0] - 1);
1266 }
1267 else {
1268 edit_to_particle(keys, pind->ekey[0]);
1269 }
1270 }
1271 else if (pind->mesh) {
1272 if (pind->hkey[0] != pa->hair) {
1273 mvert_to_particle(keys, pind->mvert[0] - 1, pind->hkey[0] - 1);
1274 }
1275 else {
1276 mvert_to_particle(keys, pind->mvert[0], pind->hkey[0]);
1277 }
1278 }
1279 else {
1280 if (pind->hkey[0] != pa->hair) {
1281 hair_to_particle(keys, pind->hkey[0] - 1);
1282 }
1283 else {
1284 hair_to_particle(keys, pind->hkey[0]);
1285 }
1286 }
1287
1288 if (point) {
1289 if (pind->ekey[1] != point->keys + point->totkey - 1) {
1290 edit_to_particle(keys + 3, pind->ekey[1] + 1);
1291 }
1292 else {
1293 edit_to_particle(keys + 3, pind->ekey[1]);
1294 }
1295 }
1296 else if (pind->mesh) {
1297 if (pind->hkey[1] != pa->hair + pa->totkey - 1) {
1298 mvert_to_particle(keys + 3, pind->mvert[1] + 1, pind->hkey[1] + 1);
1299 }
1300 else {
1301 mvert_to_particle(keys + 3, pind->mvert[1], pind->hkey[1]);
1302 }
1303 }
1304 else {
1305 if (pind->hkey[1] != pa->hair + pa->totkey - 1) {
1306 hair_to_particle(keys + 3, pind->hkey[1] + 1);
1307 }
1308 else {
1309 hair_to_particle(keys + 3, pind->hkey[1]);
1310 }
1311 }
1312 }
1313
1314 dfra = keys[2].time - keys[1].time;
1315 keytime = (real_t - keys[1].time) / dfra;
1316
1317 /* Convert velocity to time-step size. */
1318 if (pind->keyed || pind->cache || point_vel) {
1319 invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f);
1320 mul_v3_fl(keys[1].vel, invdt);
1321 mul_v3_fl(keys[2].vel, invdt);
1322 interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime);
1323 }
1324
1325 /* Now we should have in chronological order k1<=k2<=t<=k3<=k4 with key-time between
1326 * [0, 1]->[k2, k3] (k1 & k4 used for cardinal & b-spline interpolation). */
1327 psys_interpolate_particle((pind->keyed || pind->cache || point_vel) ?
1328 -1 /* signal for cubic interpolation */
1329 :
1330 (pind->bspline ? KEY_BSPLINE : KEY_CARDINAL),
1331 keys,
1332 keytime,
1333 result,
1334 1);
1335
1336 /* the velocity needs to be converted back from cubic interpolation */
1337 if (pind->keyed || pind->cache || point_vel) {
1338 mul_v3_fl(result->vel, 1.f / invdt);
1339 }
1340 }
1341
interpolate_pathcache(ParticleCacheKey * first,float t,ParticleCacheKey * result)1342 static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCacheKey *result)
1343 {
1344 int i = 0;
1345 ParticleCacheKey *cur = first;
1346
1347 /* scale the requested time to fit the entire path even if the path is cut early */
1348 t *= (first + first->segments)->time;
1349
1350 while (i < first->segments && cur->time < t) {
1351 cur++;
1352 }
1353
1354 if (cur->time == t) {
1355 *result = *cur;
1356 }
1357 else {
1358 float dt = (t - (cur - 1)->time) / (cur->time - (cur - 1)->time);
1359 interp_v3_v3v3(result->co, (cur - 1)->co, cur->co, dt);
1360 interp_v3_v3v3(result->vel, (cur - 1)->vel, cur->vel, dt);
1361 interp_qt_qtqt(result->rot, (cur - 1)->rot, cur->rot, dt);
1362 result->time = t;
1363 }
1364
1365 /* first is actual base rotation, others are incremental from first */
1366 if (cur == first || cur - 1 == first) {
1367 copy_qt_qt(result->rot, first->rot);
1368 }
1369 else {
1370 mul_qt_qtqt(result->rot, first->rot, result->rot);
1371 }
1372 }
1373
1374 /************************************************/
1375 /* Particles on a dm */
1376 /************************************************/
1377 /* interpolate a location on a face based on face coordinates */
psys_interpolate_face(MVert * mvert,MFace * mface,MTFace * tface,float (* orcodata)[3],float w[4],float vec[3],float nor[3],float utan[3],float vtan[3],float orco[3])1378 void psys_interpolate_face(MVert *mvert,
1379 MFace *mface,
1380 MTFace *tface,
1381 float (*orcodata)[3],
1382 float w[4],
1383 float vec[3],
1384 float nor[3],
1385 float utan[3],
1386 float vtan[3],
1387 float orco[3])
1388 {
1389 float *v1 = 0, *v2 = 0, *v3 = 0, *v4 = 0;
1390 float e1[3], e2[3], s1, s2, t1, t2;
1391 float *uv1, *uv2, *uv3, *uv4;
1392 float n1[3], n2[3], n3[3], n4[3];
1393 float tuv[4][2];
1394 float *o1, *o2, *o3, *o4;
1395
1396 v1 = mvert[mface->v1].co;
1397 v2 = mvert[mface->v2].co;
1398 v3 = mvert[mface->v3].co;
1399
1400 normal_short_to_float_v3(n1, mvert[mface->v1].no);
1401 normal_short_to_float_v3(n2, mvert[mface->v2].no);
1402 normal_short_to_float_v3(n3, mvert[mface->v3].no);
1403
1404 if (mface->v4) {
1405 v4 = mvert[mface->v4].co;
1406 normal_short_to_float_v3(n4, mvert[mface->v4].no);
1407
1408 interp_v3_v3v3v3v3(vec, v1, v2, v3, v4, w);
1409
1410 if (nor) {
1411 if (mface->flag & ME_SMOOTH) {
1412 interp_v3_v3v3v3v3(nor, n1, n2, n3, n4, w);
1413 }
1414 else {
1415 normal_quad_v3(nor, v1, v2, v3, v4);
1416 }
1417 }
1418 }
1419 else {
1420 interp_v3_v3v3v3(vec, v1, v2, v3, w);
1421
1422 if (nor) {
1423 if (mface->flag & ME_SMOOTH) {
1424 interp_v3_v3v3v3(nor, n1, n2, n3, w);
1425 }
1426 else {
1427 normal_tri_v3(nor, v1, v2, v3);
1428 }
1429 }
1430 }
1431
1432 /* calculate tangent vectors */
1433 if (utan && vtan) {
1434 if (tface) {
1435 uv1 = tface->uv[0];
1436 uv2 = tface->uv[1];
1437 uv3 = tface->uv[2];
1438 uv4 = tface->uv[3];
1439 }
1440 else {
1441 uv1 = tuv[0];
1442 uv2 = tuv[1];
1443 uv3 = tuv[2];
1444 uv4 = tuv[3];
1445 map_to_sphere(uv1, uv1 + 1, v1[0], v1[1], v1[2]);
1446 map_to_sphere(uv2, uv2 + 1, v2[0], v2[1], v2[2]);
1447 map_to_sphere(uv3, uv3 + 1, v3[0], v3[1], v3[2]);
1448 if (v4) {
1449 map_to_sphere(uv4, uv4 + 1, v4[0], v4[1], v4[2]);
1450 }
1451 }
1452
1453 if (v4) {
1454 s1 = uv3[0] - uv1[0];
1455 s2 = uv4[0] - uv1[0];
1456
1457 t1 = uv3[1] - uv1[1];
1458 t2 = uv4[1] - uv1[1];
1459
1460 sub_v3_v3v3(e1, v3, v1);
1461 sub_v3_v3v3(e2, v4, v1);
1462 }
1463 else {
1464 s1 = uv2[0] - uv1[0];
1465 s2 = uv3[0] - uv1[0];
1466
1467 t1 = uv2[1] - uv1[1];
1468 t2 = uv3[1] - uv1[1];
1469
1470 sub_v3_v3v3(e1, v2, v1);
1471 sub_v3_v3v3(e2, v3, v1);
1472 }
1473
1474 vtan[0] = (s1 * e2[0] - s2 * e1[0]);
1475 vtan[1] = (s1 * e2[1] - s2 * e1[1]);
1476 vtan[2] = (s1 * e2[2] - s2 * e1[2]);
1477
1478 utan[0] = (t1 * e2[0] - t2 * e1[0]);
1479 utan[1] = (t1 * e2[1] - t2 * e1[1]);
1480 utan[2] = (t1 * e2[2] - t2 * e1[2]);
1481 }
1482
1483 if (orco) {
1484 if (orcodata) {
1485 o1 = orcodata[mface->v1];
1486 o2 = orcodata[mface->v2];
1487 o3 = orcodata[mface->v3];
1488
1489 if (mface->v4) {
1490 o4 = orcodata[mface->v4];
1491
1492 interp_v3_v3v3v3v3(orco, o1, o2, o3, o4, w);
1493 }
1494 else {
1495 interp_v3_v3v3v3(orco, o1, o2, o3, w);
1496 }
1497 }
1498 else {
1499 copy_v3_v3(orco, vec);
1500 }
1501 }
1502 }
psys_interpolate_uvs(const MTFace * tface,int quad,const float w[4],float uvco[2])1503 void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float uvco[2])
1504 {
1505 float v10 = tface->uv[0][0];
1506 float v11 = tface->uv[0][1];
1507 float v20 = tface->uv[1][0];
1508 float v21 = tface->uv[1][1];
1509 float v30 = tface->uv[2][0];
1510 float v31 = tface->uv[2][1];
1511 float v40, v41;
1512
1513 if (quad) {
1514 v40 = tface->uv[3][0];
1515 v41 = tface->uv[3][1];
1516
1517 uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30 + w[3] * v40;
1518 uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31 + w[3] * v41;
1519 }
1520 else {
1521 uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30;
1522 uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31;
1523 }
1524 }
1525
psys_interpolate_mcol(const MCol * mcol,int quad,const float w[4],MCol * mc)1526 void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
1527 {
1528 const char *cp1, *cp2, *cp3, *cp4;
1529 char *cp;
1530
1531 cp = (char *)mc;
1532 cp1 = (const char *)&mcol[0];
1533 cp2 = (const char *)&mcol[1];
1534 cp3 = (const char *)&mcol[2];
1535
1536 if (quad) {
1537 cp4 = (char *)&mcol[3];
1538
1539 cp[0] = (int)(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0] + w[3] * cp4[0]);
1540 cp[1] = (int)(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1] + w[3] * cp4[1]);
1541 cp[2] = (int)(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2] + w[3] * cp4[2]);
1542 cp[3] = (int)(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3] + w[3] * cp4[3]);
1543 }
1544 else {
1545 cp[0] = (int)(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0]);
1546 cp[1] = (int)(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1]);
1547 cp[2] = (int)(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2]);
1548 cp[3] = (int)(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3]);
1549 }
1550 }
1551
psys_interpolate_value_from_verts(Mesh * mesh,short from,int index,const float fw[4],const float * values)1552 static float psys_interpolate_value_from_verts(
1553 Mesh *mesh, short from, int index, const float fw[4], const float *values)
1554 {
1555 if (values == 0 || index == -1) {
1556 return 0.0;
1557 }
1558
1559 switch (from) {
1560 case PART_FROM_VERT:
1561 return values[index];
1562 case PART_FROM_FACE:
1563 case PART_FROM_VOLUME: {
1564 MFace *mf = &mesh->mface[index];
1565 return interpolate_particle_value(
1566 values[mf->v1], values[mf->v2], values[mf->v3], values[mf->v4], fw, mf->v4);
1567 }
1568 }
1569 return 0.0f;
1570 }
1571
1572 /* conversion of pa->fw to origspace layer coordinates */
psys_w_to_origspace(const float w[4],float uv[2])1573 static void psys_w_to_origspace(const float w[4], float uv[2])
1574 {
1575 uv[0] = w[1] + w[2];
1576 uv[1] = w[2] + w[3];
1577 }
1578
1579 /* conversion of pa->fw to weights in face from origspace */
psys_origspace_to_w(OrigSpaceFace * osface,int quad,const float w[4],float neww[4])1580 static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4], float neww[4])
1581 {
1582 float v[4][3], co[3];
1583
1584 v[0][0] = osface->uv[0][0];
1585 v[0][1] = osface->uv[0][1];
1586 v[0][2] = 0.0f;
1587 v[1][0] = osface->uv[1][0];
1588 v[1][1] = osface->uv[1][1];
1589 v[1][2] = 0.0f;
1590 v[2][0] = osface->uv[2][0];
1591 v[2][1] = osface->uv[2][1];
1592 v[2][2] = 0.0f;
1593
1594 psys_w_to_origspace(w, co);
1595 co[2] = 0.0f;
1596
1597 if (quad) {
1598 v[3][0] = osface->uv[3][0];
1599 v[3][1] = osface->uv[3][1];
1600 v[3][2] = 0.0f;
1601 interp_weights_poly_v3(neww, v, 4, co);
1602 }
1603 else {
1604 interp_weights_poly_v3(neww, v, 3, co);
1605 neww[3] = 0.0f;
1606 }
1607 }
1608
1609 /**
1610 * Find the final derived mesh tessface for a particle, from its original tessface index.
1611 * This is slow and can be optimized but only for many lookups.
1612 *
1613 * \param mesh_final: Final mesh, it may not have the same topology as original mesh.
1614 * \param mesh_original: Original mesh, use for accessing #MPoly to #MFace mapping.
1615 * \param findex_orig: The input tessface index.
1616 * \param fw: Face weights (position of the particle inside the \a findex_orig tessface).
1617 * \param poly_nodes: May be NULL, otherwise an array of linked list,
1618 * one for each final \a mesh_final polygon, containing all its tessfaces indices.
1619 * \return The \a mesh_final tessface index.
1620 */
psys_particle_dm_face_lookup(Mesh * mesh_final,Mesh * mesh_original,int findex_orig,const float fw[4],struct LinkNode ** poly_nodes)1621 int psys_particle_dm_face_lookup(Mesh *mesh_final,
1622 Mesh *mesh_original,
1623 int findex_orig,
1624 const float fw[4],
1625 struct LinkNode **poly_nodes)
1626 {
1627 MFace *mtessface_final;
1628 OrigSpaceFace *osface_final;
1629 int pindex_orig;
1630 float uv[2], (*faceuv)[2];
1631
1632 const int *index_mf_to_mpoly_deformed = NULL;
1633 const int *index_mf_to_mpoly = NULL;
1634 const int *index_mp_to_orig = NULL;
1635
1636 const int totface_final = mesh_final->totface;
1637 const int totface_deformed = mesh_original ? mesh_original->totface : totface_final;
1638
1639 if (ELEM(0, totface_final, totface_deformed)) {
1640 return DMCACHE_NOTFOUND;
1641 }
1642
1643 index_mf_to_mpoly = CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX);
1644 index_mp_to_orig = CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX);
1645 BLI_assert(index_mf_to_mpoly);
1646
1647 if (mesh_original) {
1648 index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_original->fdata, CD_ORIGINDEX);
1649 }
1650 else {
1651 BLI_assert(mesh_final->runtime.deformed_only);
1652 index_mf_to_mpoly_deformed = index_mf_to_mpoly;
1653 }
1654 BLI_assert(index_mf_to_mpoly_deformed);
1655
1656 pindex_orig = index_mf_to_mpoly_deformed[findex_orig];
1657
1658 if (mesh_original == NULL) {
1659 mesh_original = mesh_final;
1660 }
1661
1662 index_mf_to_mpoly_deformed = NULL;
1663
1664 mtessface_final = mesh_final->mface;
1665 osface_final = CustomData_get_layer(&mesh_final->fdata, CD_ORIGSPACE);
1666
1667 if (osface_final == NULL) {
1668 /* Assume we don't need osface_final data, and we get a direct 1-1 mapping... */
1669 if (findex_orig < totface_final) {
1670 // printf("\tNO CD_ORIGSPACE, assuming not needed\n");
1671 return findex_orig;
1672 }
1673
1674 printf("\tNO CD_ORIGSPACE, error out of range\n");
1675 return DMCACHE_NOTFOUND;
1676 }
1677 if (findex_orig >= mesh_original->totface) {
1678 return DMCACHE_NOTFOUND; /* index not in the original mesh */
1679 }
1680
1681 psys_w_to_origspace(fw, uv);
1682
1683 if (poly_nodes) {
1684 /* we can have a restricted linked list of faces to check, faster! */
1685 LinkNode *tessface_node = poly_nodes[pindex_orig];
1686
1687 for (; tessface_node; tessface_node = tessface_node->next) {
1688 int findex_dst = POINTER_AS_INT(tessface_node->link);
1689 faceuv = osface_final[findex_dst].uv;
1690
1691 /* check that this intersects - Its possible this misses :/ -
1692 * could also check its not between */
1693 if (mtessface_final[findex_dst].v4) {
1694 if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
1695 return findex_dst;
1696 }
1697 }
1698 else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
1699 return findex_dst;
1700 }
1701 }
1702 }
1703 else { /* if we have no node, try every face */
1704 for (int findex_dst = 0; findex_dst < totface_final; findex_dst++) {
1705 /* If current tessface from 'final' DM and orig tessface (given by index)
1706 * map to the same orig poly. */
1707 if (BKE_mesh_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex_dst) ==
1708 pindex_orig) {
1709 faceuv = osface_final[findex_dst].uv;
1710
1711 /* check that this intersects - Its possible this misses :/ -
1712 * could also check its not between */
1713 if (mtessface_final[findex_dst].v4) {
1714 if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
1715 return findex_dst;
1716 }
1717 }
1718 else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
1719 return findex_dst;
1720 }
1721 }
1722 }
1723 }
1724
1725 return DMCACHE_NOTFOUND;
1726 }
1727
psys_map_index_on_dm(Mesh * mesh,int from,int index,int index_dmcache,const float fw[4],float UNUSED (foffset),int * mapindex,float mapfw[4])1728 static int psys_map_index_on_dm(Mesh *mesh,
1729 int from,
1730 int index,
1731 int index_dmcache,
1732 const float fw[4],
1733 float UNUSED(foffset),
1734 int *mapindex,
1735 float mapfw[4])
1736 {
1737 if (index < 0) {
1738 return 0;
1739 }
1740
1741 if (mesh->runtime.deformed_only || index_dmcache == DMCACHE_ISCHILD) {
1742 /* for meshes that are either only deformed or for child particles, the
1743 * index and fw do not require any mapping, so we can directly use it */
1744 if (from == PART_FROM_VERT) {
1745 if (index >= mesh->totvert) {
1746 return 0;
1747 }
1748
1749 *mapindex = index;
1750 }
1751 else { /* FROM_FACE/FROM_VOLUME */
1752 if (index >= mesh->totface) {
1753 return 0;
1754 }
1755
1756 *mapindex = index;
1757 copy_v4_v4(mapfw, fw);
1758 }
1759 }
1760 else {
1761 /* for other meshes that have been modified, we try to map the particle
1762 * to their new location, which means a different index, and for faces
1763 * also a new face interpolation weights */
1764 if (from == PART_FROM_VERT) {
1765 if (index_dmcache == DMCACHE_NOTFOUND || index_dmcache >= mesh->totvert) {
1766 return 0;
1767 }
1768
1769 *mapindex = index_dmcache;
1770 }
1771 else { /* FROM_FACE/FROM_VOLUME */
1772 /* find a face on the derived mesh that uses this face */
1773 MFace *mface;
1774 OrigSpaceFace *osface;
1775 int i;
1776
1777 i = index_dmcache;
1778
1779 if (i == DMCACHE_NOTFOUND || i >= mesh->totface) {
1780 return 0;
1781 }
1782
1783 *mapindex = i;
1784
1785 /* modify the original weights to become
1786 * weights for the derived mesh face */
1787 osface = CustomData_get_layer(&mesh->fdata, CD_ORIGSPACE);
1788 mface = &mesh->mface[i];
1789
1790 if (osface == NULL) {
1791 mapfw[0] = mapfw[1] = mapfw[2] = mapfw[3] = 0.0f;
1792 }
1793 else {
1794 psys_origspace_to_w(&osface[i], mface->v4, fw, mapfw);
1795 }
1796 }
1797 }
1798
1799 return 1;
1800 }
1801
1802 /* interprets particle data to get a point on a mesh in object space */
psys_particle_on_dm(Mesh * mesh_final,int from,int index,int index_dmcache,const float fw[4],float foffset,float vec[3],float nor[3],float utan[3],float vtan[3],float orco[3])1803 void psys_particle_on_dm(Mesh *mesh_final,
1804 int from,
1805 int index,
1806 int index_dmcache,
1807 const float fw[4],
1808 float foffset,
1809 float vec[3],
1810 float nor[3],
1811 float utan[3],
1812 float vtan[3],
1813 float orco[3])
1814 {
1815 float tmpnor[3], mapfw[4];
1816 float(*orcodata)[3];
1817 int mapindex;
1818
1819 if (!psys_map_index_on_dm(
1820 mesh_final, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
1821 if (vec) {
1822 vec[0] = vec[1] = vec[2] = 0.0;
1823 }
1824 if (nor) {
1825 nor[0] = nor[1] = 0.0;
1826 nor[2] = 1.0;
1827 }
1828 if (orco) {
1829 orco[0] = orco[1] = orco[2] = 0.0;
1830 }
1831 if (utan) {
1832 utan[0] = utan[1] = utan[2] = 0.0;
1833 }
1834 if (vtan) {
1835 vtan[0] = vtan[1] = vtan[2] = 0.0;
1836 }
1837
1838 return;
1839 }
1840
1841 orcodata = CustomData_get_layer(&mesh_final->vdata, CD_ORCO);
1842
1843 if (from == PART_FROM_VERT) {
1844 copy_v3_v3(vec, mesh_final->mvert[mapindex].co);
1845
1846 if (nor) {
1847 normal_short_to_float_v3(nor, mesh_final->mvert[mapindex].no);
1848 normalize_v3(nor);
1849 }
1850
1851 if (orco) {
1852 if (orcodata) {
1853 copy_v3_v3(orco, orcodata[mapindex]);
1854 }
1855 else {
1856 copy_v3_v3(orco, vec);
1857 }
1858 }
1859
1860 if (utan && vtan) {
1861 utan[0] = utan[1] = utan[2] = 0.0f;
1862 vtan[0] = vtan[1] = vtan[2] = 0.0f;
1863 }
1864 }
1865 else { /* PART_FROM_FACE / PART_FROM_VOLUME */
1866 MFace *mface;
1867 MTFace *mtface;
1868 MVert *mvert;
1869
1870 mface = &mesh_final->mface[mapindex];
1871 mvert = mesh_final->mvert;
1872 mtface = mesh_final->mtface;
1873
1874 if (mtface) {
1875 mtface += mapindex;
1876 }
1877
1878 if (from == PART_FROM_VOLUME) {
1879 psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, tmpnor, utan, vtan, orco);
1880 if (nor) {
1881 copy_v3_v3(nor, tmpnor);
1882 }
1883
1884 /* XXX Why not normalize tmpnor before copying it into nor??? -- mont29 */
1885 normalize_v3(tmpnor);
1886
1887 mul_v3_fl(tmpnor, -foffset);
1888 add_v3_v3(vec, tmpnor);
1889 }
1890 else {
1891 psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, nor, utan, vtan, orco);
1892 }
1893 }
1894 }
1895
psys_particle_value_from_verts(Mesh * mesh,short from,ParticleData * pa,float * values)1896 float psys_particle_value_from_verts(Mesh *mesh, short from, ParticleData *pa, float *values)
1897 {
1898 float mapfw[4];
1899 int mapindex;
1900
1901 if (!psys_map_index_on_dm(
1902 mesh, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, &mapindex, mapfw)) {
1903 return 0.0f;
1904 }
1905
1906 return psys_interpolate_value_from_verts(mesh, from, mapindex, mapfw, values);
1907 }
1908
psys_get_modifier(Object * ob,ParticleSystem * psys)1909 ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys)
1910 {
1911 ModifierData *md;
1912 ParticleSystemModifierData *psmd;
1913
1914 for (md = ob->modifiers.first; md; md = md->next) {
1915 if (md->type == eModifierType_ParticleSystem) {
1916 psmd = (ParticleSystemModifierData *)md;
1917 if (psmd->psys == psys) {
1918 return psmd;
1919 }
1920 }
1921 }
1922 return NULL;
1923 }
1924 /************************************************/
1925 /* Particles on a shape */
1926 /************************************************/
1927 /* ready for future use */
psys_particle_on_shape(int UNUSED (distr),int UNUSED (index),float * UNUSED (fuv),float vec[3],float nor[3],float utan[3],float vtan[3],float orco[3])1928 static void psys_particle_on_shape(int UNUSED(distr),
1929 int UNUSED(index),
1930 float *UNUSED(fuv),
1931 float vec[3],
1932 float nor[3],
1933 float utan[3],
1934 float vtan[3],
1935 float orco[3])
1936 {
1937 /* TODO */
1938 const float zerovec[3] = {0.0f, 0.0f, 0.0f};
1939 if (vec) {
1940 copy_v3_v3(vec, zerovec);
1941 }
1942 if (nor) {
1943 copy_v3_v3(nor, zerovec);
1944 }
1945 if (utan) {
1946 copy_v3_v3(utan, zerovec);
1947 }
1948 if (vtan) {
1949 copy_v3_v3(vtan, zerovec);
1950 }
1951 if (orco) {
1952 copy_v3_v3(orco, zerovec);
1953 }
1954 }
1955 /************************************************/
1956 /* Particles on emitter */
1957 /************************************************/
1958
psys_emitter_customdata_mask(ParticleSystem * psys,CustomData_MeshMasks * r_cddata_masks)1959 void psys_emitter_customdata_mask(ParticleSystem *psys, CustomData_MeshMasks *r_cddata_masks)
1960 {
1961 MTex *mtex;
1962 int i;
1963
1964 if (!psys->part) {
1965 return;
1966 }
1967
1968 for (i = 0; i < MAX_MTEX; i++) {
1969 mtex = psys->part->mtex[i];
1970 if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV)) {
1971 r_cddata_masks->fmask |= CD_MASK_MTFACE;
1972 }
1973 }
1974
1975 if (psys->part->tanfac != 0.0f) {
1976 r_cddata_masks->fmask |= CD_MASK_MTFACE;
1977 }
1978
1979 /* ask for vertexgroups if we need them */
1980 for (i = 0; i < PSYS_TOT_VG; i++) {
1981 if (psys->vgroup[i]) {
1982 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
1983 break;
1984 }
1985 }
1986
1987 /* particles only need this if they are after a non deform modifier, and
1988 * the modifier stack will only create them in that case. */
1989 r_cddata_masks->lmask |= CD_MASK_ORIGSPACE_MLOOP;
1990 /* XXX Check we do need all those? */
1991 r_cddata_masks->vmask |= CD_MASK_ORIGINDEX;
1992 r_cddata_masks->emask |= CD_MASK_ORIGINDEX;
1993 r_cddata_masks->pmask |= CD_MASK_ORIGINDEX;
1994
1995 r_cddata_masks->vmask |= CD_MASK_ORCO;
1996 }
1997
psys_particle_on_emitter(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])1998 void psys_particle_on_emitter(ParticleSystemModifierData *psmd,
1999 int from,
2000 int index,
2001 int index_dmcache,
2002 float fuv[4],
2003 float foffset,
2004 float vec[3],
2005 float nor[3],
2006 float utan[3],
2007 float vtan[3],
2008 float orco[3])
2009 {
2010 if (psmd && psmd->mesh_final) {
2011 if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) {
2012 if (vec) {
2013 copy_v3_v3(vec, fuv);
2014 }
2015
2016 if (orco) {
2017 copy_v3_v3(orco, fuv);
2018 }
2019 return;
2020 }
2021 /* we cant use the num_dmcache */
2022 psys_particle_on_dm(
2023 psmd->mesh_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco);
2024 }
2025 else {
2026 psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco);
2027 }
2028 }
2029 /************************************************/
2030 /* Path Cache */
2031 /************************************************/
2032
precalc_guides(ParticleSimulationData * sim,ListBase * effectors)2033 void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
2034 {
2035 EffectedPoint point;
2036 ParticleKey state;
2037 EffectorData efd;
2038 EffectorCache *eff;
2039 ParticleSystem *psys = sim->psys;
2040 EffectorWeights *weights = sim->psys->part->effector_weights;
2041 GuideEffectorData *data;
2042 PARTICLE_P;
2043
2044 if (!effectors) {
2045 return;
2046 }
2047
2048 LOOP_PARTICLES
2049 {
2050 psys_particle_on_emitter(sim->psmd,
2051 sim->psys->part->from,
2052 pa->num,
2053 pa->num_dmcache,
2054 pa->fuv,
2055 pa->foffset,
2056 state.co,
2057 0,
2058 0,
2059 0,
2060 0);
2061
2062 mul_m4_v3(sim->ob->obmat, state.co);
2063 mul_mat3_m4_v3(sim->ob->obmat, state.vel);
2064
2065 pd_point_from_particle(sim, pa, &state, &point);
2066
2067 for (eff = effectors->first; eff; eff = eff->next) {
2068 if (eff->pd->forcefield != PFIELD_GUIDE) {
2069 continue;
2070 }
2071
2072 if (!eff->guide_data) {
2073 eff->guide_data = MEM_callocN(sizeof(GuideEffectorData) * psys->totpart,
2074 "GuideEffectorData");
2075 }
2076
2077 data = eff->guide_data + p;
2078
2079 sub_v3_v3v3(efd.vec_to_point, state.co, eff->guide_loc);
2080 copy_v3_v3(efd.nor, eff->guide_dir);
2081 efd.distance = len_v3(efd.vec_to_point);
2082
2083 copy_v3_v3(data->vec_to_point, efd.vec_to_point);
2084 data->strength = effector_falloff(eff, &efd, &point, weights);
2085 }
2086 }
2087 }
2088
do_guides(Depsgraph * depsgraph,ParticleSettings * part,ListBase * effectors,ParticleKey * state,int index,float time)2089 int do_guides(Depsgraph *depsgraph,
2090 ParticleSettings *part,
2091 ListBase *effectors,
2092 ParticleKey *state,
2093 int index,
2094 float time)
2095 {
2096 CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve :
2097 NULL;
2098 CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve :
2099 NULL;
2100 EffectorCache *eff;
2101 PartDeflect *pd;
2102 Curve *cu;
2103 GuideEffectorData *data;
2104
2105 float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
2106 float guidevec[4], guidedir[3], rot2[4], temp[3];
2107 float guidetime, radius, weight, angle, totstrength = 0.0f;
2108 float vec_to_point[3];
2109
2110 if (effectors) {
2111 for (eff = effectors->first; eff; eff = eff->next) {
2112 pd = eff->pd;
2113
2114 if (pd->forcefield != PFIELD_GUIDE) {
2115 continue;
2116 }
2117
2118 data = eff->guide_data + index;
2119
2120 if (data->strength <= 0.0f) {
2121 continue;
2122 }
2123
2124 guidetime = time / (1.0f - pd->free_end);
2125
2126 if (guidetime > 1.0f) {
2127 continue;
2128 }
2129
2130 cu = (Curve *)eff->ob->data;
2131
2132 if (pd->flag & PFIELD_GUIDE_PATH_ADD) {
2133 if (where_on_path(
2134 eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius, &weight) ==
2135 0) {
2136 return 0;
2137 }
2138 }
2139 else {
2140 if (where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0) {
2141 return 0;
2142 }
2143 }
2144
2145 mul_m4_v3(eff->ob->obmat, guidevec);
2146 mul_mat3_m4_v3(eff->ob->obmat, guidedir);
2147
2148 normalize_v3(guidedir);
2149
2150 copy_v3_v3(vec_to_point, data->vec_to_point);
2151
2152 if (guidetime != 0.0f) {
2153 /* curve direction */
2154 cross_v3_v3v3(temp, eff->guide_dir, guidedir);
2155 angle = dot_v3v3(eff->guide_dir, guidedir) / (len_v3(eff->guide_dir));
2156 angle = saacos(angle);
2157 axis_angle_to_quat(rot2, temp, angle);
2158 mul_qt_v3(rot2, vec_to_point);
2159
2160 /* curve tilt */
2161 axis_angle_to_quat(rot2, guidedir, guidevec[3] - eff->guide_loc[3]);
2162 mul_qt_v3(rot2, vec_to_point);
2163 }
2164
2165 /* curve taper */
2166 if (cu->taperobj) {
2167 mul_v3_fl(vec_to_point,
2168 BKE_displist_calc_taper(depsgraph,
2169 eff->scene,
2170 cu->taperobj,
2171 (int)(data->strength * guidetime * 100.0f),
2172 100));
2173 }
2174 else { /* curve size*/
2175 if (cu->flag & CU_PATH_RADIUS) {
2176 mul_v3_fl(vec_to_point, radius);
2177 }
2178 }
2179
2180 if (clumpcurve) {
2181 BKE_curvemapping_changed_all(clumpcurve);
2182 }
2183 if (roughcurve) {
2184 BKE_curvemapping_changed_all(roughcurve);
2185 }
2186
2187 {
2188 ParticleKey key;
2189 const float par_co[3] = {0.0f, 0.0f, 0.0f};
2190 const float par_vel[3] = {0.0f, 0.0f, 0.0f};
2191 const float par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
2192 const float orco_offset[3] = {0.0f, 0.0f, 0.0f};
2193
2194 copy_v3_v3(key.co, vec_to_point);
2195 do_kink(&key,
2196 par_co,
2197 par_vel,
2198 par_rot,
2199 guidetime,
2200 pd->kink_freq,
2201 pd->kink_shape,
2202 pd->kink_amp,
2203 0.f,
2204 pd->kink,
2205 pd->kink_axis,
2206 0,
2207 0);
2208 do_clump(&key,
2209 par_co,
2210 guidetime,
2211 orco_offset,
2212 pd->clump_fac,
2213 pd->clump_pow,
2214 1.0f,
2215 part->child_flag & PART_CHILD_USE_CLUMP_NOISE,
2216 part->clump_noise_size,
2217 clumpcurve);
2218 copy_v3_v3(vec_to_point, key.co);
2219 }
2220
2221 add_v3_v3(vec_to_point, guidevec);
2222
2223 // sub_v3_v3v3(pa_loc, pa_loc, pa_zero);
2224 madd_v3_v3fl(effect, vec_to_point, data->strength);
2225 madd_v3_v3fl(veffect, guidedir, data->strength);
2226 totstrength += data->strength;
2227
2228 if (pd->flag & PFIELD_GUIDE_PATH_WEIGHT) {
2229 totstrength *= weight;
2230 }
2231 }
2232 }
2233
2234 if (totstrength != 0.0f) {
2235 if (totstrength > 1.0f) {
2236 mul_v3_fl(effect, 1.0f / totstrength);
2237 }
2238 CLAMP(totstrength, 0.0f, 1.0f);
2239 // add_v3_v3(effect, pa_zero);
2240 interp_v3_v3v3(state->co, state->co, effect, totstrength);
2241
2242 normalize_v3(veffect);
2243 mul_v3_fl(veffect, len_v3(state->vel));
2244 copy_v3_v3(state->vel, veffect);
2245 return 1;
2246 }
2247 return 0;
2248 }
2249
do_path_effectors(ParticleSimulationData * sim,int i,ParticleCacheKey * ca,int k,int steps,float * UNUSED (rootco),float effector,float UNUSED (dfra),float UNUSED (cfra),float * length,float * vec)2250 static void do_path_effectors(ParticleSimulationData *sim,
2251 int i,
2252 ParticleCacheKey *ca,
2253 int k,
2254 int steps,
2255 float *UNUSED(rootco),
2256 float effector,
2257 float UNUSED(dfra),
2258 float UNUSED(cfra),
2259 float *length,
2260 float *vec)
2261 {
2262 float force[3] = {0.0f, 0.0f, 0.0f};
2263 ParticleKey eff_key;
2264 EffectedPoint epoint;
2265
2266 /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */
2267 if (sim->psys->flag & PSYS_HAIR_DYNAMICS) {
2268 return;
2269 }
2270
2271 copy_v3_v3(eff_key.co, (ca - 1)->co);
2272 copy_v3_v3(eff_key.vel, (ca - 1)->vel);
2273 copy_qt_qt(eff_key.rot, (ca - 1)->rot);
2274
2275 pd_point_from_particle(sim, sim->psys->particles + i, &eff_key, &epoint);
2276 BKE_effectors_apply(sim->psys->effectors,
2277 sim->colliders,
2278 sim->psys->part->effector_weights,
2279 &epoint,
2280 force,
2281 NULL,
2282 NULL);
2283
2284 mul_v3_fl(force,
2285 effector * powf((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) /
2286 (float)steps);
2287
2288 add_v3_v3(force, vec);
2289
2290 normalize_v3(force);
2291
2292 if (k < steps) {
2293 sub_v3_v3v3(vec, (ca + 1)->co, ca->co);
2294 }
2295
2296 madd_v3_v3v3fl(ca->co, (ca - 1)->co, force, *length);
2297
2298 if (k < steps) {
2299 *length = len_v3(vec);
2300 }
2301 }
offset_child(ChildParticle * cpa,ParticleKey * par,float * par_rot,ParticleKey * child,float flat,float radius)2302 static void offset_child(ChildParticle *cpa,
2303 ParticleKey *par,
2304 float *par_rot,
2305 ParticleKey *child,
2306 float flat,
2307 float radius)
2308 {
2309 copy_v3_v3(child->co, cpa->fuv);
2310 mul_v3_fl(child->co, radius);
2311
2312 child->co[0] *= flat;
2313
2314 copy_v3_v3(child->vel, par->vel);
2315
2316 if (par_rot) {
2317 mul_qt_v3(par_rot, child->co);
2318 copy_qt_qt(child->rot, par_rot);
2319 }
2320 else {
2321 unit_qt(child->rot);
2322 }
2323
2324 add_v3_v3(child->co, par->co);
2325 }
psys_cache_vgroup(Mesh * mesh,ParticleSystem * psys,int vgroup)2326 float *psys_cache_vgroup(Mesh *mesh, ParticleSystem *psys, int vgroup)
2327 {
2328 float *vg = 0;
2329
2330 if (vgroup < 0) {
2331 /* hair dynamics pinning vgroup */
2332 }
2333 else if (psys->vgroup[vgroup]) {
2334 MDeformVert *dvert = mesh->dvert;
2335 if (dvert) {
2336 int totvert = mesh->totvert, i;
2337 vg = MEM_callocN(sizeof(float) * totvert, "vg_cache");
2338 if (psys->vg_neg & (1 << vgroup)) {
2339 for (i = 0; i < totvert; i++) {
2340 vg[i] = 1.0f - BKE_defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
2341 }
2342 }
2343 else {
2344 for (i = 0; i < totvert; i++) {
2345 vg[i] = BKE_defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
2346 }
2347 }
2348 }
2349 }
2350 return vg;
2351 }
psys_find_parents(ParticleSimulationData * sim,const bool use_render_params)2352 void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params)
2353 {
2354 ParticleSystem *psys = sim->psys;
2355 ParticleSettings *part = sim->psys->part;
2356 KDTree_3d *tree;
2357 ChildParticle *cpa;
2358 ParticleTexture ptex;
2359 int p, totparent, totchild = sim->psys->totchild;
2360 float co[3], orco[3];
2361 int from = PART_FROM_FACE;
2362 totparent = (int)(totchild * part->parents * 0.3f);
2363
2364 if (use_render_params && part->child_nbr && part->ren_child_nbr) {
2365 totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
2366 }
2367
2368 /* hard limit, workaround for it being ignored above */
2369 if (sim->psys->totpart < totparent) {
2370 totparent = sim->psys->totpart;
2371 }
2372
2373 tree = BLI_kdtree_3d_new(totparent);
2374
2375 for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) {
2376 psys_particle_on_emitter(
2377 sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco);
2378
2379 /* Check if particle doesn't exist because of texture influence.
2380 * Insert only existing particles into kdtree. */
2381 get_cpa_texture(sim->psmd->mesh_final,
2382 psys,
2383 part,
2384 psys->particles + cpa->pa[0],
2385 p,
2386 cpa->num,
2387 cpa->fuv,
2388 orco,
2389 &ptex,
2390 PAMAP_DENS | PAMAP_CHILD,
2391 psys->cfra);
2392
2393 if (ptex.exist >= psys_frand(psys, p + 24)) {
2394 BLI_kdtree_3d_insert(tree, p, orco);
2395 }
2396 }
2397
2398 BLI_kdtree_3d_balance(tree);
2399
2400 for (; p < totchild; p++, cpa++) {
2401 psys_particle_on_emitter(
2402 sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco);
2403 cpa->parent = BLI_kdtree_3d_find_nearest(tree, orco, NULL);
2404 }
2405
2406 BLI_kdtree_3d_free(tree);
2407 }
2408
psys_thread_context_init_path(ParticleThreadContext * ctx,ParticleSimulationData * sim,Scene * scene,float cfra,const bool editupdate,const bool use_render_params)2409 static bool psys_thread_context_init_path(ParticleThreadContext *ctx,
2410 ParticleSimulationData *sim,
2411 Scene *scene,
2412 float cfra,
2413 const bool editupdate,
2414 const bool use_render_params)
2415 {
2416 ParticleSystem *psys = sim->psys;
2417 ParticleSettings *part = psys->part;
2418 int totparent = 0, between = 0;
2419 int segments = 1 << part->draw_step;
2420 int totchild = psys->totchild;
2421
2422 psys_thread_context_init(ctx, sim);
2423
2424 /*---start figuring out what is actually wanted---*/
2425 if (psys_in_edit_mode(sim->depsgraph, psys)) {
2426 ParticleEditSettings *pset = &scene->toolsettings->particle;
2427
2428 if ((use_render_params == 0) &&
2429 (psys_orig_edit_get(psys) == NULL || pset->flag & PE_DRAW_PART) == 0) {
2430 totchild = 0;
2431 }
2432
2433 segments = 1 << pset->draw_step;
2434 }
2435
2436 if (totchild && part->childtype == PART_CHILD_FACES) {
2437 totparent = (int)(totchild * part->parents * 0.3f);
2438
2439 if (use_render_params && part->child_nbr && part->ren_child_nbr) {
2440 totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
2441 }
2442
2443 /* part->parents could still be 0 so we can't test with totparent */
2444 between = 1;
2445 }
2446
2447 if (use_render_params) {
2448 segments = 1 << part->ren_step;
2449 }
2450 else {
2451 totchild = (int)((float)totchild * (float)part->disp / 100.0f);
2452 }
2453
2454 totparent = MIN2(totparent, totchild);
2455
2456 if (totchild == 0) {
2457 return false;
2458 }
2459
2460 /* fill context values */
2461 ctx->between = between;
2462 ctx->segments = segments;
2463 if (ELEM(part->kink, PART_KINK_SPIRAL)) {
2464 ctx->extra_segments = max_ii(part->kink_extra_steps, 1);
2465 }
2466 else {
2467 ctx->extra_segments = 0;
2468 }
2469 ctx->totchild = totchild;
2470 ctx->totparent = totparent;
2471 ctx->parent_pass = 0;
2472 ctx->cfra = cfra;
2473 ctx->editupdate = editupdate;
2474
2475 psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim);
2476
2477 /* cache all relevant vertex groups if they exist */
2478 ctx->vg_length = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_LENGTH);
2479 ctx->vg_clump = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_CLUMP);
2480 ctx->vg_kink = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_KINK);
2481 ctx->vg_rough1 = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_ROUGH1);
2482 ctx->vg_rough2 = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_ROUGH2);
2483 ctx->vg_roughe = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_ROUGHE);
2484 ctx->vg_twist = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_TWIST);
2485 if (psys->part->flag & PART_CHILD_EFFECT) {
2486 ctx->vg_effector = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_EFFECTOR);
2487 }
2488
2489 /* prepare curvemapping tables */
2490 if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve) {
2491 ctx->clumpcurve = BKE_curvemapping_copy(part->clumpcurve);
2492 BKE_curvemapping_changed_all(ctx->clumpcurve);
2493 }
2494 else {
2495 ctx->clumpcurve = NULL;
2496 }
2497 if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve) {
2498 ctx->roughcurve = BKE_curvemapping_copy(part->roughcurve);
2499 BKE_curvemapping_changed_all(ctx->roughcurve);
2500 }
2501 else {
2502 ctx->roughcurve = NULL;
2503 }
2504 if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) {
2505 ctx->twistcurve = BKE_curvemapping_copy(part->twistcurve);
2506 BKE_curvemapping_changed_all(ctx->twistcurve);
2507 }
2508 else {
2509 ctx->twistcurve = NULL;
2510 }
2511
2512 return true;
2513 }
2514
psys_task_init_path(ParticleTask * task,ParticleSimulationData * sim)2515 static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim)
2516 {
2517 /* init random number generator */
2518 int seed = 31415926 + sim->psys->seed;
2519
2520 task->rng_path = BLI_rng_new(seed);
2521 }
2522
2523 /* note: this function must be thread safe, except for branching! */
psys_thread_create_path(ParticleTask * task,struct ChildParticle * cpa,ParticleCacheKey * child_keys,int i)2524 static void psys_thread_create_path(ParticleTask *task,
2525 struct ChildParticle *cpa,
2526 ParticleCacheKey *child_keys,
2527 int i)
2528 {
2529 ParticleThreadContext *ctx = task->ctx;
2530 Object *ob = ctx->sim.ob;
2531 ParticleSystem *psys = ctx->sim.psys;
2532 ParticleSettings *part = psys->part;
2533 ParticleCacheKey **cache = psys->childcache;
2534 PTCacheEdit *edit = psys_orig_edit_get(psys);
2535 ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.depsgraph, psys) && edit ?
2536 edit->pathcache :
2537 psys->pathcache;
2538 ParticleCacheKey *child, *key[4];
2539 ParticleTexture ptex;
2540 float *cpa_fuv = 0, *par_rot = 0, rot[4];
2541 float orco[3], hairmat[4][4], dvec[3], off1[4][3], off2[4][3];
2542 float eff_length, eff_vec[3], weight[4];
2543 int k, cpa_num;
2544 short cpa_from;
2545
2546 if (!pcache) {
2547 return;
2548 }
2549
2550 if (ctx->between) {
2551 ParticleData *pa = psys->particles + cpa->pa[0];
2552 int w, needupdate;
2553 float foffset, wsum = 0.f;
2554 float co[3];
2555 float p_min = part->parting_min;
2556 float p_max = part->parting_max;
2557 /* Virtual parents don't work nicely with parting. */
2558 float p_fac = part->parents > 0.f ? 0.f : part->parting_fac;
2559
2560 if (ctx->editupdate) {
2561 needupdate = 0;
2562 w = 0;
2563 while (w < 4 && cpa->pa[w] >= 0) {
2564 if (edit->points[cpa->pa[w]].flag & PEP_EDIT_RECALC) {
2565 needupdate = 1;
2566 break;
2567 }
2568 w++;
2569 }
2570
2571 if (!needupdate) {
2572 return;
2573 }
2574
2575 memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
2576 }
2577
2578 /* get parent paths */
2579 for (w = 0; w < 4; w++) {
2580 if (cpa->pa[w] >= 0) {
2581 key[w] = pcache[cpa->pa[w]];
2582 weight[w] = cpa->w[w];
2583 }
2584 else {
2585 key[w] = pcache[0];
2586 weight[w] = 0.f;
2587 }
2588 }
2589
2590 /* modify weights to create parting */
2591 if (p_fac > 0.f) {
2592 const ParticleCacheKey *key_0_last = pcache_key_segment_endpoint_safe(key[0]);
2593 for (w = 0; w < 4; w++) {
2594 if (w && (weight[w] > 0.f)) {
2595 const ParticleCacheKey *key_w_last = pcache_key_segment_endpoint_safe(key[w]);
2596 float d;
2597 if (part->flag & PART_CHILD_LONG_HAIR) {
2598 /* For long hair use tip distance/root distance as parting
2599 * factor instead of root to tip angle. */
2600 float d1 = len_v3v3(key[0]->co, key[w]->co);
2601 float d2 = len_v3v3(key_0_last->co, key_w_last->co);
2602
2603 d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f;
2604 }
2605 else {
2606 float v1[3], v2[3];
2607 sub_v3_v3v3(v1, key_0_last->co, key[0]->co);
2608 sub_v3_v3v3(v2, key_w_last->co, key[w]->co);
2609 normalize_v3(v1);
2610 normalize_v3(v2);
2611
2612 d = RAD2DEGF(saacos(dot_v3v3(v1, v2)));
2613 }
2614
2615 if (p_max > p_min) {
2616 d = (d - p_min) / (p_max - p_min);
2617 }
2618 else {
2619 d = (d - p_min) <= 0.f ? 0.f : 1.f;
2620 }
2621
2622 CLAMP(d, 0.f, 1.f);
2623
2624 if (d > 0.f) {
2625 weight[w] *= (1.f - d);
2626 }
2627 }
2628 wsum += weight[w];
2629 }
2630 for (w = 0; w < 4; w++) {
2631 weight[w] /= wsum;
2632 }
2633
2634 interp_v4_v4v4(weight, cpa->w, weight, p_fac);
2635 }
2636
2637 /* get the original coordinates (orco) for texture usage */
2638 cpa_num = cpa->num;
2639
2640 foffset = cpa->foffset;
2641 cpa_fuv = cpa->fuv;
2642 cpa_from = PART_FROM_FACE;
2643
2644 psys_particle_on_emitter(
2645 ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco);
2646
2647 mul_m4_v3(ob->obmat, co);
2648
2649 for (w = 0; w < 4; w++) {
2650 sub_v3_v3v3(off1[w], co, key[w]->co);
2651 }
2652
2653 psys_mat_hair_to_global(ob, ctx->sim.psmd->mesh_final, psys->part->from, pa, hairmat);
2654 }
2655 else {
2656 ParticleData *pa = psys->particles + cpa->parent;
2657 float co[3];
2658 if (ctx->editupdate) {
2659 if (!(edit->points[cpa->parent].flag & PEP_EDIT_RECALC)) {
2660 return;
2661 }
2662
2663 memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
2664 }
2665
2666 /* get the parent path */
2667 key[0] = pcache[cpa->parent];
2668
2669 /* get the original coordinates (orco) for texture usage */
2670 cpa_from = part->from;
2671
2672 /*
2673 * NOTE: Should in theory be the same as:
2674 * cpa_num = psys_particle_dm_face_lookup(
2675 * ctx->sim.psmd->dm_final,
2676 * ctx->sim.psmd->dm_deformed,
2677 * pa->num, pa->fuv,
2678 * NULL);
2679 */
2680 cpa_num = (ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? pa->num :
2681 pa->num_dmcache;
2682
2683 /* XXX hack to avoid messed up particle num and subsequent crash (T40733) */
2684 if (cpa_num > ctx->sim.psmd->mesh_final->totface) {
2685 cpa_num = 0;
2686 }
2687 cpa_fuv = pa->fuv;
2688
2689 psys_particle_on_emitter(ctx->sim.psmd,
2690 cpa_from,
2691 cpa_num,
2692 DMCACHE_ISCHILD,
2693 cpa_fuv,
2694 pa->foffset,
2695 co,
2696 0,
2697 0,
2698 0,
2699 orco);
2700
2701 psys_mat_hair_to_global(ob, ctx->sim.psmd->mesh_final, psys->part->from, pa, hairmat);
2702 }
2703
2704 child_keys->segments = ctx->segments;
2705
2706 /* get different child parameters from textures & vgroups */
2707 get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
2708
2709 if (ptex.exist < psys_frand(psys, i + 24)) {
2710 child_keys->segments = -1;
2711 return;
2712 }
2713
2714 /* create the child path */
2715 for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
2716 if (ctx->between) {
2717 int w = 0;
2718
2719 zero_v3(child->co);
2720 zero_v3(child->vel);
2721 unit_qt(child->rot);
2722
2723 for (w = 0; w < 4; w++) {
2724 copy_v3_v3(off2[w], off1[w]);
2725
2726 if (part->flag & PART_CHILD_LONG_HAIR) {
2727 /* Use parent rotation (in addition to emission location) to determine child offset. */
2728 if (k) {
2729 mul_qt_v3((key[w] + k)->rot, off2[w]);
2730 }
2731
2732 /* Fade the effect of rotation for even lengths in the end */
2733 project_v3_v3v3(dvec, off2[w], (key[w] + k)->vel);
2734 madd_v3_v3fl(off2[w], dvec, -(float)k / (float)ctx->segments);
2735 }
2736
2737 add_v3_v3(off2[w], (key[w] + k)->co);
2738 }
2739
2740 /* child position is the weighted sum of parent positions */
2741 interp_v3_v3v3v3v3(child->co, off2[0], off2[1], off2[2], off2[3], weight);
2742 interp_v3_v3v3v3v3(child->vel,
2743 (key[0] + k)->vel,
2744 (key[1] + k)->vel,
2745 (key[2] + k)->vel,
2746 (key[3] + k)->vel,
2747 weight);
2748
2749 copy_qt_qt(child->rot, (key[0] + k)->rot);
2750 }
2751 else {
2752 if (k) {
2753 mul_qt_qtqt(rot, (key[0] + k)->rot, key[0]->rot);
2754 par_rot = rot;
2755 }
2756 else {
2757 par_rot = key[0]->rot;
2758 }
2759 /* offset the child from the parent position */
2760 offset_child(cpa,
2761 (ParticleKey *)(key[0] + k),
2762 par_rot,
2763 (ParticleKey *)child,
2764 part->childflat,
2765 part->childrad);
2766 }
2767
2768 child->time = (float)k / (float)ctx->segments;
2769 }
2770
2771 /* apply effectors */
2772 if (part->flag & PART_CHILD_EFFECT) {
2773 for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
2774 if (k) {
2775 do_path_effectors(&ctx->sim,
2776 cpa->pa[0],
2777 child,
2778 k,
2779 ctx->segments,
2780 child_keys->co,
2781 ptex.effector,
2782 0.0f,
2783 ctx->cfra,
2784 &eff_length,
2785 eff_vec);
2786 }
2787 else {
2788 sub_v3_v3v3(eff_vec, (child + 1)->co, child->co);
2789 eff_length = len_v3(eff_vec);
2790 }
2791 }
2792 }
2793
2794 {
2795 ParticleData *pa = NULL;
2796 ParticleCacheKey *par = NULL;
2797 float par_co[3];
2798 float par_orco[3];
2799
2800 if (ctx->totparent) {
2801 if (i >= ctx->totparent) {
2802 pa = &psys->particles[cpa->parent];
2803 /* this is now threadsafe, virtual parents are calculated before rest of children */
2804 BLI_assert(cpa->parent < psys->totchildcache);
2805 par = cache[cpa->parent];
2806 }
2807 }
2808 else if (cpa->parent >= 0) {
2809 pa = &psys->particles[cpa->parent];
2810 par = pcache[cpa->parent];
2811
2812 /* If particle is non-existing, try to pick a viable parent from particles
2813 * used for interpolation. */
2814 for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) {
2815 if (cpa->pa[k] >= 0) {
2816 pa = &psys->particles[cpa->pa[k]];
2817 par = pcache[cpa->pa[k]];
2818 }
2819 }
2820
2821 if (pa->flag & PARS_UNEXIST) {
2822 pa = NULL;
2823 }
2824 }
2825
2826 if (pa) {
2827 ListBase modifiers;
2828 BLI_listbase_clear(&modifiers);
2829
2830 psys_particle_on_emitter(ctx->sim.psmd,
2831 part->from,
2832 pa->num,
2833 pa->num_dmcache,
2834 pa->fuv,
2835 pa->foffset,
2836 par_co,
2837 NULL,
2838 NULL,
2839 NULL,
2840 par_orco);
2841
2842 psys_apply_child_modifiers(
2843 ctx, &modifiers, cpa, &ptex, orco, hairmat, child_keys, par, par_orco);
2844 }
2845 else {
2846 zero_v3(par_orco);
2847 }
2848 }
2849
2850 /* Hide virtual parents */
2851 if (i < ctx->totparent) {
2852 child_keys->segments = -1;
2853 }
2854 }
2855
exec_child_path_cache(TaskPool * __restrict UNUSED (pool),void * taskdata)2856 static void exec_child_path_cache(TaskPool *__restrict UNUSED(pool), void *taskdata)
2857 {
2858 ParticleTask *task = taskdata;
2859 ParticleThreadContext *ctx = task->ctx;
2860 ParticleSystem *psys = ctx->sim.psys;
2861 ParticleCacheKey **cache = psys->childcache;
2862 ChildParticle *cpa;
2863 int i;
2864
2865 cpa = psys->child + task->begin;
2866 for (i = task->begin; i < task->end; i++, cpa++) {
2867 BLI_assert(i < psys->totchildcache);
2868 psys_thread_create_path(task, cpa, cache[i], i);
2869 }
2870 }
2871
psys_cache_child_paths(ParticleSimulationData * sim,float cfra,const bool editupdate,const bool use_render_params)2872 void psys_cache_child_paths(ParticleSimulationData *sim,
2873 float cfra,
2874 const bool editupdate,
2875 const bool use_render_params)
2876 {
2877 TaskPool *task_pool;
2878 ParticleThreadContext ctx;
2879 ParticleTask *tasks_parent, *tasks_child;
2880 int numtasks_parent, numtasks_child;
2881 int i, totchild, totparent;
2882
2883 if (sim->psys->flag & PSYS_GLOBAL_HAIR) {
2884 return;
2885 }
2886
2887 /* create a task pool for child path tasks */
2888 if (!psys_thread_context_init_path(&ctx, sim, sim->scene, cfra, editupdate, use_render_params)) {
2889 return;
2890 }
2891
2892 task_pool = BLI_task_pool_create(&ctx, TASK_PRIORITY_LOW);
2893 totchild = ctx.totchild;
2894 totparent = ctx.totparent;
2895
2896 if (editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
2897 /* just overwrite the existing cache */
2898 }
2899 else {
2900 /* clear out old and create new empty path cache */
2901 free_child_path_cache(sim->psys);
2902
2903 sim->psys->childcache = psys_alloc_path_cache_buffers(
2904 &sim->psys->childcachebufs, totchild, ctx.segments + ctx.extra_segments + 1);
2905 sim->psys->totchildcache = totchild;
2906 }
2907
2908 /* cache parent paths */
2909 ctx.parent_pass = 1;
2910 psys_tasks_create(&ctx, 0, totparent, &tasks_parent, &numtasks_parent);
2911 for (i = 0; i < numtasks_parent; i++) {
2912 ParticleTask *task = &tasks_parent[i];
2913
2914 psys_task_init_path(task, sim);
2915 BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, NULL);
2916 }
2917 BLI_task_pool_work_and_wait(task_pool);
2918
2919 /* cache child paths */
2920 ctx.parent_pass = 0;
2921 psys_tasks_create(&ctx, totparent, totchild, &tasks_child, &numtasks_child);
2922 for (i = 0; i < numtasks_child; i++) {
2923 ParticleTask *task = &tasks_child[i];
2924
2925 psys_task_init_path(task, sim);
2926 BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, NULL);
2927 }
2928 BLI_task_pool_work_and_wait(task_pool);
2929
2930 BLI_task_pool_free(task_pool);
2931
2932 psys_tasks_free(tasks_parent, numtasks_parent);
2933 psys_tasks_free(tasks_child, numtasks_child);
2934
2935 psys_thread_context_free(&ctx);
2936 }
2937
2938 /* figure out incremental rotations along path starting from unit quat */
cache_key_incremental_rotation(ParticleCacheKey * key0,ParticleCacheKey * key1,ParticleCacheKey * key2,float * prev_tangent,int i)2939 static void cache_key_incremental_rotation(ParticleCacheKey *key0,
2940 ParticleCacheKey *key1,
2941 ParticleCacheKey *key2,
2942 float *prev_tangent,
2943 int i)
2944 {
2945 float cosangle, angle, tangent[3], normal[3], q[4];
2946
2947 switch (i) {
2948 case 0:
2949 /* start from second key */
2950 break;
2951 case 1:
2952 /* calculate initial tangent for incremental rotations */
2953 sub_v3_v3v3(prev_tangent, key0->co, key1->co);
2954 normalize_v3(prev_tangent);
2955 unit_qt(key1->rot);
2956 break;
2957 default:
2958 sub_v3_v3v3(tangent, key0->co, key1->co);
2959 normalize_v3(tangent);
2960
2961 cosangle = dot_v3v3(tangent, prev_tangent);
2962
2963 /* note we do the comparison on cosangle instead of
2964 * angle, since floating point accuracy makes it give
2965 * different results across platforms */
2966 if (cosangle > 0.999999f) {
2967 copy_v4_v4(key1->rot, key2->rot);
2968 }
2969 else {
2970 angle = saacos(cosangle);
2971 cross_v3_v3v3(normal, prev_tangent, tangent);
2972 axis_angle_to_quat(q, normal, angle);
2973 mul_qt_qtqt(key1->rot, q, key2->rot);
2974 }
2975
2976 copy_v3_v3(prev_tangent, tangent);
2977 }
2978 }
2979
2980 /**
2981 * Calculates paths ready for drawing/rendering
2982 * - Useful for making use of opengl vertex arrays for super fast strand drawing.
2983 * - Makes child strands possible and creates them too into the cache.
2984 * - Cached path data is also used to determine cut position for the editmode tool. */
psys_cache_paths(ParticleSimulationData * sim,float cfra,const bool use_render_params)2985 void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params)
2986 {
2987 PARTICLE_PSMD;
2988 ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
2989 ParticleSystem *psys = sim->psys;
2990 ParticleSettings *part = psys->part;
2991 ParticleCacheKey *ca, **cache;
2992
2993 Mesh *hair_mesh = (psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) ?
2994 psys->hair_out_mesh :
2995 NULL;
2996
2997 ParticleKey result;
2998
2999 Material *ma;
3000 ParticleInterpolationData pind;
3001 ParticleTexture ptex;
3002
3003 PARTICLE_P;
3004
3005 float birthtime = 0.0, dietime = 0.0;
3006 float t, time = 0.0, dfra = 1.0 /* , frs_sec = sim->scene->r.frs_sec*/ /*UNUSED*/;
3007 float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
3008 float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
3009 float rotmat[3][3];
3010 int k;
3011 int segments = (int)pow(2.0, (double)((use_render_params) ? part->ren_step : part->draw_step));
3012 int totpart = psys->totpart;
3013 float length, vec[3];
3014 float *vg_effector = NULL;
3015 float *vg_length = NULL, pa_length = 1.0f;
3016 int keyed, baked;
3017
3018 /* we don't have anything valid to create paths from so let's quit here */
3019 if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0) {
3020 return;
3021 }
3022
3023 if (psys_in_edit_mode(sim->depsgraph, psys)) {
3024 if ((psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) {
3025 return;
3026 }
3027 }
3028
3029 keyed = psys->flag & PSYS_KEYED;
3030 baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
3031
3032 /* clear out old and create new empty path cache */
3033 psys_free_path_cache(psys, psys->edit);
3034 cache = psys->pathcache = psys_alloc_path_cache_buffers(
3035 &psys->pathcachebufs, totpart, segments + 1);
3036
3037 psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
3038 ma = BKE_object_material_get(sim->ob, psys->part->omat);
3039 if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT)) {
3040 copy_v3_v3(col, &ma->r);
3041 }
3042
3043 if ((psys->flag & PSYS_GLOBAL_HAIR) == 0) {
3044 if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
3045 vg_effector = psys_cache_vgroup(psmd->mesh_final, psys, PSYS_VG_EFFECTOR);
3046 }
3047
3048 if (!psys->totchild) {
3049 vg_length = psys_cache_vgroup(psmd->mesh_final, psys, PSYS_VG_LENGTH);
3050 }
3051 }
3052
3053 /* ensure we have tessfaces to be used for mapping */
3054 if (part->from != PART_FROM_VERT) {
3055 BKE_mesh_tessface_ensure(psmd->mesh_final);
3056 }
3057
3058 /*---first main loop: create all actual particles' paths---*/
3059 LOOP_PARTICLES
3060 {
3061 if (!psys->totchild) {
3062 psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
3063 pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
3064 if (vg_length) {
3065 pa_length *= psys_particle_value_from_verts(psmd->mesh_final, part->from, pa, vg_length);
3066 }
3067 }
3068
3069 pind.keyed = keyed;
3070 pind.cache = baked ? psys->pointcache : NULL;
3071 pind.epoint = NULL;
3072 pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
3073 pind.mesh = hair_mesh;
3074
3075 memset(cache[p], 0, sizeof(*cache[p]) * (segments + 1));
3076
3077 cache[p]->segments = segments;
3078
3079 /*--get the first data points--*/
3080 init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
3081
3082 /* 'hairmat' is needed for non-hair particle too so we get proper rotations. */
3083 psys_mat_hair_to_global(sim->ob, psmd->mesh_final, psys->part->from, pa, hairmat);
3084 copy_v3_v3(rotmat[0], hairmat[2]);
3085 copy_v3_v3(rotmat[1], hairmat[1]);
3086 copy_v3_v3(rotmat[2], hairmat[0]);
3087
3088 if (part->draw & PART_ABS_PATH_TIME) {
3089 birthtime = MAX2(pind.birthtime, part->path_start);
3090 dietime = MIN2(pind.dietime, part->path_end);
3091 }
3092 else {
3093 float tb = pind.birthtime;
3094 birthtime = tb + part->path_start * (pind.dietime - tb);
3095 dietime = tb + part->path_end * (pind.dietime - tb);
3096 }
3097
3098 if (birthtime >= dietime) {
3099 cache[p]->segments = -1;
3100 continue;
3101 }
3102
3103 dietime = birthtime + pa_length * (dietime - birthtime);
3104
3105 /*--interpolate actual path from data points--*/
3106 for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
3107 time = (float)k / (float)segments;
3108 t = birthtime + time * (dietime - birthtime);
3109 result.time = -t;
3110 do_particle_interpolation(psys, p, pa, t, &pind, &result);
3111 copy_v3_v3(ca->co, result.co);
3112
3113 /* dynamic hair is in object space */
3114 /* keyed and baked are already in global space */
3115 if (hair_mesh) {
3116 mul_m4_v3(sim->ob->obmat, ca->co);
3117 }
3118 else if (!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) {
3119 mul_m4_v3(hairmat, ca->co);
3120 }
3121
3122 copy_v3_v3(ca->col, col);
3123 }
3124
3125 if (part->type == PART_HAIR) {
3126 HairKey *hkey;
3127
3128 for (k = 0, hkey = pa->hair; k < pa->totkey; k++, hkey++) {
3129 mul_v3_m4v3(hkey->world_co, hairmat, hkey->co);
3130 }
3131 }
3132
3133 /*--modify paths and calculate rotation & velocity--*/
3134
3135 if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
3136 /* apply effectors */
3137 if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
3138 float effector = 1.0f;
3139 if (vg_effector) {
3140 effector *= psys_particle_value_from_verts(
3141 psmd->mesh_final, psys->part->from, pa, vg_effector);
3142 }
3143
3144 sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
3145 length = len_v3(vec);
3146
3147 for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++) {
3148 do_path_effectors(
3149 sim, p, ca, k, segments, cache[p]->co, effector, dfra, cfra, &length, vec);
3150 }
3151 }
3152
3153 /* apply guide curves to path data */
3154 if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) {
3155 for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
3156 /* ca is safe to cast, since only co and vel are used */
3157 do_guides(sim->depsgraph,
3158 sim->psys->part,
3159 sim->psys->effectors,
3160 (ParticleKey *)ca,
3161 p,
3162 (float)k / (float)segments);
3163 }
3164 }
3165
3166 /* lattices have to be calculated separately to avoid mixups between effector calculations */
3167 if (psys->lattice_deform_data) {
3168 for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
3169 BKE_lattice_deform_data_eval_co(
3170 psys->lattice_deform_data, ca->co, psys->lattice_strength);
3171 }
3172 }
3173 }
3174
3175 /* finally do rotation & velocity */
3176 for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++) {
3177 cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
3178
3179 if (k == segments) {
3180 copy_qt_qt(ca->rot, (ca - 1)->rot);
3181 }
3182
3183 /* set velocity */
3184 sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
3185
3186 if (k == 1) {
3187 copy_v3_v3((ca - 1)->vel, ca->vel);
3188 }
3189
3190 ca->time = (float)k / (float)segments;
3191 }
3192 /* First rotation is based on emitting face orientation.
3193 * This is way better than having flipping rotations resulting
3194 * from using a global axis as a rotation pole (vec_to_quat()).
3195 * It's not an ideal solution though since it disregards the
3196 * initial tangent, but taking that in to account will allow
3197 * the possibility of flipping again. -jahka
3198 */
3199 mat3_to_quat_is_ok(cache[p]->rot, rotmat);
3200 }
3201
3202 psys->totcached = totpart;
3203
3204 if (psys->lattice_deform_data) {
3205 BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
3206 psys->lattice_deform_data = NULL;
3207 }
3208
3209 if (vg_effector) {
3210 MEM_freeN(vg_effector);
3211 }
3212
3213 if (vg_length) {
3214 MEM_freeN(vg_length);
3215 }
3216 }
3217
3218 typedef struct CacheEditrPathsIterData {
3219 Object *object;
3220 PTCacheEdit *edit;
3221 ParticleSystemModifierData *psmd;
3222 ParticleData *pa;
3223 int segments;
3224 bool use_weight;
3225 } CacheEditrPathsIterData;
3226
psys_cache_edit_paths_iter(void * __restrict iter_data_v,const int iter,const TaskParallelTLS * __restrict UNUSED (tls))3227 static void psys_cache_edit_paths_iter(void *__restrict iter_data_v,
3228 const int iter,
3229 const TaskParallelTLS *__restrict UNUSED(tls))
3230 {
3231 CacheEditrPathsIterData *iter_data = (CacheEditrPathsIterData *)iter_data_v;
3232 PTCacheEdit *edit = iter_data->edit;
3233 PTCacheEditPoint *point = &edit->points[iter];
3234 if (edit->totcached && !(point->flag & PEP_EDIT_RECALC)) {
3235 return;
3236 }
3237 if (point->totkey == 0) {
3238 return;
3239 }
3240 Object *ob = iter_data->object;
3241 ParticleSystem *psys = edit->psys;
3242 ParticleCacheKey **cache = edit->pathcache;
3243 ParticleSystemModifierData *psmd = iter_data->psmd;
3244 ParticleData *pa = iter_data->pa ? iter_data->pa + iter : NULL;
3245 PTCacheEditKey *ekey = point->keys;
3246 const int segments = iter_data->segments;
3247 const bool use_weight = iter_data->use_weight;
3248
3249 float birthtime = 0.0f, dietime = 0.0f;
3250 float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f};
3251
3252 ParticleInterpolationData pind;
3253 pind.keyed = 0;
3254 pind.cache = NULL;
3255 pind.epoint = point;
3256 pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0;
3257 pind.mesh = NULL;
3258
3259 /* should init_particle_interpolation set this ? */
3260 if (use_weight) {
3261 pind.hkey[0] = NULL;
3262 /* pa != NULL since the weight brush is only available for hair */
3263 pind.hkey[0] = pa->hair;
3264 pind.hkey[1] = pa->hair + 1;
3265 }
3266
3267 memset(cache[iter], 0, sizeof(*cache[iter]) * (segments + 1));
3268
3269 cache[iter]->segments = segments;
3270
3271 /*--get the first data points--*/
3272 init_particle_interpolation(ob, psys, pa, &pind);
3273
3274 if (psys) {
3275 psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
3276 copy_v3_v3(rotmat[0], hairmat[2]);
3277 copy_v3_v3(rotmat[1], hairmat[1]);
3278 copy_v3_v3(rotmat[2], hairmat[0]);
3279 }
3280
3281 birthtime = pind.birthtime;
3282 dietime = pind.dietime;
3283
3284 if (birthtime >= dietime) {
3285 cache[iter]->segments = -1;
3286 return;
3287 }
3288
3289 /*--interpolate actual path from data points--*/
3290 ParticleCacheKey *ca;
3291 int k;
3292 float t, time = 0.0f, keytime = 0.0f;
3293 for (k = 0, ca = cache[iter]; k <= segments; k++, ca++) {
3294 time = (float)k / (float)segments;
3295 t = birthtime + time * (dietime - birthtime);
3296 ParticleKey result;
3297 result.time = -t;
3298 do_particle_interpolation(psys, iter, pa, t, &pind, &result);
3299 copy_v3_v3(ca->co, result.co);
3300
3301 /* non-hair points are already in global space */
3302 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
3303 mul_m4_v3(hairmat, ca->co);
3304
3305 if (k) {
3306 cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
3307
3308 if (k == segments) {
3309 copy_qt_qt(ca->rot, (ca - 1)->rot);
3310 }
3311
3312 /* set velocity */
3313 sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
3314
3315 if (k == 1) {
3316 copy_v3_v3((ca - 1)->vel, ca->vel);
3317 }
3318 }
3319 }
3320 else {
3321 ca->vel[0] = ca->vel[1] = 0.0f;
3322 ca->vel[2] = 1.0f;
3323 }
3324
3325 /* selection coloring in edit mode */
3326 if (use_weight) {
3327 if (k == 0) {
3328 BKE_defvert_weight_to_rgb(ca->col, pind.hkey[1]->weight);
3329 }
3330 else {
3331 /* warning: copied from 'do_particle_interpolation' (without 'mvert' array stepping) */
3332 float real_t;
3333 if (result.time < 0.0f) {
3334 real_t = -result.time;
3335 }
3336 else {
3337 real_t = pind.hkey[0]->time +
3338 t * (pind.hkey[0][pa->totkey - 1].time - pind.hkey[0]->time);
3339 }
3340
3341 while (pind.hkey[1]->time < real_t) {
3342 pind.hkey[1]++;
3343 }
3344 pind.hkey[0] = pind.hkey[1] - 1;
3345 /* end copy */
3346
3347 float w1[3], w2[3];
3348 keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
3349
3350 BKE_defvert_weight_to_rgb(w1, pind.hkey[0]->weight);
3351 BKE_defvert_weight_to_rgb(w2, pind.hkey[1]->weight);
3352
3353 interp_v3_v3v3(ca->col, w1, w2, keytime);
3354 }
3355 }
3356 else {
3357 /* HACK(fclem): Instead of setting the color we pass the select state in the red channel.
3358 * This is then picked up in DRW and the gpu shader will do the color interpolation. */
3359 if ((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT) {
3360 if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
3361 ca->col[0] = 1.0f;
3362 }
3363 else {
3364 keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
3365 ca->col[0] = 1.0f - keytime;
3366 }
3367 }
3368 else {
3369 if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
3370 keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
3371 ca->col[0] = keytime;
3372 }
3373 else {
3374 ca->col[0] = 0.0f;
3375 }
3376 }
3377 }
3378
3379 ca->time = t;
3380 }
3381 if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
3382 /* First rotation is based on emitting face orientation.
3383 * This is way better than having flipping rotations resulting
3384 * from using a global axis as a rotation pole (vec_to_quat()).
3385 * It's not an ideal solution though since it disregards the
3386 * initial tangent, but taking that in to account will allow
3387 * the possibility of flipping again. -jahka
3388 */
3389 mat3_to_quat_is_ok(cache[iter]->rot, rotmat);
3390 }
3391 }
3392
psys_cache_edit_paths(Depsgraph * depsgraph,Scene * scene,Object * ob,PTCacheEdit * edit,float cfra,const bool use_render_params)3393 void psys_cache_edit_paths(Depsgraph *depsgraph,
3394 Scene *scene,
3395 Object *ob,
3396 PTCacheEdit *edit,
3397 float cfra,
3398 const bool use_render_params)
3399 {
3400 ParticleCacheKey **cache = edit->pathcache;
3401 ParticleEditSettings *pset = &scene->toolsettings->particle;
3402
3403 ParticleSystem *psys = edit->psys;
3404
3405 ParticleData *pa = psys ? psys->particles : NULL;
3406
3407 int segments = 1 << pset->draw_step;
3408 int totpart = edit->totpoint, recalc_set = 0;
3409
3410 if (edit->psmd_eval == NULL) {
3411 return;
3412 }
3413
3414 segments = MAX2(segments, 4);
3415
3416 if (!cache || edit->totpoint != edit->totcached) {
3417 /* Clear out old and create new empty path cache. */
3418 psys_free_path_cache(edit->psys, edit);
3419 cache = edit->pathcache = psys_alloc_path_cache_buffers(
3420 &edit->pathcachebufs, totpart, segments + 1);
3421 /* Set flag for update (child particles check this too). */
3422 int i;
3423 PTCacheEditPoint *point;
3424 for (i = 0, point = edit->points; i < totpart; i++, point++) {
3425 point->flag |= PEP_EDIT_RECALC;
3426 }
3427 recalc_set = 1;
3428 }
3429
3430 const bool use_weight = (pset->brushtype == PE_BRUSH_WEIGHT) && (psys != NULL) &&
3431 (psys->particles != NULL);
3432
3433 CacheEditrPathsIterData iter_data;
3434 iter_data.object = ob;
3435 iter_data.edit = edit;
3436 iter_data.psmd = edit->psmd_eval;
3437 iter_data.pa = pa;
3438 iter_data.segments = segments;
3439 iter_data.use_weight = use_weight;
3440
3441 TaskParallelSettings settings;
3442 BLI_parallel_range_settings_defaults(&settings);
3443 BLI_task_parallel_range(0, edit->totpoint, &iter_data, psys_cache_edit_paths_iter, &settings);
3444
3445 edit->totcached = totpart;
3446
3447 if (psys) {
3448 ParticleSimulationData sim = {0};
3449 sim.depsgraph = depsgraph;
3450 sim.scene = scene;
3451 sim.ob = ob;
3452 sim.psys = psys;
3453 sim.psmd = edit->psmd_eval;
3454
3455 psys_cache_child_paths(&sim, cfra, true, use_render_params);
3456 }
3457
3458 /* clear recalc flag if set here */
3459 if (recalc_set) {
3460 PTCacheEditPoint *point;
3461 int i;
3462 for (i = 0, point = edit->points; i < totpart; i++, point++) {
3463 point->flag &= ~PEP_EDIT_RECALC;
3464 }
3465 }
3466 }
3467 /************************************************/
3468 /* Particle Key handling */
3469 /************************************************/
copy_particle_key(ParticleKey * to,ParticleKey * from,int time)3470 void copy_particle_key(ParticleKey *to, ParticleKey *from, int time)
3471 {
3472 if (time) {
3473 memcpy(to, from, sizeof(ParticleKey));
3474 }
3475 else {
3476 float to_time = to->time;
3477 memcpy(to, from, sizeof(ParticleKey));
3478 to->time = to_time;
3479 }
3480 }
psys_get_from_key(ParticleKey * key,float loc[3],float vel[3],float rot[4],float * time)3481 void psys_get_from_key(ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time)
3482 {
3483 if (loc) {
3484 copy_v3_v3(loc, key->co);
3485 }
3486 if (vel) {
3487 copy_v3_v3(vel, key->vel);
3488 }
3489 if (rot) {
3490 copy_qt_qt(rot, key->rot);
3491 }
3492 if (time) {
3493 *time = key->time;
3494 }
3495 }
3496
triatomat(float * v1,float * v2,float * v3,float (* uv)[2],float mat[4][4])3497 static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[4][4])
3498 {
3499 float det, w1, w2, d1[2], d2[2];
3500
3501 memset(mat, 0, sizeof(float[4][4]));
3502 mat[3][3] = 1.0f;
3503
3504 /* first axis is the normal */
3505 normal_tri_v3(mat[2], v1, v2, v3);
3506
3507 /* second axis along (1, 0) in uv space */
3508 if (uv) {
3509 d1[0] = uv[1][0] - uv[0][0];
3510 d1[1] = uv[1][1] - uv[0][1];
3511 d2[0] = uv[2][0] - uv[0][0];
3512 d2[1] = uv[2][1] - uv[0][1];
3513
3514 det = d2[0] * d1[1] - d2[1] * d1[0];
3515
3516 if (det != 0.0f) {
3517 det = 1.0f / det;
3518 w1 = -d2[1] * det;
3519 w2 = d1[1] * det;
3520
3521 mat[1][0] = w1 * (v2[0] - v1[0]) + w2 * (v3[0] - v1[0]);
3522 mat[1][1] = w1 * (v2[1] - v1[1]) + w2 * (v3[1] - v1[1]);
3523 mat[1][2] = w1 * (v2[2] - v1[2]) + w2 * (v3[2] - v1[2]);
3524 normalize_v3(mat[1]);
3525 }
3526 else {
3527 mat[1][0] = mat[1][1] = mat[1][2] = 0.0f;
3528 }
3529 }
3530 else {
3531 sub_v3_v3v3(mat[1], v2, v1);
3532 normalize_v3(mat[1]);
3533 }
3534
3535 /* third as a cross product */
3536 cross_v3_v3v3(mat[0], mat[1], mat[2]);
3537 }
3538
psys_face_mat(Object * ob,Mesh * mesh,ParticleData * pa,float mat[4][4],int orco)3539 static void psys_face_mat(Object *ob, Mesh *mesh, ParticleData *pa, float mat[4][4], int orco)
3540 {
3541 float v[3][3];
3542 MFace *mface;
3543 OrigSpaceFace *osface;
3544 float(*orcodata)[3];
3545
3546 int i = (ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? pa->num : pa->num_dmcache;
3547 if (i == -1 || i >= mesh->totface) {
3548 unit_m4(mat);
3549 return;
3550 }
3551
3552 mface = &mesh->mface[i];
3553 osface = CustomData_get(&mesh->fdata, i, CD_ORIGSPACE);
3554
3555 if (orco && (orcodata = CustomData_get_layer(&mesh->vdata, CD_ORCO))) {
3556 copy_v3_v3(v[0], orcodata[mface->v1]);
3557 copy_v3_v3(v[1], orcodata[mface->v2]);
3558 copy_v3_v3(v[2], orcodata[mface->v3]);
3559
3560 /* ugly hack to use non-transformed orcos, since only those
3561 * give symmetric results for mirroring in particle mode */
3562 if (CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX)) {
3563 BKE_mesh_orco_verts_transform(ob->data, v, 3, 1);
3564 }
3565 }
3566 else {
3567 copy_v3_v3(v[0], mesh->mvert[mface->v1].co);
3568 copy_v3_v3(v[1], mesh->mvert[mface->v2].co);
3569 copy_v3_v3(v[2], mesh->mvert[mface->v3].co);
3570 }
3571
3572 triatomat(v[0], v[1], v[2], (osface) ? osface->uv : NULL, mat);
3573 }
3574
psys_mat_hair_to_object(Object * UNUSED (ob),Mesh * mesh,short from,ParticleData * pa,float hairmat[4][4])3575 void psys_mat_hair_to_object(
3576 Object *UNUSED(ob), Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
3577 {
3578 float vec[3];
3579
3580 /* can happen when called from a different object's modifier */
3581 if (!mesh) {
3582 unit_m4(hairmat);
3583 return;
3584 }
3585
3586 psys_face_mat(0, mesh, pa, hairmat, 0);
3587 psys_particle_on_dm(mesh, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0);
3588 copy_v3_v3(hairmat[3], vec);
3589 }
3590
psys_mat_hair_to_orco(Object * ob,Mesh * mesh,short from,ParticleData * pa,float hairmat[4][4])3591 void psys_mat_hair_to_orco(
3592 Object *ob, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
3593 {
3594 float vec[3], orco[3];
3595
3596 psys_face_mat(ob, mesh, pa, hairmat, 1);
3597 psys_particle_on_dm(
3598 mesh, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco);
3599
3600 /* see psys_face_mat for why this function is called */
3601 if (CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX)) {
3602 BKE_mesh_orco_verts_transform(ob->data, &orco, 1, 1);
3603 }
3604 copy_v3_v3(hairmat[3], orco);
3605 }
3606
psys_vec_rot_to_face(Mesh * mesh,ParticleData * pa,float vec[3])3607 void psys_vec_rot_to_face(Mesh *mesh, ParticleData *pa, float vec[3])
3608 {
3609 float mat[4][4];
3610
3611 psys_face_mat(0, mesh, pa, mat, 0);
3612 transpose_m4(mat); /* cheap inverse for rotation matrix */
3613 mul_mat3_m4_v3(mat, vec);
3614 }
3615
psys_mat_hair_to_global(Object * ob,Mesh * mesh,short from,ParticleData * pa,float hairmat[4][4])3616 void psys_mat_hair_to_global(
3617 Object *ob, Mesh *mesh, short from, ParticleData *pa, float hairmat[4][4])
3618 {
3619 float facemat[4][4];
3620
3621 psys_mat_hair_to_object(ob, mesh, from, pa, facemat);
3622
3623 mul_m4_m4m4(hairmat, ob->obmat, facemat);
3624 }
3625
3626 /************************************************/
3627 /* ParticleSettings handling */
3628 /************************************************/
object_add_or_copy_particle_system(Main * bmain,Scene * scene,Object * ob,const char * name,const ParticleSystem * psys_orig)3629 static ModifierData *object_add_or_copy_particle_system(
3630 Main *bmain, Scene *scene, Object *ob, const char *name, const ParticleSystem *psys_orig)
3631 {
3632 ParticleSystem *psys;
3633 ModifierData *md;
3634 ParticleSystemModifierData *psmd;
3635
3636 if (!ob || ob->type != OB_MESH) {
3637 return NULL;
3638 }
3639
3640 if (name == NULL) {
3641 name = (psys_orig != NULL) ? psys_orig->name : DATA_("ParticleSettings");
3642 }
3643
3644 psys = ob->particlesystem.first;
3645 for (; psys; psys = psys->next) {
3646 psys->flag &= ~PSYS_CURRENT;
3647 }
3648
3649 psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
3650 psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
3651 BLI_addtail(&ob->particlesystem, psys);
3652 psys_unique_name(ob, psys, name);
3653
3654 if (psys_orig != NULL) {
3655 psys->part = psys_orig->part;
3656 id_us_plus(&psys->part->id);
3657 }
3658 else {
3659 psys->part = BKE_particlesettings_add(bmain, psys->name);
3660 }
3661 md = BKE_modifier_new(eModifierType_ParticleSystem);
3662 BLI_strncpy(md->name, psys->name, sizeof(md->name));
3663 BKE_modifier_unique_name(&ob->modifiers, md);
3664
3665 psmd = (ParticleSystemModifierData *)md;
3666 psmd->psys = psys;
3667 BLI_addtail(&ob->modifiers, md);
3668
3669 psys->totpart = 0;
3670 psys->flag = PSYS_CURRENT;
3671 if (scene != NULL) {
3672 psys->cfra = BKE_scene_frame_to_ctime(scene, CFRA + 1);
3673 }
3674
3675 DEG_relations_tag_update(bmain);
3676 DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3677
3678 return md;
3679 }
3680
object_add_particle_system(Main * bmain,Scene * scene,Object * ob,const char * name)3681 ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, const char *name)
3682 {
3683 return object_add_or_copy_particle_system(bmain, scene, ob, name, NULL);
3684 }
3685
object_copy_particle_system(Main * bmain,Scene * scene,Object * ob,const ParticleSystem * psys_orig)3686 ModifierData *object_copy_particle_system(Main *bmain,
3687 Scene *scene,
3688 Object *ob,
3689 const ParticleSystem *psys_orig)
3690 {
3691 return object_add_or_copy_particle_system(bmain, scene, ob, NULL, psys_orig);
3692 }
3693
object_remove_particle_system(Main * bmain,Scene * UNUSED (scene),Object * ob)3694 void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob)
3695 {
3696 ParticleSystem *psys = psys_get_current(ob);
3697 ParticleSystemModifierData *psmd;
3698 ModifierData *md;
3699
3700 if (!psys) {
3701 return;
3702 }
3703
3704 /* Clear particle system in fluid modifier. */
3705 if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid))) {
3706 FluidModifierData *fmd = (FluidModifierData *)md;
3707
3708 /* Clear particle system pointer in flow settings. */
3709 if ((fmd->type == MOD_FLUID_TYPE_FLOW) && fmd->flow && fmd->flow->psys) {
3710 if (fmd->flow->psys == psys) {
3711 fmd->flow->psys = NULL;
3712 }
3713 }
3714 /* Clear particle flag in domain settings when removing particle system manually. */
3715 if (fmd->type == MOD_FLUID_TYPE_DOMAIN) {
3716 if (psys->part->type == PART_FLUID_FLIP) {
3717 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP;
3718 }
3719 if (psys->part->type == PART_FLUID_SPRAY || psys->part->type == PART_FLUID_SPRAYFOAM ||
3720 psys->part->type == PART_FLUID_SPRAYBUBBLE ||
3721 psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
3722 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_SPRAY;
3723 }
3724 if (psys->part->type == PART_FLUID_FOAM || psys->part->type == PART_FLUID_SPRAYFOAM ||
3725 psys->part->type == PART_FLUID_FOAMBUBBLE ||
3726 psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
3727 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FOAM;
3728 }
3729 if (psys->part->type == PART_FLUID_BUBBLE || psys->part->type == PART_FLUID_FOAMBUBBLE ||
3730 psys->part->type == PART_FLUID_SPRAYBUBBLE ||
3731 psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
3732 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_BUBBLE;
3733 }
3734 if (psys->part->type == PART_FLUID_TRACER) {
3735 fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_TRACER;
3736 }
3737
3738 /* Disable combined export if combined particle system was deleted. */
3739 if (psys->part->type == PART_FLUID_SPRAYFOAM || psys->part->type == PART_FLUID_SPRAYBUBBLE ||
3740 psys->part->type == PART_FLUID_FOAMBUBBLE ||
3741 psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) {
3742 fmd->domain->sndparticle_combined_export = SNDPARTICLE_COMBINED_EXPORT_OFF;
3743 }
3744 }
3745 }
3746
3747 if ((md = BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint))) {
3748 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
3749 if (pmd->brush && pmd->brush->psys) {
3750 if (pmd->brush->psys == psys) {
3751 pmd->brush->psys = NULL;
3752 }
3753 }
3754 }
3755
3756 /* Clear modifier, skip empty ones. */
3757 psmd = psys_get_modifier(ob, psys);
3758 if (psmd) {
3759 BLI_remlink(&ob->modifiers, psmd);
3760 BKE_modifier_free((ModifierData *)psmd);
3761 }
3762
3763 /* Clear particle system. */
3764 BLI_remlink(&ob->particlesystem, psys);
3765 if (psys->part) {
3766 id_us_min(&psys->part->id);
3767 }
3768 psys_free(ob, psys);
3769
3770 if (ob->particlesystem.first) {
3771 ((ParticleSystem *)ob->particlesystem.first)->flag |= PSYS_CURRENT;
3772 }
3773 else {
3774 ob->mode &= ~OB_MODE_PARTICLE_EDIT;
3775 }
3776
3777 DEG_relations_tag_update(bmain);
3778 DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3779
3780 /* Flush object mode. */
3781 DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
3782 }
3783
BKE_particlesettings_add(Main * bmain,const char * name)3784 ParticleSettings *BKE_particlesettings_add(Main *bmain, const char *name)
3785 {
3786 ParticleSettings *part;
3787
3788 part = BKE_id_new(bmain, ID_PA, name);
3789
3790 return part;
3791 }
3792
BKE_particlesettings_clump_curve_init(ParticleSettings * part)3793 void BKE_particlesettings_clump_curve_init(ParticleSettings *part)
3794 {
3795 CurveMapping *cumap = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
3796
3797 cumap->cm[0].curve[0].x = 0.0f;
3798 cumap->cm[0].curve[0].y = 1.0f;
3799 cumap->cm[0].curve[1].x = 1.0f;
3800 cumap->cm[0].curve[1].y = 1.0f;
3801
3802 BKE_curvemapping_init(cumap);
3803
3804 part->clumpcurve = cumap;
3805 }
3806
BKE_particlesettings_rough_curve_init(ParticleSettings * part)3807 void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
3808 {
3809 CurveMapping *cumap = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
3810
3811 cumap->cm[0].curve[0].x = 0.0f;
3812 cumap->cm[0].curve[0].y = 1.0f;
3813 cumap->cm[0].curve[1].x = 1.0f;
3814 cumap->cm[0].curve[1].y = 1.0f;
3815
3816 BKE_curvemapping_init(cumap);
3817
3818 part->roughcurve = cumap;
3819 }
3820
BKE_particlesettings_twist_curve_init(ParticleSettings * part)3821 void BKE_particlesettings_twist_curve_init(ParticleSettings *part)
3822 {
3823 CurveMapping *cumap = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
3824
3825 cumap->cm[0].curve[0].x = 0.0f;
3826 cumap->cm[0].curve[0].y = 1.0f;
3827 cumap->cm[0].curve[1].x = 1.0f;
3828 cumap->cm[0].curve[1].y = 1.0f;
3829
3830 BKE_curvemapping_init(cumap);
3831
3832 part->twistcurve = cumap;
3833 }
3834
3835 /************************************************/
3836 /* Textures */
3837 /************************************************/
3838
get_particle_uv(Mesh * mesh,ParticleData * pa,int index,const float fuv[4],char * name,float * texco,bool from_vert)3839 static int get_particle_uv(Mesh *mesh,
3840 ParticleData *pa,
3841 int index,
3842 const float fuv[4],
3843 char *name,
3844 float *texco,
3845 bool from_vert)
3846 {
3847 MFace *mf;
3848 MTFace *tf;
3849 int i;
3850
3851 tf = CustomData_get_layer_named(&mesh->fdata, CD_MTFACE, name);
3852
3853 if (tf == NULL) {
3854 tf = mesh->mtface;
3855 }
3856
3857 if (tf == NULL) {
3858 return 0;
3859 }
3860
3861 if (pa) {
3862 i = ELEM(pa->num_dmcache, DMCACHE_NOTFOUND, DMCACHE_ISCHILD) ? pa->num : pa->num_dmcache;
3863 if ((!from_vert && i >= mesh->totface) || (from_vert && i >= mesh->totvert)) {
3864 i = -1;
3865 }
3866 }
3867 else {
3868 i = index;
3869 }
3870
3871 if (i == -1) {
3872 texco[0] = 0.0f;
3873 texco[1] = 0.0f;
3874 texco[2] = 0.0f;
3875 }
3876 else {
3877 if (from_vert) {
3878 mf = mesh->mface;
3879
3880 /* This finds the first face to contain the emitting vertex,
3881 * this is not ideal, but is mostly fine as UV seams generally
3882 * map to equal-colored parts of a texture */
3883 for (int j = 0; j < mesh->totface; j++, mf++) {
3884 if (ELEM(i, mf->v1, mf->v2, mf->v3, mf->v4)) {
3885 i = j;
3886 break;
3887 }
3888 }
3889 }
3890 else {
3891 mf = &mesh->mface[i];
3892 }
3893
3894 psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
3895
3896 texco[0] = texco[0] * 2.0f - 1.0f;
3897 texco[1] = texco[1] * 2.0f - 1.0f;
3898 texco[2] = 0.0f;
3899 }
3900
3901 return 1;
3902 }
3903
3904 #define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \
3905 if ((event & mtex->mapto) & type) { \
3906 pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \
3907 } \
3908 (void)0
3909
3910 #define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \
3911 if (event & type) { \
3912 CLAMP(pvalue, 0.0f, 1.0f); \
3913 } \
3914 (void)0
3915
3916 #define CLAMP_WARP_PARTICLE_TEXTURE_POS(type, pvalue) \
3917 if (event & type) { \
3918 if (pvalue < 0.0f) { \
3919 pvalue = 1.0f + pvalue; \
3920 } \
3921 CLAMP(pvalue, 0.0f, 1.0f); \
3922 } \
3923 (void)0
3924
3925 #define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \
3926 if (event & type) { \
3927 CLAMP(pvalue, -1.0f, 1.0f); \
3928 } \
3929 (void)0
3930
get_cpa_texture(Mesh * mesh,ParticleSystem * psys,ParticleSettings * part,ParticleData * par,int child_index,int face_index,const float fw[4],float * orco,ParticleTexture * ptex,int event,float cfra)3931 static void get_cpa_texture(Mesh *mesh,
3932 ParticleSystem *psys,
3933 ParticleSettings *part,
3934 ParticleData *par,
3935 int child_index,
3936 int face_index,
3937 const float fw[4],
3938 float *orco,
3939 ParticleTexture *ptex,
3940 int event,
3941 float cfra)
3942 {
3943 MTex *mtex, **mtexp = part->mtex;
3944 int m;
3945 float value, rgba[4], texvec[3];
3946
3947 ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = ptex->gravity = ptex->field =
3948 ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp = ptex->effector = ptex->rough1 =
3949 ptex->rough2 = ptex->roughe = 1.0f;
3950 ptex->twist = 1.0f;
3951
3952 ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26);
3953 ptex->length *= part->clength_thres < psys_frand(psys, child_index + 27) ? part->clength : 1.0f;
3954
3955 for (m = 0; m < MAX_MTEX; m++, mtexp++) {
3956 mtex = *mtexp;
3957 if (mtex && mtex->tex && mtex->mapto) {
3958 float def = mtex->def_var;
3959 short blend = mtex->blendtype;
3960 short texco = mtex->texco;
3961
3962 if (ELEM(texco, TEXCO_UV, TEXCO_ORCO) &&
3963 (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 ||
3964 part->distr == PART_DISTR_GRID)) {
3965 texco = TEXCO_GLOB;
3966 }
3967
3968 switch (texco) {
3969 case TEXCO_GLOB:
3970 copy_v3_v3(texvec, par->state.co);
3971 break;
3972 case TEXCO_OBJECT:
3973 copy_v3_v3(texvec, par->state.co);
3974 if (mtex->object) {
3975 mul_m4_v3(mtex->object->imat, texvec);
3976 }
3977 break;
3978 case TEXCO_UV:
3979 if (fw && get_particle_uv(mesh,
3980 NULL,
3981 face_index,
3982 fw,
3983 mtex->uvname,
3984 texvec,
3985 (part->from == PART_FROM_VERT))) {
3986 break;
3987 }
3988 /* no break, failed to get uv's, so let's try orco's */
3989 ATTR_FALLTHROUGH;
3990 case TEXCO_ORCO:
3991 copy_v3_v3(texvec, orco);
3992 break;
3993 case TEXCO_PARTICLE:
3994 /* texture coordinates in range [-1, 1] */
3995 texvec[0] = 2.f * (cfra - par->time) / (par->dietime - par->time) - 1.f;
3996 texvec[1] = 0.f;
3997 texvec[2] = 0.f;
3998 break;
3999 }
4000
4001 RE_texture_evaluate(mtex, texvec, 0, NULL, false, false, &value, rgba);
4002
4003 if ((event & mtex->mapto) & PAMAP_ROUGH) {
4004 ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(
4005 def, ptex->rough1, value, mtex->roughfac, blend);
4006 }
4007
4008 SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
4009 SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac);
4010 SET_PARTICLE_TEXTURE(PAMAP_KINK_AMP, ptex->kink_amp, mtex->kinkampfac);
4011 SET_PARTICLE_TEXTURE(PAMAP_KINK_FREQ, ptex->kink_freq, mtex->kinkfac);
4012 SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
4013 SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac);
4014 }
4015 }
4016
4017 CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
4018 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump);
4019 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_KINK_AMP, ptex->kink_amp);
4020 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_KINK_FREQ, ptex->kink_freq);
4021 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1);
4022 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
4023 }
psys_get_texture(ParticleSimulationData * sim,ParticleData * pa,ParticleTexture * ptex,int event,float cfra)4024 void psys_get_texture(
4025 ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra)
4026 {
4027 Object *ob = sim->ob;
4028 Mesh *me = (Mesh *)ob->data;
4029 ParticleSettings *part = sim->psys->part;
4030 MTex **mtexp = part->mtex;
4031 MTex *mtex;
4032 int m;
4033 float value, rgba[4], co[3], texvec[3];
4034 int setvars = 0;
4035
4036 /* initialize ptex */
4037 ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = ptex->gravity = ptex->field =
4038 ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp = ptex->effector =
4039 ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
4040 ptex->twist = 1.0f;
4041
4042 ptex->time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
4043
4044 for (m = 0; m < MAX_MTEX; m++, mtexp++) {
4045 mtex = *mtexp;
4046 if (mtex && mtex->tex && mtex->mapto) {
4047 float def = mtex->def_var;
4048 short blend = mtex->blendtype;
4049 short texco = mtex->texco;
4050
4051 if (texco == TEXCO_UV && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 ||
4052 part->distr == PART_DISTR_GRID)) {
4053 texco = TEXCO_GLOB;
4054 }
4055
4056 switch (texco) {
4057 case TEXCO_GLOB:
4058 copy_v3_v3(texvec, pa->state.co);
4059 break;
4060 case TEXCO_OBJECT:
4061 copy_v3_v3(texvec, pa->state.co);
4062 if (mtex->object) {
4063 mul_m4_v3(mtex->object->imat, texvec);
4064 }
4065 break;
4066 case TEXCO_UV:
4067 if (get_particle_uv(sim->psmd->mesh_final,
4068 pa,
4069 0,
4070 pa->fuv,
4071 mtex->uvname,
4072 texvec,
4073 (part->from == PART_FROM_VERT))) {
4074 break;
4075 }
4076 /* no break, failed to get uv's, so let's try orco's */
4077 ATTR_FALLTHROUGH;
4078 case TEXCO_ORCO:
4079 psys_particle_on_emitter(sim->psmd,
4080 sim->psys->part->from,
4081 pa->num,
4082 pa->num_dmcache,
4083 pa->fuv,
4084 pa->foffset,
4085 co,
4086 0,
4087 0,
4088 0,
4089 texvec);
4090
4091 BKE_mesh_texspace_ensure(me);
4092 sub_v3_v3(texvec, me->loc);
4093 if (me->size[0] != 0.0f) {
4094 texvec[0] /= me->size[0];
4095 }
4096 if (me->size[1] != 0.0f) {
4097 texvec[1] /= me->size[1];
4098 }
4099 if (me->size[2] != 0.0f) {
4100 texvec[2] /= me->size[2];
4101 }
4102 break;
4103 case TEXCO_PARTICLE:
4104 /* texture coordinates in range [-1, 1] */
4105 texvec[0] = 2.f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.f;
4106 if (sim->psys->totpart > 0) {
4107 texvec[1] = 2.f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - 1.f;
4108 }
4109 else {
4110 texvec[1] = 0.0f;
4111 }
4112 texvec[2] = 0.f;
4113 break;
4114 }
4115
4116 RE_texture_evaluate(mtex, texvec, 0, NULL, false, false, &value, rgba);
4117
4118 if ((event & mtex->mapto) & PAMAP_TIME) {
4119 /* the first time has to set the base value for time regardless of blend mode */
4120 if ((setvars & MAP_PA_TIME) == 0) {
4121 int flip = (mtex->timefac < 0.0f);
4122 float timefac = fabsf(mtex->timefac);
4123 ptex->time *= 1.0f - timefac;
4124 ptex->time += timefac * ((flip) ? 1.0f - value : value);
4125 setvars |= MAP_PA_TIME;
4126 }
4127 else {
4128 ptex->time = texture_value_blend(def, ptex->time, value, mtex->timefac, blend);
4129 }
4130 }
4131 SET_PARTICLE_TEXTURE(PAMAP_LIFE, ptex->life, mtex->lifefac);
4132 SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
4133 SET_PARTICLE_TEXTURE(PAMAP_SIZE, ptex->size, mtex->sizefac);
4134 SET_PARTICLE_TEXTURE(PAMAP_IVEL, ptex->ivel, mtex->ivelfac);
4135 SET_PARTICLE_TEXTURE(PAMAP_FIELD, ptex->field, mtex->fieldfac);
4136 SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac);
4137 SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac);
4138 SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
4139 SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac);
4140 }
4141 }
4142
4143 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_TIME, ptex->time);
4144 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_LIFE, ptex->life);
4145 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
4146 CLAMP_PARTICLE_TEXTURE_POS(PAMAP_SIZE, ptex->size);
4147 CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_IVEL, ptex->ivel);
4148 CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_FIELD, ptex->field);
4149 CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_GRAVITY, ptex->gravity);
4150 CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp);
4151 CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
4152 }
4153 /************************************************/
4154 /* Particle State */
4155 /************************************************/
psys_get_timestep(ParticleSimulationData * sim)4156 float psys_get_timestep(ParticleSimulationData *sim)
4157 {
4158 return 0.04f * sim->psys->part->timetweak;
4159 }
psys_get_child_time(ParticleSystem * psys,ChildParticle * cpa,float cfra,float * birthtime,float * dietime)4160 float psys_get_child_time(
4161 ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
4162 {
4163 ParticleSettings *part = psys->part;
4164 float time, life;
4165
4166 if (part->childtype == PART_CHILD_FACES) {
4167 int w = 0;
4168 time = 0.0;
4169 while (w < 4 && cpa->pa[w] >= 0) {
4170 time += cpa->w[w] * (psys->particles + cpa->pa[w])->time;
4171 w++;
4172 }
4173
4174 life = part->lifetime * (1.0f - part->randlife * psys_frand(psys, cpa - psys->child + 25));
4175 }
4176 else {
4177 ParticleData *pa = psys->particles + cpa->parent;
4178
4179 time = pa->time;
4180 life = pa->lifetime;
4181 }
4182
4183 if (birthtime) {
4184 *birthtime = time;
4185 }
4186 if (dietime) {
4187 *dietime = time + life;
4188 }
4189
4190 return (cfra - time) / life;
4191 }
psys_get_child_size(ParticleSystem * psys,ChildParticle * cpa,float UNUSED (cfra),float * UNUSED (pa_time))4192 float psys_get_child_size(ParticleSystem *psys,
4193 ChildParticle *cpa,
4194 float UNUSED(cfra),
4195 float *UNUSED(pa_time))
4196 {
4197 ParticleSettings *part = psys->part;
4198 float size; /* time XXX */
4199
4200 if (part->childtype == PART_CHILD_FACES) {
4201 int w = 0;
4202 size = 0.0;
4203 while (w < 4 && cpa->pa[w] >= 0) {
4204 size += cpa->w[w] * (psys->particles + cpa->pa[w])->size;
4205 w++;
4206 }
4207 }
4208 else {
4209 size = psys->particles[cpa->parent].size;
4210 }
4211
4212 size *= part->childsize;
4213
4214 if (part->childrandsize != 0.0f) {
4215 size *= 1.0f - part->childrandsize * psys_frand(psys, cpa - psys->child + 26);
4216 }
4217
4218 return size;
4219 }
get_child_modifier_parameters(ParticleSettings * part,ParticleThreadContext * ctx,ChildParticle * cpa,short cpa_from,int cpa_num,float * cpa_fuv,float * orco,ParticleTexture * ptex)4220 static void get_child_modifier_parameters(ParticleSettings *part,
4221 ParticleThreadContext *ctx,
4222 ChildParticle *cpa,
4223 short cpa_from,
4224 int cpa_num,
4225 float *cpa_fuv,
4226 float *orco,
4227 ParticleTexture *ptex)
4228 {
4229 ParticleSystem *psys = ctx->sim.psys;
4230 int i = cpa - psys->child;
4231
4232 get_cpa_texture(ctx->mesh,
4233 psys,
4234 part,
4235 psys->particles + cpa->pa[0],
4236 i,
4237 cpa_num,
4238 cpa_fuv,
4239 orco,
4240 ptex,
4241 PAMAP_DENS | PAMAP_CHILD,
4242 psys->cfra);
4243
4244 if (ptex->exist < psys_frand(psys, i + 24)) {
4245 return;
4246 }
4247
4248 if (ctx->vg_length) {
4249 ptex->length *= psys_interpolate_value_from_verts(
4250 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_length);
4251 }
4252 if (ctx->vg_clump) {
4253 ptex->clump *= psys_interpolate_value_from_verts(
4254 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_clump);
4255 }
4256 if (ctx->vg_kink) {
4257 ptex->kink_freq *= psys_interpolate_value_from_verts(
4258 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_kink);
4259 }
4260 if (ctx->vg_rough1) {
4261 ptex->rough1 *= psys_interpolate_value_from_verts(
4262 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough1);
4263 }
4264 if (ctx->vg_rough2) {
4265 ptex->rough2 *= psys_interpolate_value_from_verts(
4266 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough2);
4267 }
4268 if (ctx->vg_roughe) {
4269 ptex->roughe *= psys_interpolate_value_from_verts(
4270 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_roughe);
4271 }
4272 if (ctx->vg_effector) {
4273 ptex->effector *= psys_interpolate_value_from_verts(
4274 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector);
4275 }
4276 if (ctx->vg_twist) {
4277 ptex->twist *= psys_interpolate_value_from_verts(
4278 ctx->mesh, cpa_from, cpa_num, cpa_fuv, ctx->vg_twist);
4279 }
4280 }
4281 /* gets hair (or keyed) particles state at the "path time" specified in state->time */
psys_get_particle_on_path(ParticleSimulationData * sim,int p,ParticleKey * state,const bool vel)4282 void psys_get_particle_on_path(ParticleSimulationData *sim,
4283 int p,
4284 ParticleKey *state,
4285 const bool vel)
4286 {
4287 PARTICLE_PSMD;
4288 ParticleSystem *psys = sim->psys;
4289 ParticleSettings *part = sim->psys->part;
4290 Material *ma = BKE_object_material_get(sim->ob, part->omat);
4291 ParticleData *pa;
4292 ChildParticle *cpa;
4293 ParticleTexture ptex;
4294 ParticleKey *par = 0, keys[4], tstate;
4295 ParticleThreadContext ctx; /* fake thread context for child modifiers */
4296 ParticleInterpolationData pind;
4297
4298 float t;
4299 float co[3], orco[3];
4300 float hairmat[4][4];
4301 int totpart = psys->totpart;
4302 int totchild = psys->totchild;
4303 short between = 0, edit = 0;
4304
4305 int keyed = part->phystype & PART_PHYS_KEYED && psys->flag & PSYS_KEYED;
4306 int cached = !keyed && part->type != PART_HAIR;
4307
4308 float *cpa_fuv;
4309 int cpa_num;
4310 short cpa_from;
4311
4312 /* initialize keys to zero */
4313 memset(keys, 0, sizeof(ParticleKey[4]));
4314
4315 t = state->time;
4316 CLAMP(t, 0.0f, 1.0f);
4317
4318 if (p < totpart) {
4319 /* interpolate pathcache directly if it exist */
4320 if (psys->pathcache) {
4321 ParticleCacheKey result;
4322 interpolate_pathcache(psys->pathcache[p], t, &result);
4323 copy_v3_v3(state->co, result.co);
4324 copy_v3_v3(state->vel, result.vel);
4325 copy_qt_qt(state->rot, result.rot);
4326 }
4327 /* otherwise interpolate with other means */
4328 else {
4329 pa = psys->particles + p;
4330
4331 pind.keyed = keyed;
4332 pind.cache = cached ? psys->pointcache : NULL;
4333 pind.epoint = NULL;
4334 pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
4335 /* pind.dm disabled in editmode means we don't get effectors taken into
4336 * account when subdividing for instance */
4337 pind.mesh = psys_in_edit_mode(sim->depsgraph, psys) ?
4338 NULL :
4339 psys->hair_out_mesh; /* XXX Sybren EEK */
4340 init_particle_interpolation(sim->ob, psys, pa, &pind);
4341 do_particle_interpolation(psys, p, pa, t, &pind, state);
4342
4343 if (pind.mesh) {
4344 mul_m4_v3(sim->ob->obmat, state->co);
4345 mul_mat3_m4_v3(sim->ob->obmat, state->vel);
4346 }
4347 else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
4348 if ((pa->flag & PARS_REKEY) == 0) {
4349 psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, part->from, pa, hairmat);
4350 mul_m4_v3(hairmat, state->co);
4351 mul_mat3_m4_v3(hairmat, state->vel);
4352
4353 if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) {
4354 do_guides(
4355 sim->depsgraph, sim->psys->part, sim->psys->effectors, state, p, state->time);
4356 /* TODO: proper velocity handling */
4357 }
4358
4359 if (psys->lattice_deform_data && edit == 0) {
4360 BKE_lattice_deform_data_eval_co(
4361 psys->lattice_deform_data, state->co, psys->lattice_strength);
4362 }
4363 }
4364 }
4365 }
4366 }
4367 else if (totchild) {
4368 // invert_m4_m4(imat, ob->obmat);
4369
4370 /* interpolate childcache directly if it exists */
4371 if (psys->childcache) {
4372 ParticleCacheKey result;
4373 interpolate_pathcache(psys->childcache[p - totpart], t, &result);
4374 copy_v3_v3(state->co, result.co);
4375 copy_v3_v3(state->vel, result.vel);
4376 copy_qt_qt(state->rot, result.rot);
4377 }
4378 else {
4379 float par_co[3], par_orco[3];
4380
4381 cpa = psys->child + p - totpart;
4382
4383 if (state->time < 0.0f) {
4384 t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
4385 }
4386
4387 if (part->childtype == PART_CHILD_FACES) {
4388 /* part->parents could still be 0 so we can't test with totparent */
4389 between = 1;
4390 }
4391 if (between) {
4392 int w = 0;
4393 float foffset;
4394
4395 /* get parent states */
4396 while (w < 4 && cpa->pa[w] >= 0) {
4397 keys[w].time = state->time;
4398 psys_get_particle_on_path(sim, cpa->pa[w], keys + w, 1);
4399 w++;
4400 }
4401
4402 /* get the original coordinates (orco) for texture usage */
4403 cpa_num = cpa->num;
4404
4405 foffset = cpa->foffset;
4406 cpa_fuv = cpa->fuv;
4407 cpa_from = PART_FROM_FACE;
4408
4409 psys_particle_on_emitter(
4410 psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco);
4411
4412 /* We need to save the actual root position of the child for
4413 * positioning it accurately to the surface of the emitter. */
4414 // copy_v3_v3(cpa_1st, co);
4415
4416 // mul_m4_v3(ob->obmat, cpa_1st);
4417
4418 pa = psys->particles + cpa->parent;
4419
4420 psys_particle_on_emitter(psmd,
4421 part->from,
4422 pa->num,
4423 pa->num_dmcache,
4424 pa->fuv,
4425 pa->foffset,
4426 par_co,
4427 0,
4428 0,
4429 0,
4430 par_orco);
4431 if (part->type == PART_HAIR) {
4432 psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
4433 }
4434 else {
4435 unit_m4(hairmat);
4436 }
4437
4438 pa = 0;
4439 }
4440 else {
4441 /* get the parent state */
4442 keys->time = state->time;
4443 psys_get_particle_on_path(sim, cpa->parent, keys, 1);
4444
4445 /* get the original coordinates (orco) for texture usage */
4446 pa = psys->particles + cpa->parent;
4447
4448 cpa_from = part->from;
4449 cpa_num = pa->num;
4450 cpa_fuv = pa->fuv;
4451
4452 psys_particle_on_emitter(psmd,
4453 part->from,
4454 pa->num,
4455 pa->num_dmcache,
4456 pa->fuv,
4457 pa->foffset,
4458 par_co,
4459 0,
4460 0,
4461 0,
4462 par_orco);
4463 if (part->type == PART_HAIR) {
4464 psys_particle_on_emitter(
4465 psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco);
4466 psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
4467 }
4468 else {
4469 copy_v3_v3(orco, cpa->fuv);
4470 unit_m4(hairmat);
4471 }
4472 }
4473
4474 /* get different child parameters from textures & vgroups */
4475 memset(&ctx, 0, sizeof(ParticleThreadContext));
4476 ctx.sim = *sim;
4477 ctx.mesh = psmd->mesh_final;
4478 ctx.ma = ma;
4479 /* TODO: assign vertex groups */
4480 get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
4481
4482 if (between) {
4483 int w = 0;
4484
4485 state->co[0] = state->co[1] = state->co[2] = 0.0f;
4486 state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
4487
4488 /* child position is the weighted sum of parent positions */
4489 while (w < 4 && cpa->pa[w] >= 0) {
4490 state->co[0] += cpa->w[w] * keys[w].co[0];
4491 state->co[1] += cpa->w[w] * keys[w].co[1];
4492 state->co[2] += cpa->w[w] * keys[w].co[2];
4493
4494 state->vel[0] += cpa->w[w] * keys[w].vel[0];
4495 state->vel[1] += cpa->w[w] * keys[w].vel[1];
4496 state->vel[2] += cpa->w[w] * keys[w].vel[2];
4497 w++;
4498 }
4499 /* apply offset for correct positioning */
4500 // add_v3_v3(state->co, cpa_1st);
4501 }
4502 else {
4503 /* offset the child from the parent position */
4504 offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
4505 }
4506
4507 par = keys;
4508
4509 if (vel) {
4510 copy_particle_key(&tstate, state, 1);
4511 }
4512
4513 /* apply different deformations to the child path */
4514 ParticleChildModifierContext modifier_ctx = {NULL};
4515 modifier_ctx.thread_ctx = NULL;
4516 modifier_ctx.sim = sim;
4517 modifier_ctx.ptex = &ptex;
4518 modifier_ctx.cpa = cpa;
4519 modifier_ctx.orco = orco;
4520 modifier_ctx.par_co = par->co;
4521 modifier_ctx.par_vel = par->vel;
4522 modifier_ctx.par_rot = par->rot;
4523 modifier_ctx.par_orco = par_orco;
4524 modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL;
4525 do_child_modifiers(&modifier_ctx, hairmat, state, t);
4526
4527 /* try to estimate correct velocity */
4528 if (vel) {
4529 ParticleKey tstate_tmp;
4530 float length = len_v3(state->vel);
4531
4532 if (t >= 0.001f) {
4533 tstate_tmp.time = t - 0.001f;
4534 psys_get_particle_on_path(sim, p, &tstate_tmp, 0);
4535 sub_v3_v3v3(state->vel, state->co, tstate_tmp.co);
4536 normalize_v3(state->vel);
4537 }
4538 else {
4539 tstate_tmp.time = t + 0.001f;
4540 psys_get_particle_on_path(sim, p, &tstate_tmp, 0);
4541 sub_v3_v3v3(state->vel, tstate_tmp.co, state->co);
4542 normalize_v3(state->vel);
4543 }
4544
4545 mul_v3_fl(state->vel, length);
4546 }
4547 }
4548 }
4549 }
4550 /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
psys_get_particle_state(ParticleSimulationData * sim,int p,ParticleKey * state,int always)4551 int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always)
4552 {
4553 ParticleSystem *psys = sim->psys;
4554 ParticleSettings *part = psys->part;
4555 ParticleData *pa = NULL;
4556 ChildParticle *cpa = NULL;
4557 float cfra;
4558 int totpart = psys->totpart;
4559 float timestep = psys_get_timestep(sim);
4560
4561 /* negative time means "use current time" */
4562 cfra = state->time > 0 ? state->time : DEG_get_ctime(sim->depsgraph);
4563
4564 if (p >= totpart) {
4565 if (!psys->totchild) {
4566 return 0;
4567 }
4568
4569 if (part->childtype == PART_CHILD_FACES) {
4570 if (!(psys->flag & PSYS_KEYED)) {
4571 return 0;
4572 }
4573
4574 cpa = psys->child + p - totpart;
4575
4576 state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL);
4577
4578 if (!always) {
4579 if ((state->time < 0.0f && !(part->flag & PART_UNBORN)) ||
4580 (state->time > 1.0f && !(part->flag & PART_DIED))) {
4581 return 0;
4582 }
4583 }
4584
4585 state->time = (cfra - (part->sta + (part->end - part->sta) * psys_frand(psys, p + 23))) /
4586 (part->lifetime * psys_frand(psys, p + 24));
4587
4588 psys_get_particle_on_path(sim, p, state, 1);
4589 return 1;
4590 }
4591
4592 cpa = sim->psys->child + p - totpart;
4593 pa = sim->psys->particles + cpa->parent;
4594 }
4595 else {
4596 pa = sim->psys->particles + p;
4597 }
4598
4599 if (pa) {
4600 if (!always) {
4601 if ((cfra < pa->time && (part->flag & PART_UNBORN) == 0) ||
4602 (cfra >= pa->dietime && (part->flag & PART_DIED) == 0)) {
4603 return 0;
4604 }
4605 }
4606
4607 cfra = MIN2(cfra, pa->dietime);
4608 }
4609
4610 if (sim->psys->flag & PSYS_KEYED) {
4611 state->time = -cfra;
4612 psys_get_particle_on_path(sim, p, state, 1);
4613 return 1;
4614 }
4615
4616 if (cpa) {
4617 float mat[4][4];
4618 ParticleKey *key1;
4619 float t = (cfra - pa->time) / pa->lifetime;
4620 const float par_orco[3] = {0.0f, 0.0f, 0.0f};
4621
4622 key1 = &pa->state;
4623 offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad);
4624
4625 CLAMP(t, 0.0f, 1.0f);
4626
4627 unit_m4(mat);
4628 ParticleChildModifierContext modifier_ctx = {NULL};
4629 modifier_ctx.thread_ctx = NULL;
4630 modifier_ctx.sim = sim;
4631 modifier_ctx.ptex = NULL;
4632 modifier_ctx.cpa = cpa;
4633 modifier_ctx.orco = cpa->fuv;
4634 modifier_ctx.par_co = key1->co;
4635 modifier_ctx.par_vel = key1->vel;
4636 modifier_ctx.par_rot = key1->rot;
4637 modifier_ctx.par_orco = par_orco;
4638 modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL;
4639
4640 do_child_modifiers(&modifier_ctx, mat, state, t);
4641
4642 if (psys->lattice_deform_data) {
4643 BKE_lattice_deform_data_eval_co(
4644 psys->lattice_deform_data, state->co, psys->lattice_strength);
4645 }
4646 }
4647 else {
4648 if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
4649 copy_particle_key(state, &pa->state, 1);
4650 }
4651 else if (pa->prev_state.time == cfra) {
4652 copy_particle_key(state, &pa->prev_state, 1);
4653 }
4654 else {
4655 float dfra, frs_sec = sim->scene->r.frs_sec;
4656 /* let's interpolate to try to be as accurate as possible */
4657 if (pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) {
4658 if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) {
4659 /* prev_state is wrong so let's not use it,
4660 * this can happen at frames 1, 0 or particle birth. */
4661 dfra = state->time - pa->state.time;
4662
4663 copy_particle_key(state, &pa->state, 1);
4664
4665 madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
4666 }
4667 else {
4668 ParticleKey keys[4];
4669 float keytime;
4670
4671 copy_particle_key(keys + 1, &pa->prev_state, 1);
4672 copy_particle_key(keys + 2, &pa->state, 1);
4673
4674 dfra = keys[2].time - keys[1].time;
4675
4676 keytime = (state->time - keys[1].time) / dfra;
4677
4678 /* convert velocity to timestep size */
4679 mul_v3_fl(keys[1].vel, dfra * timestep);
4680 mul_v3_fl(keys[2].vel, dfra * timestep);
4681
4682 psys_interpolate_particle(-1, keys, keytime, state, 1);
4683
4684 /* convert back to real velocity */
4685 mul_v3_fl(state->vel, 1.f / (dfra * timestep));
4686
4687 interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime);
4688 interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime);
4689 }
4690 }
4691 else if (pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) {
4692 /* linear interpolation using only pa->state */
4693
4694 dfra = state->time - pa->state.time;
4695
4696 copy_particle_key(state, &pa->state, 1);
4697
4698 madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
4699 }
4700 else {
4701 /* Extrapolating over big ranges is not accurate
4702 * so let's just give something close to reasonable back. */
4703 copy_particle_key(state, &pa->state, 0);
4704 }
4705 }
4706
4707 if (sim->psys->lattice_deform_data) {
4708 BKE_lattice_deform_data_eval_co(
4709 sim->psys->lattice_deform_data, state->co, psys->lattice_strength);
4710 }
4711 }
4712
4713 return 1;
4714 }
4715
psys_get_dupli_texture(ParticleSystem * psys,ParticleSettings * part,ParticleSystemModifierData * psmd,ParticleData * pa,ChildParticle * cpa,float uv[2],float orco[3])4716 void psys_get_dupli_texture(ParticleSystem *psys,
4717 ParticleSettings *part,
4718 ParticleSystemModifierData *psmd,
4719 ParticleData *pa,
4720 ChildParticle *cpa,
4721 float uv[2],
4722 float orco[3])
4723 {
4724 MFace *mface;
4725 float loc[3];
4726 int num;
4727
4728 /* XXX: on checking '(psmd->dm != NULL)'
4729 * This is incorrect but needed for meta-ball evaluation.
4730 * Ideally this would be calculated via the depsgraph, however with meta-balls,
4731 * the entire scenes dupli's are scanned, which also looks into uncalculated data.
4732 *
4733 * For now just include this workaround as an alternative to crashing,
4734 * but longer term meta-balls should behave in a more manageable way, see: T46622. */
4735
4736 uv[0] = uv[1] = 0.0f;
4737
4738 /* Grid distribution doesn't support UV or emit from vertex mode */
4739 bool is_grid = (part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT);
4740
4741 if (cpa) {
4742 if ((part->childtype == PART_CHILD_FACES) && (psmd->mesh_final != NULL)) {
4743 if (!is_grid) {
4744 CustomData *mtf_data = &psmd->mesh_final->fdata;
4745 const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
4746
4747 if (uv_idx >= 0) {
4748 MTFace *mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
4749 if (mtface != NULL) {
4750 mface = CustomData_get(&psmd->mesh_final->fdata, cpa->num, CD_MFACE);
4751 mtface += cpa->num;
4752 psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
4753 }
4754 }
4755 }
4756
4757 psys_particle_on_emitter(psmd,
4758 PART_FROM_FACE,
4759 cpa->num,
4760 DMCACHE_ISCHILD,
4761 cpa->fuv,
4762 cpa->foffset,
4763 loc,
4764 0,
4765 0,
4766 0,
4767 orco);
4768 return;
4769 }
4770
4771 pa = psys->particles + cpa->pa[0];
4772 }
4773
4774 if ((part->from == PART_FROM_FACE) && (psmd->mesh_final != NULL) && !is_grid) {
4775 num = pa->num_dmcache;
4776
4777 if (num == DMCACHE_NOTFOUND) {
4778 num = pa->num;
4779 }
4780
4781 if (num >= psmd->mesh_final->totface) {
4782 /* happens when simplify is enabled
4783 * gives invalid coords but would crash otherwise */
4784 num = DMCACHE_NOTFOUND;
4785 }
4786
4787 if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
4788 CustomData *mtf_data = &psmd->mesh_final->fdata;
4789 const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
4790
4791 if (uv_idx >= 0) {
4792 MTFace *mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
4793 mface = CustomData_get(&psmd->mesh_final->fdata, num, CD_MFACE);
4794 mtface += num;
4795 psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
4796 }
4797 }
4798 }
4799
4800 psys_particle_on_emitter(
4801 psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, 0, 0, 0, orco);
4802 }
4803
psys_get_dupli_path_transform(ParticleSimulationData * sim,ParticleData * pa,ChildParticle * cpa,ParticleCacheKey * cache,float mat[4][4],float * scale)4804 void psys_get_dupli_path_transform(ParticleSimulationData *sim,
4805 ParticleData *pa,
4806 ChildParticle *cpa,
4807 ParticleCacheKey *cache,
4808 float mat[4][4],
4809 float *scale)
4810 {
4811 Object *ob = sim->ob;
4812 ParticleSystem *psys = sim->psys;
4813 ParticleSystemModifierData *psmd = sim->psmd;
4814 float loc[3], nor[3], vec[3], side[3], len;
4815 float xvec[3] = {-1.0, 0.0, 0.0}, nmat[3][3];
4816
4817 sub_v3_v3v3(vec, (cache + cache->segments)->co, cache->co);
4818 len = normalize_v3(vec);
4819
4820 if (pa == NULL && psys->part->childflat != PART_CHILD_FACES) {
4821 pa = psys->particles + cpa->pa[0];
4822 }
4823
4824 if (pa) {
4825 psys_particle_on_emitter(psmd,
4826 sim->psys->part->from,
4827 pa->num,
4828 pa->num_dmcache,
4829 pa->fuv,
4830 pa->foffset,
4831 loc,
4832 nor,
4833 0,
4834 0,
4835 0);
4836 }
4837 else {
4838 psys_particle_on_emitter(psmd,
4839 PART_FROM_FACE,
4840 cpa->num,
4841 DMCACHE_ISCHILD,
4842 cpa->fuv,
4843 cpa->foffset,
4844 loc,
4845 nor,
4846 0,
4847 0,
4848 0);
4849 }
4850
4851 if (psys->part->rotmode == PART_ROT_VEL) {
4852 transpose_m3_m4(nmat, ob->imat);
4853 mul_m3_v3(nmat, nor);
4854 normalize_v3(nor);
4855
4856 /* make sure that we get a proper side vector */
4857 if (fabsf(dot_v3v3(nor, vec)) > 0.999999f) {
4858 if (fabsf(dot_v3v3(nor, xvec)) > 0.999999f) {
4859 nor[0] = 0.0f;
4860 nor[1] = 1.0f;
4861 nor[2] = 0.0f;
4862 }
4863 else {
4864 nor[0] = 1.0f;
4865 nor[1] = 0.0f;
4866 nor[2] = 0.0f;
4867 }
4868 }
4869 cross_v3_v3v3(side, nor, vec);
4870 normalize_v3(side);
4871
4872 /* rotate side vector around vec */
4873 if (psys->part->phasefac != 0) {
4874 float q_phase[4];
4875 float phasefac = psys->part->phasefac;
4876 if (psys->part->randphasefac != 0.0f) {
4877 phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20);
4878 }
4879 axis_angle_to_quat(q_phase, vec, phasefac * (float)M_PI);
4880
4881 mul_qt_v3(q_phase, side);
4882 }
4883
4884 cross_v3_v3v3(nor, vec, side);
4885
4886 unit_m4(mat);
4887 copy_v3_v3(mat[0], vec);
4888 copy_v3_v3(mat[1], side);
4889 copy_v3_v3(mat[2], nor);
4890 }
4891 else {
4892 quat_to_mat4(mat, pa->state.rot);
4893 }
4894
4895 *scale = len;
4896 }
4897
psys_apply_hair_lattice(Depsgraph * depsgraph,Scene * scene,Object * ob,ParticleSystem * psys)4898 void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys)
4899 {
4900 ParticleSimulationData sim = {0};
4901 sim.depsgraph = depsgraph;
4902 sim.scene = scene;
4903 sim.ob = ob;
4904 sim.psys = psys;
4905 sim.psmd = psys_get_modifier(ob, psys);
4906
4907 psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
4908
4909 if (psys->lattice_deform_data) {
4910 ParticleData *pa = psys->particles;
4911 HairKey *hkey;
4912 int p, h;
4913 float hairmat[4][4], imat[4][4];
4914
4915 for (p = 0; p < psys->totpart; p++, pa++) {
4916 psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, psys->part->from, pa, hairmat);
4917 invert_m4_m4(imat, hairmat);
4918
4919 hkey = pa->hair;
4920 for (h = 0; h < pa->totkey; h++, hkey++) {
4921 mul_m4_v3(hairmat, hkey->co);
4922 BKE_lattice_deform_data_eval_co(
4923 psys->lattice_deform_data, hkey->co, psys->lattice_strength);
4924 mul_m4_v3(imat, hkey->co);
4925 }
4926 }
4927
4928 BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
4929 psys->lattice_deform_data = NULL;
4930
4931 /* protect the applied shape */
4932 psys->flag |= PSYS_EDITED;
4933 }
4934 }
4935
4936 /* Draw Engine */
4937 void (*BKE_particle_batch_cache_dirty_tag_cb)(ParticleSystem *psys, int mode) = NULL;
4938 void (*BKE_particle_batch_cache_free_cb)(ParticleSystem *psys) = NULL;
4939
BKE_particle_batch_cache_dirty_tag(ParticleSystem * psys,int mode)4940 void BKE_particle_batch_cache_dirty_tag(ParticleSystem *psys, int mode)
4941 {
4942 if (psys->batch_cache) {
4943 BKE_particle_batch_cache_dirty_tag_cb(psys, mode);
4944 }
4945 }
BKE_particle_batch_cache_free(ParticleSystem * psys)4946 void BKE_particle_batch_cache_free(ParticleSystem *psys)
4947 {
4948 if (psys->batch_cache) {
4949 BKE_particle_batch_cache_free_cb(psys);
4950 }
4951 }
4952