Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BKE_particle.h « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 1dac4e540d96b342814490e66a325868c43f4995 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2007 Janne Karhu. All rights reserved.
 *           2011-2012 AutoCRC (adaptive time step, Classical SPH). */

#pragma once

/** \file
 * \ingroup bke
 */

#include "BLI_buffer.h"
#include "BLI_utildefines.h"

#include "DNA_particle_types.h"

#ifdef __cplusplus
extern "C" {
#endif

struct ParticleKey;
struct ParticleSettings;
struct ParticleSystem;
struct ParticleSystemModifierData;

struct BVHTreeRay;
struct BVHTreeRayHit;
struct BlendDataReader;
struct BlendLibReader;
struct BlendWriter;
struct CustomData_MeshMasks;
struct Depsgraph;
struct EdgeHash;
struct KDTree_3d;
struct LatticeDeformData;
struct LinkNode;
struct MCol;
struct MFace;
struct MTFace;
struct Main;
struct ModifierData;
struct Object;
struct RNG;
struct Scene;

#define PARTICLE_COLLISION_MAX_COLLISIONS 10

#define PARTICLE_P \
  ParticleData *pa; \
  int p
#define LOOP_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++)
#define LOOP_EXISTING_PARTICLES \
  for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) \
    if (!(pa->flag & PARS_UNEXIST))
#define LOOP_SHOWN_PARTICLES \
  for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) \
    if (!(pa->flag & (PARS_UNEXIST | PARS_NO_DISP)))
/* OpenMP: Can only advance one variable within loop definition. */
#define LOOP_DYNAMIC_PARTICLES \
  for (p = 0; p < psys->totpart; p++) \
    if ((pa = psys->particles + p)->state.time > 0.0f)

/* Fast but sure way to get the modifier. */
#define PARTICLE_PSMD \
  ParticleSystemModifierData *psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys)

/* common stuff that many particle functions need */
typedef struct ParticleSimulationData {
  struct Depsgraph *depsgraph;
  struct Scene *scene;
  struct Object *ob;
  struct ParticleSystem *psys;
  struct ParticleSystemModifierData *psmd;
  struct ListBase *colliders;
  /* Courant number. This is used to implement an adaptive time step. Only the
   * maximum value per time step is important. Only sph_integrate makes use of
   * this at the moment. Other solvers could, too. */
  float courant_num;
  /* Only valid during dynamics_step(). */
  struct RNG *rng;
} ParticleSimulationData;

typedef struct SPHData {
  ParticleSystem *psys[10];
  ParticleData *pa;
  float mass;
  struct EdgeHash *eh;
  float *gravity;
  float hfac;
  /* Average distance to neighbors (other particles in the support domain),
   * for calculating the Courant number (adaptive time step). */
  int pass;
  float element_size;
  float flow[3];

  /* Temporary thread-local buffer for springs created during this step. */
  BLI_Buffer new_springs;

  /* Integrator callbacks. This allows different SPH implementations. */
  void (*force_cb)(void *sphdata_v, ParticleKey *state, float *force, float *impulse);
  void (*density_cb)(void *rangedata_v, int index, const float co[3], float squared_dist);
} SPHData;

typedef struct ParticleTexture {
  float ivel;                                         /* used in reset */
  float time, life, exist, size;                      /* used in init */
  float damp, gravity, field;                         /* used in physics */
  float length, clump, kink_freq, kink_amp, effector; /* used in path caching */
  float rough1, rough2, roughe;                       /* used in path caching */
  float twist;                                        /* used in path caching */
} ParticleTexture;

typedef struct ParticleSeam {
  float v0[3], v1[3];
  float nor[3], dir[3], tan[3];
  float length2;
} ParticleSeam;

typedef struct ParticleCacheKey {
  float co[3];
  float vel[3];
  float rot[4];
  float col[3];
  float time;
  int segments;
} ParticleCacheKey;

typedef struct ParticleThreadContext {
  /* shared */
  struct ParticleSimulationData sim;
  struct Mesh *mesh;
  struct Material *ma;

  /* distribution */
  struct KDTree_3d *tree;

  struct ParticleSeam *seams;
  int totseam;

  float *jit, *jitoff, *weight;
  float maxweight;
  int *index, jitlevel;

  int cfrom, distr;

  struct ParticleData *tpars;

  /* path caching */
  bool editupdate;
  int between, segments, extra_segments;
  int totchild, totparent, parent_pass;

  float cfra;

  float *vg_length, *vg_clump, *vg_kink;
  float *vg_rough1, *vg_rough2, *vg_roughe;
  float *vg_effector;
  float *vg_twist;

  struct CurveMapping *clumpcurve;
  struct CurveMapping *roughcurve;
  struct CurveMapping *twistcurve;
} ParticleThreadContext;

typedef struct ParticleTask {
  ParticleThreadContext *ctx;
  struct RNG *rng, *rng_path;
  int begin, end;
} ParticleTask;

typedef struct ParticleCollisionElement {
  /* pointers to original data */
  float *x[3], *v[3];

  /* Values interpolated from original data. */
  float x0[3], x1[3], x2[3], p[3];

  /* results for found intersection point */
  float nor[3], vel[3], uv[2];

  /* count of original data (1-4) */
  int tot;

  /* index of the collision face */
  int index;

  /* flags for inversed normal / particle already inside element at start */
  short inv_nor, inside;
} ParticleCollisionElement;

/** Container for moving data between deflet_particle and particle_intersect_face. */
typedef struct ParticleCollision {
  struct Object *current;
  struct Object *hit;
  struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS + 1];
  struct Object *emitter;

  /** Collision modifier for current object. */
  struct CollisionModifierData *md;

  /** Time factor of previous collision, needed for subtracting face velocity. */
  float f;
  float fac1, fac2;

  float cfra, old_cfra;

  /** Original length of co2-co1, needed for collision time evaluation. */
  float original_ray_length;

  int skip_count;

  ParticleCollisionElement pce;

  /* total_time is the amount of time in this subframe
   * inv_total_time is the opposite
   * inv_timestep is the inverse of the amount of time in this frame */
  float total_time, inv_total_time, inv_timestep;

  float radius;
  float co1[3], co2[3];
  float ve1[3], ve2[3];

  float acc[3], boid_z;

  int boid;
} ParticleCollision;

typedef struct ParticleDrawData {
  float *vdata, *vd;   /* vertex data */
  float *ndata, *nd;   /* normal data */
  float *cdata, *cd;   /* color data */
  float *vedata, *ved; /* velocity data */
  float *ma_col;
  int totpart, partsize;
  int flag;
  int totpoint, totve;
} ParticleDrawData;

#define PARTICLE_DRAW_DATA_UPDATED 1

#define PSYS_FRAND_COUNT 1024
extern unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
extern unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
extern float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];

void BKE_particle_init_rng(void);

BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
{
  /* XXX far from ideal, this simply scrambles particle random numbers a bit
   * to avoid obvious correlations.
   * Can't use previous psys->frand arrays because these require initialization
   * inside psys_check_enabled, which wreaks havoc in multi-threaded depsgraph updates.
   */
  unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT];
  unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT];
  return PSYS_FRAND_BASE[(offset + seed * multiplier) % PSYS_FRAND_COUNT];
}

BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float vec[3])
{
  unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT];
  unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT];
  vec[0] = PSYS_FRAND_BASE[(offset + (seed + 0) * multiplier) % PSYS_FRAND_COUNT];
  vec[1] = PSYS_FRAND_BASE[(offset + (seed + 1) * multiplier) % PSYS_FRAND_COUNT];
  vec[2] = PSYS_FRAND_BASE[(offset + (seed + 2) * multiplier) % PSYS_FRAND_COUNT];
}

/* ----------- functions needed outside particlesystem ---------------- */
/* particle.c */

/* Few helpers for count-all etc. */

int count_particles(struct ParticleSystem *psys);
int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur);

int psys_get_child_number(struct Scene *scene,
                          struct ParticleSystem *psys,
                          bool use_render_params);
int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys, bool use_render_params);

/**
 * Get object's active particle system safely.
 */
struct ParticleSystem *psys_get_current(struct Object *ob);

/* For RNA API. */

short psys_get_current_num(struct Object *ob);
void psys_set_current_num(struct Object *ob, int index);
/* UNUSED */
// struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);

struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);

/**
 * For a given evaluated particle system get its original.
 *
 * If this input is an original particle system already, the return value is the same as the input.
 */
struct ParticleSystem *psys_orig_get(struct ParticleSystem *psys);

/**
 * For a given original object and its particle system,
 * get evaluated particle system within a given dependency graph.
 */
struct ParticleSystem *psys_eval_get(struct Depsgraph *depsgraph,
                                     struct Object *object,
                                     struct ParticleSystem *psys);

bool psys_in_edit_mode(struct Depsgraph *depsgraph, const struct ParticleSystem *psys);
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, bool use_render_params);
bool psys_check_edited(struct ParticleSystem *psys);

void psys_find_group_weights(struct ParticleSettings *part);
void psys_check_group_weights(struct ParticleSettings *part);
int psys_uses_gravity(struct ParticleSimulationData *sim);
void BKE_particlesettings_fluid_default_settings(struct ParticleSettings *part);

/**
 * Free cache path.
 */
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
/**
 * Free everything.
 */
void psys_free(struct Object *ob, struct ParticleSystem *psys);
/**
 * Copy.
 */
void psys_copy_particles(struct ParticleSystem *psys_dst, struct ParticleSystem *psys_src);

bool psys_render_simplify_params(struct ParticleSystem *psys,
                                 struct ChildParticle *cpa,
                                 float *params);

void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
void psys_interpolate_mcol(const struct MCol *mcol, int quad, const float w[4], struct MCol *mc);

void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time);

void psys_emitter_customdata_mask(struct ParticleSystem *psys,
                                  struct CustomData_MeshMasks *r_cddata_masks);
void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd,
                              int from,
                              int index,
                              int index_dmcache,
                              float fuv[4],
                              float foffset,
                              float vec[3],
                              float nor[3],
                              float utan[3],
                              float vtan[3],
                              float orco[3]);
struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob,
                                                     struct ParticleSystem *psys);

struct ModifierData *object_add_particle_system(struct Main *bmain,
                                                struct Scene *scene,
                                                struct Object *ob,
                                                const char *name);
struct ModifierData *object_copy_particle_system(struct Main *bmain,
                                                 struct Scene *scene,
                                                 struct Object *ob,
                                                 const struct ParticleSystem *psys_orig);
void object_remove_particle_system(struct Main *bmain,
                                   struct Scene *scene,
                                   struct Object *ob,
                                   struct ParticleSystem *psys);
struct ParticleSettings *BKE_particlesettings_add(struct Main *bmain, const char *name);
void psys_reset(struct ParticleSystem *psys, int mode);

void psys_find_parents(struct ParticleSimulationData *sim, bool use_render_params);

void psys_unique_name(struct Object *object, struct ParticleSystem *psys, const char *defname);

/**
 * Calculates paths ready for drawing/rendering
 * - Useful for making use of opengl vertex arrays for super fast strand drawing.
 * - Makes child strands possible and creates them too into the cache.
 * - Cached path data is also used to determine cut position for the edit-mode tool.
 */
void psys_cache_paths(struct ParticleSimulationData *sim, float cfra, bool use_render_params);
void psys_cache_edit_paths(struct Depsgraph *depsgraph,
                           struct Scene *scene,
                           struct Object *ob,
                           struct PTCacheEdit *edit,
                           float cfra,
                           bool use_render_params);
void psys_cache_child_paths(struct ParticleSimulationData *sim,
                            float cfra,
                            bool editupdate,
                            bool use_render_params);
bool do_guides(struct Depsgraph *depsgraph,
               struct ParticleSettings *part,
               struct ListBase *effectors,
               ParticleKey *state,
               int index,
               float time);
void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors);
float psys_get_timestep(struct ParticleSimulationData *sim);
float psys_get_child_time(struct ParticleSystem *psys,
                          struct ChildParticle *cpa,
                          float cfra,
                          float *birthtime,
                          float *dietime);
float psys_get_child_size(struct ParticleSystem *psys,
                          struct ChildParticle *cpa,
                          float cfra,
                          float *pa_time);
/**
 * Gets hair (or keyed) particles state at the "path time" specified in `state->time`.
 */
void psys_get_particle_on_path(struct ParticleSimulationData *sim,
                               int pa_num,
                               struct ParticleKey *state,
                               bool vel);
/**
 * Gets particle's state at a time.
 * \return true if particle exists and can be seen and false if not.
 */
bool psys_get_particle_state(struct ParticleSimulationData *sim,
                             int p,
                             struct ParticleKey *state,
                             bool always);

/* Child paths. */

void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part);
void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part);
void BKE_particlesettings_twist_curve_init(struct ParticleSettings *part);
void psys_apply_child_modifiers(struct ParticleThreadContext *ctx,
                                struct ListBase *modifiers,
                                struct ChildParticle *cpa,
                                struct ParticleTexture *ptex,
                                const float orco[3],
                                float hairmat[4][4],
                                struct ParticleCacheKey *keys,
                                struct ParticleCacheKey *parent_keys,
                                const float parent_orco[3]);

void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata);
void psys_sph_finalize(struct SPHData *sphdata);
/**
 * Sample the density field at a point in space.
 */
void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]);

/* For anim.c */

void psys_get_dupli_texture(struct ParticleSystem *psys,
                            struct ParticleSettings *part,
                            struct ParticleSystemModifierData *psmd,
                            struct ParticleData *pa,
                            struct ChildParticle *cpa,
                            float uv[2],
                            float orco[3]);
void psys_get_dupli_path_transform(struct ParticleSimulationData *sim,
                                   struct ParticleData *pa,
                                   struct ChildParticle *cpa,
                                   struct ParticleCacheKey *cache,
                                   float mat[4][4],
                                   float *scale);

/**
 * Threaded child particle distribution and path caching.
 */
void psys_thread_context_init(struct ParticleThreadContext *ctx,
                              struct ParticleSimulationData *sim);
void psys_thread_context_free(struct ParticleThreadContext *ctx);
void psys_tasks_create(struct ParticleThreadContext *ctx,
                       int startpart,
                       int endpart,
                       struct ParticleTask **r_tasks,
                       int *r_numtasks);
void psys_tasks_free(struct ParticleTask *tasks, int numtasks);

void psys_apply_hair_lattice(struct Depsgraph *depsgraph,
                             struct Scene *scene,
                             struct Object *ob,
                             struct ParticleSystem *psys);

/* particle_system.c */

struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
/**
 * Counts valid keyed targets.
 */
void psys_count_keyed_targets(struct ParticleSimulationData *sim);
void psys_update_particle_tree(struct ParticleSystem *psys, float cfra);
/**
 * System type has changed so set sensible defaults and clear non applicable flags.
 */
void psys_changed_type(struct Object *ob, struct ParticleSystem *psys);

void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
void psys_get_pointcache_start_end(struct Scene *scene,
                                   ParticleSystem *psys,
                                   int *sfra,
                                   int *efra);

void psys_check_boid_data(struct ParticleSystem *psys);

void psys_get_birth_coords(struct ParticleSimulationData *sim,
                           struct ParticleData *pa,
                           struct ParticleKey *state,
                           float dtime,
                           float cfra);

/**
 * Main particle update call, checks that things are ok on the large scale and
 * then advances in to actual particle calculations depending on particle type.
 */
void particle_system_update(struct Depsgraph *depsgraph,
                            struct Scene *scene,
                            struct Object *ob,
                            struct ParticleSystem *psys,
                            bool use_render_params);

/**
 * Callback format for performing operations on ID-pointers for particle systems.
 */
typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys,
                                     struct ID **idpoin,
                                     void *userdata,
                                     int cb_flag);

void BKE_particlesystem_id_loop(struct ParticleSystem *psys,
                                ParticleSystemIDFunc func,
                                void *userdata);

/**
 * Reset all particle systems in the given object.
 */
void BKE_particlesystem_reset_all(struct Object *object);

/* ----------- functions needed only inside particlesystem ------------ */

/* particle.c */

void psys_disable_all(struct Object *ob);
void psys_enable_all(struct Object *ob);

void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics);
void free_keyed_keys(struct ParticleSystem *psys);
void psys_free_particles(struct ParticleSystem *psys);
void psys_free_children(struct ParticleSystem *psys);

void psys_interpolate_particle(
    short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, bool velocity);
void psys_vec_rot_to_face(struct Mesh *mesh, struct ParticleData *pa, float vec[3]);
void psys_mat_hair_to_object(struct Object *ob,
                             struct Mesh *mesh,
                             short from,
                             struct ParticleData *pa,
                             float hairmat[4][4]);
void psys_mat_hair_to_global(struct Object *ob,
                             struct Mesh *mesh,
                             short from,
                             struct ParticleData *pa,
                             float hairmat[4][4]);
void psys_mat_hair_to_orco(struct Object *ob,
                           struct Mesh *mesh,
                           short from,
                           struct ParticleData *pa,
                           float hairmat[4][4]);

float psys_get_dietime_from_cache(struct PointCache *cache, int index);

void psys_free_pdd(struct ParticleSystem *psys);

float *psys_cache_vgroup(struct Mesh *mesh, struct ParticleSystem *psys, int vgroup);
void psys_get_texture(struct ParticleSimulationData *sim,
                      struct ParticleData *pa,
                      struct ParticleTexture *ptex,
                      int event,
                      float cfra);
/**
 * Interpolate a location on a face based on face coordinates.
 */
void psys_interpolate_face(struct Mesh *mesh,
                           const float (*positions)[3],
                           const float (*vert_normals)[3],
                           struct MFace *mface,
                           struct MTFace *tface,
                           const float (*orcodata)[3],
                           float w[4],
                           float vec[3],
                           float nor[3],
                           float utan[3],
                           float vtan[3],
                           float orco[3]);
float psys_particle_value_from_verts(struct Mesh *mesh,
                                     short from,
                                     struct ParticleData *pa,
                                     float *values);
void psys_get_from_key(
    struct ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time);

/**
 * Callback for #BVHTree near test.
 */
void BKE_psys_collision_neartest_cb(void *userdata,
                                    int index,
                                    const struct BVHTreeRay *ray,
                                    struct BVHTreeRayHit *hit);
/**
 * Interprets particle data to get a point on a mesh in object space.
 */
void psys_particle_on_dm(struct 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]);

/* particle_system.c */

void distribute_particles(struct ParticleSimulationData *sim, int from);
/**
 * Set particle parameters that don't change during particle's life.
 */
void init_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
void psys_calc_dmcache(struct Object *ob,
                       struct Mesh *mesh_final,
                       struct Mesh *mesh_original,
                       struct ParticleSystem *psys);
/**
 * Find the final derived mesh tessface for a particle, from its original tessface index.
 * This is slow and can be optimized but only for many lookups.
 *
 * \param mesh_final: Final mesh, it may not have the same topology as original mesh.
 * \param mesh_original: Original mesh, use for accessing #MPoly to #MFace mapping.
 * \param findex_orig: The input tessface index.
 * \param fw: Face weights (position of the particle inside the \a findex_orig tessface).
 * \param poly_nodes: May be NULL, otherwise an array of linked list,
 * one for each final \a mesh_final polygon, containing all its tessfaces indices.
 * \return The \a mesh_final tessface index.
 */
int psys_particle_dm_face_lookup(struct Mesh *mesh_final,
                                 struct Mesh *mesh_original,
                                 int findex_orig,
                                 const float fw[4],
                                 struct LinkNode **poly_nodes);

/**
 * Sets particle to the emitter surface with initial velocity & rotation.
 */
void reset_particle(struct ParticleSimulationData *sim,
                    struct ParticleData *pa,
                    float dtime,
                    float cfra);

float psys_get_current_display_percentage(struct ParticleSystem *psys, bool use_render_params);

/* psys_reset */
#define PSYS_RESET_ALL 1
#define PSYS_RESET_DEPSGRAPH 2
/* #define PSYS_RESET_CHILDREN  3 */ /*UNUSED*/
#define PSYS_RESET_CACHE_MISS 4

/* index_dmcache */
#define DMCACHE_NOTFOUND -1
#define DMCACHE_ISCHILD -2

/* **** Depsgraph evaluation **** */

struct Depsgraph;

void BKE_particle_settings_eval_reset(struct Depsgraph *depsgraph,
                                      struct ParticleSettings *particle_settings);

void BKE_particle_system_eval_init(struct Depsgraph *depsgraph, struct Object *object);

/* Draw Cache */
enum {
  BKE_PARTICLE_BATCH_DIRTY_ALL = 0,
};
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode);
void BKE_particle_batch_cache_free(struct ParticleSystem *psys);

extern void (*BKE_particle_batch_cache_dirty_tag_cb)(struct ParticleSystem *psys, int mode);
extern void (*BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys);

/* .blend file I/O */

void BKE_particle_partdeflect_blend_read_data(struct BlendDataReader *reader,
                                              struct PartDeflect *pd);
void BKE_particle_partdeflect_blend_read_lib(struct BlendLibReader *reader,
                                             struct ID *id,
                                             struct PartDeflect *pd);
void BKE_particle_system_blend_write(struct BlendWriter *writer, struct ListBase *particles);
void BKE_particle_system_blend_read_data(struct BlendDataReader *reader,
                                         struct ListBase *particles);
void BKE_particle_system_blend_read_lib(struct BlendLibReader *reader,
                                        struct Object *ob,
                                        struct ID *id,
                                        struct ListBase *particles);

#ifdef __cplusplus
}
#endif