Blender  V3.3
pointcache.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 
14 #include "CLG_log.h"
15 
16 #include "MEM_guardedalloc.h"
17 
18 #include "DNA_ID.h"
19 #include "DNA_collection_types.h"
20 #include "DNA_dynamicpaint_types.h"
21 #include "DNA_fluid_types.h"
22 #include "DNA_modifier_types.h"
23 #include "DNA_object_force_types.h"
24 #include "DNA_object_types.h"
25 #include "DNA_particle_types.h"
26 #include "DNA_rigidbody_types.h"
27 #include "DNA_scene_types.h"
28 #include "DNA_simulation_types.h"
29 
30 #include "BLI_blenlib.h"
31 #include "BLI_endian_switch.h"
32 #include "BLI_math.h"
33 #include "BLI_string.h"
34 #include "BLI_utildefines.h"
35 
36 #include "BLT_translation.h"
37 
38 #include "PIL_time.h"
39 
40 #include "BKE_appdir.h"
41 #include "BKE_cloth.h"
42 #include "BKE_collection.h"
43 #include "BKE_dynamicpaint.h"
44 #include "BKE_fluid.h"
45 #include "BKE_global.h"
46 #include "BKE_lib_id.h"
47 #include "BKE_main.h"
48 #include "BKE_modifier.h"
49 #include "BKE_object.h"
50 #include "BKE_particle.h"
51 #include "BKE_pointcache.h"
52 #include "BKE_scene.h"
53 #include "BKE_softbody.h"
54 
55 #include "BLO_read_write.h"
56 
57 #include "DEG_depsgraph_query.h"
58 
59 #include "BIK_api.h"
60 
61 #ifdef WITH_BULLET
62 # include "RBI_api.h"
63 #endif
64 
65 #ifdef WITH_LZO
66 # ifdef WITH_SYSTEM_LZO
67 # include <lzo/lzo1x.h>
68 # else
69 # include "minilzo.h"
70 # endif
71 # define LZO_HEAP_ALLOC(var, size) \
72  lzo_align_t __LZO_MMODEL var[((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)]
73 #endif
74 
75 #define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
76 
77 #ifdef WITH_LZMA
78 # include "LzmaLib.h"
79 #endif
80 
81 /* needed for directory lookup */
82 #ifndef WIN32
83 # include <dirent.h>
84 #else
85 # include "BLI_winstuff.h"
86 #endif
87 
88 #define PTCACHE_DATA_FROM(data, type, from) \
89  if (data[type]) { \
90  memcpy(data[type], from, ptcache_data_size[type]); \
91  } \
92  (void)0
93 
94 #define PTCACHE_DATA_TO(data, type, index, to) \
95  if (data[type]) { \
96  memcpy(to, \
97  (char *)(data)[type] + ((index) ? (index)*ptcache_data_size[type] : 0), \
98  ptcache_data_size[type]); \
99  } \
100  (void)0
101 
102 /* could be made into a pointcache option */
103 #define DURIAN_POINTCACHE_LIB_OK 1
104 
105 static CLG_LogRef LOG = {"bke.pointcache"};
106 
107 static int ptcache_data_size[] = {
108  sizeof(unsigned int), /* BPHYS_DATA_INDEX */
109  sizeof(float[3]), /* BPHYS_DATA_LOCATION */
110  sizeof(float[3]), /* BPHYS_DATA_VELOCITY */
111  sizeof(float[4]), /* BPHYS_DATA_ROTATION */
112  sizeof(float[3]), /* BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
113  sizeof(float), /* BPHYS_DATA_SIZE */
114  sizeof(float[3]), /* BPHYS_DATA_TIMES */
115  sizeof(BoidData), /* case BPHYS_DATA_BOIDS */
116 };
117 
118 static int ptcache_extra_datasize[] = {
119  0,
120  sizeof(ParticleSpring),
121  sizeof(float[3]),
122 };
123 
124 /* forward declarations */
125 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len);
127  PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode);
128 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size);
129 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
130 
131 /* Common functions */
133 {
134  int error = 0;
135 
136  /* Custom functions should read these basic elements too! */
137  if (!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) {
138  error = 1;
139  }
140 
141  if (!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) {
142  error = 1;
143  }
144 
145  return !error;
146 }
148 {
149  /* Custom functions should write these basic elements too! */
150  if (!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) {
151  return 0;
152  }
153 
154  if (!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) {
155  return 0;
156  }
157 
158  return 1;
159 }
161  unsigned int type,
162  unsigned int count,
163  void *data)
164 {
165  PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: extra data descriptor");
166 
167  extra->type = type;
168  extra->totdata = count;
169 
170  size_t size = extra->totdata * ptcache_extra_datasize[extra->type];
171 
172  extra->data = MEM_mallocN(size, "Point cache: extra data");
173  memcpy(extra->data, data, size);
174 
175  BLI_addtail(&pm->extradata, extra);
176 }
177 /* Softbody functions */
178 static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
179 {
180  SoftBody *soft = soft_v;
181  BodyPoint *bp = soft->bpoint + index;
182 
185 
186  return 1;
187 }
189  int index, void *soft_v, void **data, float UNUSED(cfra), const float *old_data)
190 {
191  SoftBody *soft = soft_v;
192  BodyPoint *bp = soft->bpoint + index;
193 
194  if (old_data) {
195  memcpy(bp->pos, data, sizeof(float[3]));
196  memcpy(bp->vec, data + 3, sizeof(float[3]));
197  }
198  else {
201  }
202 }
203 static void ptcache_softbody_interpolate(int index,
204  void *soft_v,
205  void **data,
206  float cfra,
207  float cfra1,
208  float cfra2,
209  const float *old_data)
210 {
211  SoftBody *soft = soft_v;
212  BodyPoint *bp = soft->bpoint + index;
213  ParticleKey keys[4];
214  float dfra;
215 
216  if (cfra1 == cfra2) {
217  return;
218  }
219 
220  copy_v3_v3(keys[1].co, bp->pos);
221  copy_v3_v3(keys[1].vel, bp->vec);
222 
223  if (old_data) {
224  memcpy(keys[2].co, old_data, sizeof(float[3]));
225  memcpy(keys[2].vel, old_data + 3, sizeof(float[3]));
226  }
227  else {
228  BKE_ptcache_make_particle_key(keys + 2, 0, data, cfra2);
229  }
230 
231  dfra = cfra2 - cfra1;
232 
233  mul_v3_fl(keys[1].vel, dfra);
234  mul_v3_fl(keys[2].vel, dfra);
235 
236  psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
237 
238  mul_v3_fl(keys->vel, 1.0f / dfra);
239 
240  copy_v3_v3(bp->pos, keys->co);
241  copy_v3_v3(bp->vec, keys->vel);
242 }
243 static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
244 {
245  SoftBody *soft = soft_v;
246  return soft->totpoint;
247 }
248 static void ptcache_softbody_error(const ID *UNUSED(owner_id),
249  void *UNUSED(soft_v),
250  const char *UNUSED(message))
251 {
252  /* ignored for now */
253 }
254 
255 /* Particle functions. */
256 
257 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
258 {
261 
262  /* no rotation info, so make something nice up */
263  if (data[BPHYS_DATA_ROTATION] == NULL) {
264  vec_to_quat(key->rot, key->vel, OB_NEGX, OB_POSZ);
265  }
266  else {
268  }
269 
271  key->time = time;
272 }
273 static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
274 {
275  ParticleSystem *psys = psys_v;
276  ParticleData *pa = psys->particles + index;
277  BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
278  float times[3];
279  int step = psys->pointcache->step;
280 
281  /* Skip some particles that are not stored in the cache. */
283  if (psys->part->flag & PART_DIED) {
284  /* Dead particles are stored when they are displayed. */
285  if (cfra < pa->time - step) {
286  return 0;
287  }
288  }
289  else {
290  /* Inclusive ranges for particle lifetime (`dietime - 1` for an inclusive end-frame). */
291  const int pa_sfra = (int)pa->time - step;
292  const int pa_efra = ((int)pa->dietime - 1) + step;
293  if (!(cfra >= pa_sfra && cfra <= pa_efra)) {
294  return 0;
295  }
296  }
297  }
298 
299  times[0] = pa->time;
300  times[1] = pa->dietime;
301  times[2] = pa->lifetime;
302 
310 
311  if (boid) {
313  }
314 
315  /* Return flag 1+1=2 for newly born particles
316  * to copy exact birth location to previously cached frame. */
317  return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
318 }
320  int index, void *psys_v, void **data, float cfra, const float *old_data)
321 {
322  ParticleSystem *psys = psys_v;
323  ParticleData *pa;
324  BoidParticle *boid;
325  float timestep = 0.04f * psys->part->timetweak;
326 
327  if (index >= psys->totpart) {
328  return;
329  }
330 
331  pa = psys->particles + index;
332  boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
333 
334  if (cfra > pa->state.time) {
335  memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
336  }
337 
338  if (old_data) {
339  /* old format cache */
340  memcpy(&pa->state, old_data, sizeof(ParticleKey));
341  return;
342  }
343 
344  BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
345 
346  /* set frames cached before birth to birth time */
347  if (cfra < pa->time) {
348  pa->state.time = pa->time;
349  }
350  else if (cfra > pa->dietime) {
351  pa->state.time = pa->dietime;
352  }
353 
354  if (data[BPHYS_DATA_SIZE]) {
356  }
357 
358  if (data[BPHYS_DATA_TIMES]) {
359  float times[3];
361  pa->time = times[0];
362  pa->dietime = times[1];
363  pa->lifetime = times[2];
364  }
365 
366  if (boid) {
368  }
369 
370  /* determine velocity from previous location */
372  if (cfra > pa->prev_state.time) {
373  sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
374  mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep);
375  }
376  else {
377  sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
378  mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep);
379  }
380  }
381 
382  /* default to no rotation */
384  unit_qt(pa->state.rot);
385  }
386 }
387 static void ptcache_particle_interpolate(int index,
388  void *psys_v,
389  void **data,
390  float cfra,
391  float cfra1,
392  float cfra2,
393  const float *old_data)
394 {
395  ParticleSystem *psys = psys_v;
396  ParticleData *pa;
397  ParticleKey keys[4];
398  float dfra, timestep = 0.04f * psys->part->timetweak;
399 
400  if (index >= psys->totpart) {
401  return;
402  }
403 
404  pa = psys->particles + index;
405 
406  /* Inclusive ranges for particle lifetime (`dietime - 1` for an inclusive end-frame). */
407  const int pa_sfra = (int)pa->time - psys->pointcache->step;
408  const int pa_efra = ((int)pa->dietime - 1) + psys->pointcache->step;
409 
410  /* Particle wasn't read from first cache so can't interpolate. */
411  if (!(cfra1 >= pa_sfra && cfra1 <= pa_efra)) {
412  return;
413  }
414 
415  cfra = MIN2(cfra, pa->dietime);
416  cfra1 = MIN2(cfra1, pa->dietime);
417  cfra2 = MIN2(cfra2, pa->dietime);
418 
419  if (cfra1 == cfra2) {
420  return;
421  }
422 
423  memcpy(keys + 1, &pa->state, sizeof(ParticleKey));
424  if (old_data) {
425  memcpy(keys + 2, old_data, sizeof(ParticleKey));
426  }
427  else {
428  BKE_ptcache_make_particle_key(keys + 2, 0, data, cfra2);
429  }
430 
431  /* determine velocity from previous location */
433  if (keys[1].time > keys[2].time) {
434  sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
435  mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep);
436  }
437  else {
438  sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
439  mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep);
440  }
441  }
442 
443  /* default to no rotation */
445  unit_qt(keys[2].rot);
446  }
447 
448  if (cfra > pa->time) {
449  cfra1 = MAX2(cfra1, pa->time);
450  }
451 
452  dfra = cfra2 - cfra1;
453 
454  mul_v3_fl(keys[1].vel, dfra * timestep);
455  mul_v3_fl(keys[2].vel, dfra * timestep);
456 
457  psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
458  interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
459 
460  mul_v3_fl(pa->state.vel, 1.0f / (dfra * timestep));
461 
462  pa->state.time = cfra;
463 }
464 
465 static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
466 {
467  ParticleSystem *psys = psys_v;
468  return psys->totpart;
469 }
470 
471 static void ptcache_particle_error(const ID *UNUSED(owner_id),
472  void *UNUSED(psys_v),
473  const char *UNUSED(message))
474 {
475  /* ignored for now */
476 }
477 
478 static int ptcache_particle_totwrite(void *psys_v, int cfra)
479 {
480  ParticleSystem *psys = psys_v;
481  ParticleData *pa = psys->particles;
482  int p, step = psys->pointcache->step;
483  int totwrite = 0;
484 
485  if (cfra == 0) {
486  return psys->totpart;
487  }
488 
489  if (psys->part->flag & PART_DIED) {
490  /* Also store dead particles when they are displayed. */
491  for (p = 0; p < psys->totpart; p++, pa++) {
492  const int pa_sfra = (int)pa->time - step;
493  totwrite += (cfra >= pa_sfra);
494  }
495  }
496  else {
497  for (p = 0; p < psys->totpart; p++, pa++) {
498  /* Inclusive ranges for particle lifetime (`dietime - 1` for an inclusive end-frame). */
499  const int pa_sfra = (int)pa->time - step;
500  const int pa_efra = ((int)pa->dietime - 1) + step;
501  totwrite += (cfra >= pa_sfra) && (cfra <= pa_efra);
502  }
503  }
504 
505  return totwrite;
506 }
507 
508 static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
509 {
510  ParticleSystem *psys = psys_v;
511 
512  if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid &&
514  psys->fluid_springs) {
517  }
518 }
519 
520 static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
521 {
522  ParticleSystem *psys = psys_v;
523  PTCacheExtra *extra = pm->extradata.first;
524 
525  for (; extra; extra = extra->next) {
526  switch (extra->type) {
528  if (psys->fluid_springs) {
529  MEM_freeN(psys->fluid_springs);
530  }
531 
532  psys->fluid_springs = MEM_dupallocN(extra->data);
533  psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata;
534  break;
535  }
536  }
537  }
538 }
539 
540 /* Cloth functions */
541 static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
542 {
543  ClothModifierData *clmd = cloth_v;
544  Cloth *cloth = clmd->clothObject;
545  ClothVertex *vert = cloth->verts + index;
546 
550 
551  return 1;
552 }
553 static void ptcache_cloth_read(
554  int index, void *cloth_v, void **data, float UNUSED(cfra), const float *old_data)
555 {
556  ClothModifierData *clmd = cloth_v;
557  Cloth *cloth = clmd->clothObject;
558  ClothVertex *vert = cloth->verts + index;
559 
560  if (old_data) {
561  memcpy(vert->x, data, sizeof(float[3]));
562  memcpy(vert->xconst, data + 3, sizeof(float[3]));
563  memcpy(vert->v, data + 6, sizeof(float[3]));
564  }
565  else {
569  }
570 }
571 static void ptcache_cloth_interpolate(int index,
572  void *cloth_v,
573  void **data,
574  float cfra,
575  float cfra1,
576  float cfra2,
577  const float *old_data)
578 {
579  ClothModifierData *clmd = cloth_v;
580  Cloth *cloth = clmd->clothObject;
581  ClothVertex *vert = cloth->verts + index;
582  ParticleKey keys[4];
583  float dfra;
584 
585  if (cfra1 == cfra2) {
586  return;
587  }
588 
589  copy_v3_v3(keys[1].co, vert->x);
590  copy_v3_v3(keys[1].vel, vert->v);
591 
592  if (old_data) {
593  memcpy(keys[2].co, old_data, sizeof(float[3]));
594  memcpy(keys[2].vel, old_data + 6, sizeof(float[3]));
595  }
596  else {
597  BKE_ptcache_make_particle_key(keys + 2, 0, data, cfra2);
598  }
599 
600  dfra = cfra2 - cfra1;
601 
602  mul_v3_fl(keys[1].vel, dfra);
603  mul_v3_fl(keys[2].vel, dfra);
604 
605  psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
606 
607  mul_v3_fl(keys->vel, 1.0f / dfra);
608 
609  copy_v3_v3(vert->x, keys->co);
610  copy_v3_v3(vert->v, keys->vel);
611 
612  /* should vert->xconst be interpolated somehow too? - jahka */
613 }
614 
615 static void ptcache_cloth_extra_write(void *cloth_v, PTCacheMem *pm, int UNUSED(cfra))
616 {
617  ClothModifierData *clmd = cloth_v;
618  Cloth *cloth = clmd->clothObject;
619 
620  if (!is_zero_v3(cloth->average_acceleration)) {
622  }
623 }
624 static void ptcache_cloth_extra_read(void *cloth_v, PTCacheMem *pm, float UNUSED(cfra))
625 {
626  ClothModifierData *clmd = cloth_v;
627  Cloth *cloth = clmd->clothObject;
628  PTCacheExtra *extra = pm->extradata.first;
629 
631 
632  for (; extra; extra = extra->next) {
633  switch (extra->type) {
635  copy_v3_v3(cloth->average_acceleration, extra->data);
636  break;
637  }
638  }
639  }
640 }
641 
642 static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
643 {
644  ClothModifierData *clmd = cloth_v;
645  return clmd->clothObject ? clmd->clothObject->mvert_num : 0;
646 }
647 
648 static void ptcache_cloth_error(const ID *owner_id, void *cloth_v, const char *message)
649 {
650  ClothModifierData *clmd = cloth_v;
651  BLI_assert(GS(owner_id->name) == ID_OB);
652  if (clmd->hairdata == NULL) {
653  /* If there is hair data, this modifier does not actually exist on the object. */
654  BKE_modifier_set_error((Object *)owner_id, &clmd->modifier, "%s", message);
655  }
656 }
657 
658 static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
659 {
661 
662  if (!surface->data) {
663  return 0;
664  }
665 
666  return surface->data->total_points;
667 }
668 
669 static void ptcache_dynamicpaint_error(const ID *UNUSED(owner_id),
670  void *UNUSED(sd),
671  const char *UNUSED(message))
672 {
673  /* ignored for now */
674 }
675 
676 #define DPAINT_CACHE_VERSION "1.01"
677 
678 static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
679 {
681  int cache_compress = 1;
682 
683  /* version header */
684  ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char[4]));
685 
686  if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
687  int total_points = surface->data->total_points;
688  unsigned int in_len;
689  unsigned char *out;
690 
691  /* cache type */
692  ptcache_file_write(pf, &surface->type, 1, sizeof(int));
693 
694  if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
695  in_len = sizeof(PaintPoint) * total_points;
696  }
698  in_len = sizeof(float) * total_points;
699  }
700  else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
701  in_len = sizeof(PaintWavePoint) * total_points;
702  }
703  else {
704  return 0;
705  }
706 
707  out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
708 
710  pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress);
711  MEM_freeN(out);
712  }
713  return 1;
714 }
715 static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
716 {
718  char version[4];
719 
720  /* version header */
721  ptcache_file_read(pf, version, 1, sizeof(char[4]));
722  if (!STREQLEN(version, DPAINT_CACHE_VERSION, 4)) {
723  CLOG_ERROR(&LOG, "Dynamic Paint: Invalid cache version: '%c%c%c%c'!", UNPACK4(version));
724  return 0;
725  }
726 
727  if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
728  unsigned int data_len;
729  int surface_type;
730 
731  /* cache type */
732  ptcache_file_read(pf, &surface_type, 1, sizeof(int));
733 
734  if (surface_type != surface->type) {
735  return 0;
736  }
737 
738  /* read surface data */
739  if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
740  data_len = sizeof(PaintPoint);
741  }
743  data_len = sizeof(float);
744  }
745  else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
746  data_len = sizeof(PaintWavePoint);
747  }
748  else {
749  return 0;
750  }
751 
753  pf, (unsigned char *)surface->data->type_data, data_len * surface->data->total_points);
754  }
755  return 1;
756 }
757 
758 /* Rigid Body functions */
759 static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
760 {
761  RigidBodyWorld *rbw = rb_v;
762  Object *ob = NULL;
763 
764  if (rbw->objects) {
765  ob = rbw->objects[index];
766  }
767 
768  if (ob && ob->rigidbody_object) {
769  RigidBodyOb *rbo = ob->rigidbody_object;
770 
771  if (rbo->type == RBO_TYPE_ACTIVE && rbo->shared->physics_object != NULL) {
772 #ifdef WITH_BULLET
775 #endif
778  }
779  }
780 
781  return 1;
782 }
784  int index, void *rb_v, void **data, float UNUSED(cfra), const float *old_data)
785 {
786  RigidBodyWorld *rbw = rb_v;
787  Object *ob = NULL;
788 
789  if (rbw->objects) {
790  ob = rbw->objects[index];
791  }
792 
793  if (ob && ob->rigidbody_object) {
794  RigidBodyOb *rbo = ob->rigidbody_object;
795 
796  if (rbo->type == RBO_TYPE_ACTIVE) {
797 
798  if (old_data) {
799  memcpy(rbo->pos, data, sizeof(float[3]));
800  memcpy(rbo->orn, data + 3, sizeof(float[4]));
801  }
802  else {
805  }
806  }
807  }
808 }
809 static void ptcache_rigidbody_interpolate(int index,
810  void *rb_v,
811  void **data,
812  float cfra,
813  float cfra1,
814  float cfra2,
815  const float *old_data)
816 {
817  RigidBodyWorld *rbw = rb_v;
818  Object *ob = NULL;
819 
820  if (rbw->objects) {
821  ob = rbw->objects[index];
822  }
823 
824  if (ob && ob->rigidbody_object) {
825  RigidBodyOb *rbo = ob->rigidbody_object;
826 
827  if (rbo->type == RBO_TYPE_ACTIVE) {
828  /* It may be possible to improve results by taking into account velocity
829  * for interpolation using psys_interpolate_particle, however this is
830  * not currently cached. */
831  float pos[3], orn[4];
832 
833  if (old_data) {
834  memcpy(pos, data, sizeof(float[3]));
835  memcpy(orn, data + 3, sizeof(float[4]));
836  }
837  else {
840  }
841 
842  const float t = (cfra - cfra1) / (cfra2 - cfra1);
843  interp_v3_v3v3(rbo->pos, rbo->pos, pos, t);
844  interp_qt_qtqt(rbo->orn, rbo->orn, orn, t);
845  }
846  }
847 }
848 static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
849 {
850  RigidBodyWorld *rbw = rb_v;
851 
852  return rbw->numbodies;
853 }
854 
855 static void ptcache_rigidbody_error(const struct ID *UNUSED(owner_id),
856  void *UNUSED(rb_v),
857  const char *UNUSED(message))
858 {
859  /* ignored for now */
860 }
861 
862 /* Creating ID's */
863 
865 {
866  memset(pid, 0, sizeof(PTCacheID));
867 
868  pid->owner_id = &ob->id;
869  pid->calldata = sb;
871  pid->cache = sb->shared->pointcache;
872  pid->cache_ptr = &sb->shared->pointcache;
873  pid->ptcaches = &sb->shared->ptcaches;
876 
880 
881  pid->write_stream = NULL;
882  pid->read_stream = NULL;
883 
884  pid->write_extra_data = NULL;
885  pid->read_extra_data = NULL;
887 
890 
891  pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_VELOCITY);
892  pid->info_types = 0;
893 
894  pid->stack_index = pid->cache->index;
895 
896  pid->default_step = 1;
897  pid->max_step = 20;
899 }
901 {
902  memset(pid, 0, sizeof(PTCacheID));
903 
904  pid->owner_id = &ob->id;
905  pid->calldata = psys;
907  pid->stack_index = psys->pointcache->index;
908  pid->cache = psys->pointcache;
909  pid->cache_ptr = &psys->pointcache;
910  pid->ptcaches = &psys->ptcaches;
911 
912  if (psys->part->type != PART_HAIR) {
913  pid->flag |= PTCACHE_VEL_PER_SEC;
914  }
915 
919 
923 
924  pid->write_stream = NULL;
925  pid->read_stream = NULL;
926 
927  pid->write_extra_data = NULL;
928  pid->read_extra_data = NULL;
930 
933 
934  pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_VELOCITY) |
935  (1 << BPHYS_DATA_INDEX);
936 
937  if (psys->part->phystype == PART_PHYS_BOIDS) {
938  pid->data_types |= (1 << BPHYS_DATA_AVELOCITY) | (1 << BPHYS_DATA_ROTATION) |
939  (1 << BPHYS_DATA_BOIDS);
940  }
941  else if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid &&
945  }
946 
947  if (psys->part->flag & PART_ROTATIONS) {
948  pid->data_types |= (1 << BPHYS_DATA_ROTATION);
949 
950  if (psys->part->rotmode != PART_ROT_VEL || psys->part->avemode == PART_AVE_RAND ||
951  psys->part->avefac != 0.0f) {
952  pid->data_types |= (1 << BPHYS_DATA_AVELOCITY);
953  }
954  }
955 
956  pid->info_types = (1 << BPHYS_DATA_TIMES);
957 
958  pid->default_step = 1;
959  pid->max_step = 20;
961 }
963 {
964  memset(pid, 0, sizeof(PTCacheID));
965 
966  pid->owner_id = &ob->id;
967  pid->calldata = clmd;
968  pid->type = PTCACHE_TYPE_CLOTH;
969  pid->stack_index = clmd->point_cache->index;
970  pid->cache = clmd->point_cache;
971  pid->cache_ptr = &clmd->point_cache;
972  pid->ptcaches = &clmd->ptcaches;
974  pid->error = ptcache_cloth_error;
975 
979 
980  pid->write_stream = NULL;
981  pid->read_stream = NULL;
982 
986 
989 
990  pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_VELOCITY) |
991  (1 << BPHYS_DATA_XCONST);
992  pid->info_types = 0;
993 
994  pid->default_step = 1;
995  pid->max_step = 1;
997 }
998 
999 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *fmd)
1000 {
1001  FluidDomainSettings *fds = fmd->domain;
1002 
1003  memset(pid, 0, sizeof(PTCacheID));
1004 
1005  pid->owner_id = &ob->id;
1006  pid->calldata = fmd;
1007 
1009  pid->stack_index = fds->point_cache[0]->index;
1010 
1011  pid->cache = fds->point_cache[0];
1012  pid->cache_ptr = &(fds->point_cache[0]);
1013  pid->ptcaches = &(fds->ptcaches[0]);
1014 }
1015 
1017 {
1018 
1019  memset(pid, 0, sizeof(PTCacheID));
1020 
1021  pid->owner_id = &ob->id;
1022  pid->calldata = surface;
1024  pid->cache = surface->pointcache;
1025  pid->cache_ptr = &surface->pointcache;
1026  pid->ptcaches = &surface->ptcaches;
1029 
1030  pid->write_point = NULL;
1031  pid->read_point = NULL;
1032  pid->interpolate_point = NULL;
1033 
1036 
1037  pid->write_extra_data = NULL;
1038  pid->read_extra_data = NULL;
1040 
1043 
1045  pid->info_types = 0;
1046 
1047  pid->stack_index = pid->cache->index;
1048 
1049  pid->default_step = 1;
1050  pid->max_step = 1;
1052 }
1053 
1055 {
1056 
1057  memset(pid, 0, sizeof(PTCacheID));
1058 
1059  pid->owner_id = ob != NULL ? &ob->id : NULL;
1060  pid->calldata = rbw;
1062  pid->cache = rbw->shared->pointcache;
1063  pid->cache_ptr = &rbw->shared->pointcache;
1064  pid->ptcaches = &rbw->shared->ptcaches;
1067 
1071 
1072  pid->write_stream = NULL;
1073  pid->read_stream = NULL;
1074 
1075  pid->write_extra_data = NULL;
1076  pid->read_extra_data = NULL;
1078 
1081 
1082  pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_ROTATION);
1083  pid->info_types = 0;
1084 
1085  pid->stack_index = pid->cache->index;
1086 
1087  pid->default_step = 1;
1088  pid->max_step = 1;
1090 }
1091 
1093 {
1094  PTCacheID result = {0};
1095 
1096  ListBase pidlist;
1098 
1099  LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
1100  if (pid->cache == cache) {
1101  result = *pid;
1102  break;
1103  }
1104  }
1105 
1106  BLI_freelistN(&pidlist);
1107 
1108  return result;
1109 }
1110 
1111 /* Callback which is used by point cache foreach() family of functions.
1112  *
1113  * Receives ID of the point cache.
1114  *
1115  * NOTE: This ID is owned by foreach() routines and can not be used outside of
1116  * the foreach loop. This means that if one wants to store them those are to be
1117  * malloced and copied over.
1118  *
1119  * If the function returns false, then foreach() loop aborts.
1120  */
1121 typedef bool (*ForeachPtcacheCb)(PTCacheID *pid, void *userdata);
1122 
1125  void *callback_user_data)
1126 {
1127  PTCacheID pid;
1128  for (ParticleSystem *psys = object->particlesystem.first; psys != NULL; psys = psys->next) {
1129  if (psys->part == NULL) {
1130  continue;
1131  }
1132  /* Check to make sure point cache is actually used by the particles. */
1133  if (ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
1134  continue;
1135  }
1136  /* Hair needs to be included in id-list for cache edit mode to work. */
1137 #if 0
1138  if ((psys->part->type == PART_HAIR) && (psys->flag & PSYS_HAIR_DYNAMICS) == 0) {
1139  continue;
1140  }
1141 #endif
1142  if (psys->part->type == PART_FLUID) {
1143  continue;
1144  }
1145  BKE_ptcache_id_from_particles(&pid, object, psys);
1146  if (!callback(&pid, callback_user_data)) {
1147  return false;
1148  }
1149  }
1150  return true;
1151 }
1152 
1155  void *callback_user_data)
1156 {
1157  PTCacheID pid;
1158  for (ModifierData *md = object->modifiers.first; md != NULL; md = md->next) {
1159  if (md->type == eModifierType_Cloth) {
1160  BKE_ptcache_id_from_cloth(&pid, object, (ClothModifierData *)md);
1161  if (!callback(&pid, callback_user_data)) {
1162  return false;
1163  }
1164  }
1165  else if (md->type == eModifierType_Fluid) {
1166  FluidModifierData *fmd = (FluidModifierData *)md;
1167  if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
1168  BKE_ptcache_id_from_smoke(&pid, object, (FluidModifierData *)md);
1169  if (!callback(&pid, callback_user_data)) {
1170  return false;
1171  }
1172  }
1173  }
1174  else if (md->type == eModifierType_DynamicPaint) {
1176  if (pmd->canvas) {
1178  for (; surface; surface = surface->next) {
1180  if (!callback(&pid, callback_user_data)) {
1181  return false;
1182  }
1183  }
1184  }
1185  }
1186  }
1187  return true;
1188 }
1189 
1190 /* Return false if any of callbacks returned false. */
1192  Scene *scene, Object *object, int duplis, ForeachPtcacheCb callback, void *callback_user_data)
1193 {
1194  PTCacheID pid;
1195 
1196  if (object != NULL) {
1197  /* Soft body. */
1198  if (object->soft != NULL) {
1199  BKE_ptcache_id_from_softbody(&pid, object, object->soft);
1200  if (!callback(&pid, callback_user_data)) {
1201  return false;
1202  }
1203  }
1204  /* Particle systems. */
1205  if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) {
1206  return false;
1207  }
1208  /* Modifiers. */
1209  if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) {
1210  return false;
1211  }
1212  /* Consider all object in dupli-groups to be part of the same object,
1213  * for baking with linking dupli-groups. Once we have better overrides
1214  * this can be revisited so users select the local objects directly. */
1215  if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) {
1217  if (current_object == object) {
1218  continue;
1219  }
1220  foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data);
1221  }
1223  }
1224  }
1225 
1226  /* Rigid body. */
1227  if (scene != NULL && (object == NULL || object->rigidbody_object != NULL) &&
1228  scene->rigidbody_world != NULL) {
1230  if (!callback(&pid, callback_user_data)) {
1231  return false;
1232  }
1233  }
1234  return true;
1235 }
1236 
1240 
1241 static bool ptcache_ids_from_object_cb(PTCacheID *pid, void *userdata)
1242 {
1243  PTCacheIDsFromObjectData *data = userdata;
1244  PTCacheID *own_pid = MEM_mallocN(sizeof(PTCacheID), "PTCacheID");
1245  *own_pid = *pid;
1246  BLI_addtail(data->list_base, own_pid);
1247  return true;
1248 }
1249 
1251 {
1253  lb->first = lb->last = NULL;
1254  data.list_base = lb;
1256 }
1257 
1258 static bool ptcache_object_has_cb(PTCacheID *UNUSED(pid), void *UNUSED(userdata))
1259 {
1260  return false;
1261 }
1262 
1263 bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis)
1264 {
1265  return !foreach_object_ptcache(scene, ob, duplis, ptcache_object_has_cb, NULL);
1266 }
1267 
1268 /* File handling */
1269 
1270 static const char *ptcache_file_extension(const PTCacheID *pid)
1271 {
1272  switch (pid->file_type) {
1273  default:
1274  case PTCACHE_FILE_PTCACHE:
1275  return PTCACHE_EXT;
1276  }
1277 }
1278 
1282 static int ptcache_frame_from_filename(const char *filename, const char *ext)
1283 {
1284  const int frame_len = 6;
1285  const int ext_len = frame_len + strlen(ext);
1286  const int len = strlen(filename);
1287 
1288  /* could crash if trying to copy a string out of this range */
1289  if (len > ext_len) {
1290  /* using frame_len here gives compile error (vla) */
1291  char num[/* frame_len */ 6 + 1];
1292  BLI_strncpy(num, filename + len - ext_len, sizeof(num));
1293 
1294  return atoi(num);
1295  }
1296 
1297  return -1;
1298 }
1299 
1300 /* Takes an Object ID and returns a unique name
1301  * - id: object id
1302  * - cfra: frame for the cache, can be negative
1303  * - stack_index: index in the modifier stack. we can have cache for more than one stack_index
1304  */
1305 
1306 #define MAX_PTCACHE_PATH FILE_MAX
1307 #define MAX_PTCACHE_FILE (FILE_MAX * 2)
1308 
1309 static int ptcache_path(PTCacheID *pid, char *filename)
1310 {
1311  const char *blendfile_path = BKE_main_blendfile_path_from_global();
1312  Library *lib = (pid->owner_id) ? pid->owner_id->lib : NULL;
1313  const char *blendfilename = (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH) == 0) ?
1314  lib->filepath_abs :
1315  blendfile_path;
1316  size_t i;
1317 
1318  if (pid->cache->flag & PTCACHE_EXTERNAL) {
1319  strcpy(filename, pid->cache->path);
1320 
1321  if (BLI_path_is_rel(filename)) {
1322  BLI_path_abs(filename, blendfilename);
1323  }
1324 
1325  return BLI_path_slash_ensure(filename); /* new strlen() */
1326  }
1327  if ((blendfile_path[0] != '\0') || lib) {
1328  char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
1329 
1330  BLI_split_file_part(blendfilename, file, sizeof(file));
1331  i = strlen(file);
1332 
1333  /* remove .blend */
1334  if (i > 6) {
1335  file[i - 6] = '\0';
1336  }
1337 
1338  /* Add blend file name to pointcache dir. */
1339  BLI_snprintf(filename, MAX_PTCACHE_PATH, "//" PTCACHE_PATH "%s", file);
1340 
1341  BLI_path_abs(filename, blendfilename);
1342  return BLI_path_slash_ensure(filename); /* new strlen() */
1343  }
1344 
1345  /* use the temp path. this is weak but better than not using point cache at all */
1346  /* temporary directory is assumed to exist and ALWAYS has a trailing slash */
1348 
1349  return BLI_path_slash_ensure(filename); /* new strlen() */
1350 }
1351 
1353  char *filename,
1354  const size_t filename_len,
1355  const bool use_frame_number,
1356  const int cfra)
1357 {
1358  size_t len = filename_len;
1359  char *filename_ext;
1360  filename_ext = filename + filename_len;
1361  *filename_ext = '\0';
1362 
1363  /* PointCaches are inserted in object's list on demand, we need a valid index now. */
1364  if (pid->cache->index < 0) {
1365  BLI_assert(GS(pid->owner_id->name) == ID_OB);
1367  }
1368 
1369  const char *ext = ptcache_file_extension(pid);
1370  if (use_frame_number) {
1371  if (pid->cache->flag & PTCACHE_EXTERNAL) {
1372  if (pid->cache->index >= 0) {
1374  filename_ext, MAX_PTCACHE_FILE - len, "_%06d_%02u%s", cfra, pid->stack_index, ext);
1375  }
1376  else {
1377  len += BLI_snprintf_rlen(filename_ext, MAX_PTCACHE_FILE - len, "_%06d%s", cfra, ext);
1378  }
1379  }
1380  else {
1382  filename_ext, MAX_PTCACHE_FILE - len, "_%06d_%02u%s", cfra, pid->stack_index, ext);
1383  }
1384  }
1385  else {
1386  if (pid->cache->flag & PTCACHE_EXTERNAL) {
1387  if (pid->cache->index >= 0) {
1389  filename_ext, MAX_PTCACHE_FILE - len, "_%02u%s", pid->stack_index, ext);
1390  }
1391  else {
1392  len += BLI_snprintf_rlen(filename_ext, MAX_PTCACHE_FILE - len, "%s", ext);
1393  }
1394  }
1395  else {
1397  filename_ext, MAX_PTCACHE_FILE - len, "_%02u%s", pid->stack_index, ext);
1398  }
1399  }
1400 
1401  return len;
1402 }
1403 
1404 static int ptcache_filename(
1405  PTCacheID *pid, char *filename, int cfra, const bool do_path, const bool do_ext)
1406 {
1407  int len = 0;
1408  char *idname;
1409  char *newname;
1410  filename[0] = '\0';
1411  newname = filename;
1412 
1413  if ((pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
1414  const char *blendfile_path = BKE_main_blendfile_path_from_global();
1415  if (blendfile_path[0] == '\0') {
1416  return 0; /* save blend file before using disk pointcache */
1417  }
1418  }
1419 
1420  /* start with temp dir */
1421  if (do_path) {
1422  len = ptcache_path(pid, filename);
1423  newname += len;
1424  }
1425  if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
1426  idname = (pid->owner_id->name + 2);
1427  /* convert chars to hex so they are always a valid filename */
1428  while ('\0' != *idname) {
1429  BLI_snprintf(newname, MAX_PTCACHE_FILE - len, "%02X", (unsigned int)(*idname++));
1430  newname += 2;
1431  len += 2;
1432  }
1433  }
1434  else {
1435  int temp = (int)strlen(pid->cache->name);
1436  strcpy(newname, pid->cache->name);
1437  newname += temp;
1438  len += temp;
1439  }
1440 
1441  if (do_ext) {
1442  len += ptcache_filename_ext_append(pid, filename, (size_t)len, true, cfra);
1443  }
1444 
1445  return len; /* make sure the above string is always 16 chars */
1446 }
1447 
1451 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
1452 {
1453  PTCacheFile *pf;
1454  FILE *fp = NULL;
1455  char filepath[MAX_PTCACHE_FILE];
1456 
1457 #ifndef DURIAN_POINTCACHE_LIB_OK
1458  /* don't allow writing for linked objects */
1459  if (pid->owner_id->lib && mode == PTCACHE_FILE_WRITE) {
1460  return NULL;
1461  }
1462 #endif
1463  if ((pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
1464  const char *blendfile_path = BKE_main_blendfile_path_from_global();
1465  if (blendfile_path[0] == '\0') {
1466  return NULL; /* save blend file before using disk pointcache */
1467  }
1468  }
1469 
1470  ptcache_filename(pid, filepath, cfra, true, true);
1471 
1472  if (mode == PTCACHE_FILE_READ) {
1473  fp = BLI_fopen(filepath, "rb");
1474  }
1475  else if (mode == PTCACHE_FILE_WRITE) {
1476  /* Will create the dir if needs be, same as "//textures" is created. */
1477  BLI_make_existing_file(filepath);
1478 
1479  fp = BLI_fopen(filepath, "wb");
1480  }
1481  else if (mode == PTCACHE_FILE_UPDATE) {
1482  BLI_make_existing_file(filepath);
1483  fp = BLI_fopen(filepath, "rb+");
1484  }
1485 
1486  if (!fp) {
1487  return NULL;
1488  }
1489 
1490  pf = MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
1491  pf->fp = fp;
1492  pf->old_format = 0;
1493  pf->frame = cfra;
1494 
1495  return pf;
1496 }
1498 {
1499  if (pf) {
1500  fclose(pf->fp);
1501  MEM_freeN(pf);
1502  }
1503 }
1504 
1505 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
1506 {
1507  int r = 0;
1508  unsigned char compressed = 0;
1509  size_t in_len;
1510 #ifdef WITH_LZO
1511  size_t out_len = len;
1512 #endif
1513  unsigned char *in;
1514  unsigned char *props = MEM_callocN(sizeof(char[16]), "tmp");
1515 
1516  ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
1517  if (compressed) {
1518  unsigned int size;
1519  ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1520  in_len = (size_t)size;
1521  if (in_len == 0) {
1522  /* do nothing */
1523  }
1524  else {
1525  in = (unsigned char *)MEM_callocN(sizeof(unsigned char) * in_len,
1526  "pointcache_compressed_buffer");
1527  ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
1528 #ifdef WITH_LZO
1529  if (compressed == 1) {
1530  r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
1531  }
1532 #endif
1533 #ifdef WITH_LZMA
1534  if (compressed == 2) {
1535  size_t sizeOfIt;
1536  size_t leni = in_len, leno = len;
1537  ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1538  sizeOfIt = (size_t)size;
1539  ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
1540  r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
1541  }
1542 #endif
1543  MEM_freeN(in);
1544  }
1545  }
1546  else {
1547  ptcache_file_read(pf, result, len, sizeof(unsigned char));
1548  }
1549 
1550  MEM_freeN(props);
1551 
1552  return r;
1553 }
1555  PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
1556 {
1557  int r = 0;
1558  unsigned char compressed = 0;
1559  size_t out_len = 0;
1560  unsigned char *props = MEM_callocN(sizeof(char[16]), "tmp");
1561  size_t sizeOfIt = 5;
1562 
1563  (void)mode; /* unused when building w/o compression */
1564 
1565 #ifdef WITH_LZO
1566  out_len = LZO_OUT_LEN(in_len);
1567  if (mode == 1) {
1568  LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
1569 
1570  r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
1571  if (!(r == LZO_E_OK) || (out_len >= in_len)) {
1572  compressed = 0;
1573  }
1574  else {
1575  compressed = 1;
1576  }
1577  }
1578 #endif
1579 #ifdef WITH_LZMA
1580  if (mode == 2) {
1581 
1582  r = LzmaCompress(out,
1583  &out_len,
1584  in,
1585  in_len, /* assume sizeof(char)==1.... */
1586  props,
1587  &sizeOfIt,
1588  5,
1589  1 << 24,
1590  3,
1591  0,
1592  2,
1593  32,
1594  2);
1595 
1596  if (!(r == SZ_OK) || (out_len >= in_len)) {
1597  compressed = 0;
1598  }
1599  else {
1600  compressed = 2;
1601  }
1602  }
1603 #endif
1604 
1605  ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
1606  if (compressed) {
1607  unsigned int size = out_len;
1608  ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
1609  ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
1610  }
1611  else {
1612  ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
1613  }
1614 
1615  if (compressed == 2) {
1616  unsigned int size = sizeOfIt;
1617  ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
1618  ptcache_file_write(pf, props, size, sizeof(unsigned char));
1619  }
1620 
1621  MEM_freeN(props);
1622 
1623  return r;
1624 }
1625 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
1626 {
1627  return (fread(f, size, tot, pf->fp) == tot);
1628 }
1629 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size)
1630 {
1631  return (fwrite(f, size, tot, pf->fp) == tot);
1632 }
1634 {
1635  int i;
1636 
1637  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1638  if ((pf->data_types & (1 << i)) &&
1639  !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) {
1640  return 0;
1641  }
1642  }
1643 
1644  return 1;
1645 }
1647 {
1648  int i;
1649 
1650  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1651  if ((pf->data_types & (1 << i)) &&
1652  !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) {
1653  return 0;
1654  }
1655  }
1656 
1657  return 1;
1658 }
1660 {
1661  unsigned int typeflag = 0;
1662  int error = 0;
1663  char bphysics[8];
1664 
1665  pf->data_types = 0;
1666 
1667  if (fread(bphysics, sizeof(char), 8, pf->fp) != 8) {
1668  error = 1;
1669  }
1670 
1671  if (!error && !STREQLEN(bphysics, "BPHYSICS", 8)) {
1672  error = 1;
1673  }
1674 
1675  if (!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp)) {
1676  error = 1;
1677  }
1678 
1679  pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
1680  pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
1681 
1682  /* if there was an error set file as it was */
1683  if (error) {
1684  BLI_fseek(pf->fp, 0, SEEK_SET);
1685  }
1686 
1687  return !error;
1688 }
1690 {
1691  const char *bphysics = "BPHYSICS";
1692  unsigned int typeflag = pf->type + pf->flag;
1693 
1694  if (fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) {
1695  return 0;
1696  }
1697 
1698  if (!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp)) {
1699  return 0;
1700  }
1701 
1702  return 1;
1703 }
1704 
1705 /* Data pointer handling. */
1706 
1707 int BKE_ptcache_data_size(int data_type)
1708 {
1709  return ptcache_data_size[data_type];
1710 }
1711 
1713 {
1714  int data_types = pf->data_types;
1715 
1716  pf->cur[BPHYS_DATA_INDEX] = (data_types & (1 << BPHYS_DATA_INDEX)) ? &pf->data.index : NULL;
1717  pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1 << BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL;
1718  pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1 << BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL;
1719  pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1 << BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL;
1720  pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1 << BPHYS_DATA_AVELOCITY)) ? &pf->data.ave :
1721  NULL;
1722  pf->cur[BPHYS_DATA_SIZE] = (data_types & (1 << BPHYS_DATA_SIZE)) ? &pf->data.size : NULL;
1723  pf->cur[BPHYS_DATA_TIMES] = (data_types & (1 << BPHYS_DATA_TIMES)) ? &pf->data.times : NULL;
1724  pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1 << BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL;
1725 }
1726 
1727 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
1728 {
1729  if (pm->totpoint > 0 && pm->data[BPHYS_DATA_INDEX]) {
1730  unsigned int *data = pm->data[BPHYS_DATA_INDEX];
1731  unsigned int mid, low = 0, high = pm->totpoint - 1;
1732 
1733  if (index < *data || index > *(data + high)) {
1734  return -1;
1735  }
1736 
1737  /* check simple case for continuous indexes first */
1738  if (index - *data < high && data[index - *data] == index) {
1739  return index - *data;
1740  }
1741 
1742  while (low <= high) {
1743  mid = (low + high) / 2;
1744 
1745  if (data[mid] > index) {
1746  high = mid - 1;
1747  }
1748  else if (data[mid] < index) {
1749  low = mid + 1;
1750  }
1751  else {
1752  return mid;
1753  }
1754  }
1755 
1756  return -1;
1757  }
1758 
1759  return (index < pm->totpoint ? index : -1);
1760 }
1761 
1763 {
1764  int data_types = pm->data_types;
1765  int i;
1766 
1767  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1768  cur[i] = ((data_types & (1 << i)) ? pm->data[i] : NULL);
1769  }
1770 }
1771 
1773 {
1774  int i;
1775 
1776  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1777  if (cur[i]) {
1778  cur[i] = (char *)cur[i] + ptcache_data_size[i];
1779  }
1780  }
1781 }
1783 {
1784  int data_types = pm->data_types;
1785  int i, index = BKE_ptcache_mem_index_find(pm, point_index);
1786 
1787  if (index < 0) {
1788  /* Can't give proper location without reallocation, so don't give any location.
1789  * Some points will be cached improperly, but this only happens with simulation
1790  * steps bigger than cache->step, so the cache has to be recalculated anyways
1791  * at some point.
1792  */
1793  return 0;
1794  }
1795 
1796  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1797  cur[i] = (data_types & (1 << i)) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL;
1798  }
1799 
1800  return 1;
1801 }
1803 {
1804  int data_types = pm->data_types;
1805  int totpoint = pm->totpoint;
1806  int i;
1807 
1808  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1809  if (data_types & (1 << i)) {
1810  pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
1811  }
1812  }
1813 }
1815 {
1816  void **data = pm->data;
1817  int i;
1818 
1819  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1820  if (data[i]) {
1821  MEM_freeN(data[i]);
1822  }
1823  }
1824 }
1825 static void ptcache_data_copy(void *from[], void *to[])
1826 {
1827  int i;
1828  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1829  /* NOTE: durian file 03.4b_comp crashes if to[i] is not tested
1830  * its NULL, not sure if this should be fixed elsewhere but for now its needed */
1831  if (from[i] && to[i]) {
1832  memcpy(to[i], from[i], ptcache_data_size[i]);
1833  }
1834  }
1835 }
1836 
1838 {
1839  PTCacheExtra *extra = pm->extradata.first;
1840 
1841  if (extra) {
1842  for (; extra; extra = extra->next) {
1843  if (extra->data) {
1844  MEM_freeN(extra->data);
1845  }
1846  }
1847 
1848  BLI_freelistN(&pm->extradata);
1849  }
1850 }
1851 
1853 {
1854  ptcache_data_free(pm);
1855  ptcache_extra_free(pm);
1856 }
1857 
1859 {
1860  if (pid->type == PTCACHE_TYPE_SOFTBODY) {
1861  return sizeof(float[6]);
1862  }
1863  if (pid->type == PTCACHE_TYPE_PARTICLES) {
1864  return sizeof(ParticleKey);
1865  }
1866  if (pid->type == PTCACHE_TYPE_CLOTH) {
1867  return sizeof(float[9]);
1868  }
1869 
1870  return 0;
1871 }
1872 
1873 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
1874 {
1875  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
1876  int cfra1 = frame, cfra2 = frame + 1;
1877 
1878  while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) {
1879  cfra1--;
1880  }
1881 
1882  if (cfra1 < pid->cache->startframe) {
1883  cfra1 = 0;
1884  }
1885 
1886  while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) {
1887  cfra2++;
1888  }
1889 
1890  if (cfra2 > pid->cache->endframe) {
1891  cfra2 = 0;
1892  }
1893 
1894  if (cfra1 && !cfra2) {
1895  *fra1 = 0;
1896  *fra2 = cfra1;
1897  }
1898  else {
1899  *fra1 = cfra1;
1900  *fra2 = cfra2;
1901  }
1902  }
1903  else if (pid->cache->mem_cache.first) {
1904  PTCacheMem *pm = pid->cache->mem_cache.first;
1905  PTCacheMem *pm2 = pid->cache->mem_cache.last;
1906 
1907  while (pm->next && pm->next->frame <= frame) {
1908  pm = pm->next;
1909  }
1910 
1911  if (pm2->frame < frame) {
1912  pm2 = NULL;
1913  }
1914  else {
1915  while (pm2->prev && pm2->prev->frame > frame) {
1916  pm2 = pm2->prev;
1917  }
1918  }
1919 
1920  if (!pm2) {
1921  *fra1 = 0;
1922  *fra2 = pm->frame;
1923  }
1924  else {
1925  *fra1 = pm->frame;
1926  *fra2 = pm2->frame;
1927  }
1928  }
1929 }
1930 
1932 {
1934  PTCacheMem *pm = NULL;
1935  unsigned int i, error = 0;
1936 
1937  if (pf == NULL) {
1938  return NULL;
1939  }
1940 
1942  error = 1;
1943  }
1944 
1945  if (!error && (pf->type != pid->type || !pid->read_header(pf))) {
1946  error = 1;
1947  }
1948 
1949  if (!error) {
1950  pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1951 
1952  pm->totpoint = pf->totpoint;
1953  pm->data_types = pf->data_types;
1954  pm->frame = pf->frame;
1955 
1956  ptcache_data_alloc(pm);
1957 
1958  if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
1959  for (i = 0; i < BPHYS_TOT_DATA; i++) {
1960  unsigned int out_len = pm->totpoint * ptcache_data_size[i];
1961  if (pf->data_types & (1 << i)) {
1962  ptcache_file_compressed_read(pf, (unsigned char *)(pm->data[i]), out_len);
1963  }
1964  }
1965  }
1966  else {
1967  void *cur[BPHYS_TOT_DATA];
1970 
1971  for (i = 0; i < pm->totpoint; i++) {
1972  if (!ptcache_file_data_read(pf)) {
1973  error = 1;
1974  break;
1975  }
1976  ptcache_data_copy(pf->cur, cur);
1978  }
1979  }
1980  }
1981 
1982  if (!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) {
1983  unsigned int extratype = 0;
1984 
1985  while (ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) {
1986  PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata");
1987 
1988  extra->type = extratype;
1989 
1990  ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int));
1991 
1992  extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type],
1993  "Pointcache extradata->data");
1994 
1995  if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
1997  (unsigned char *)(extra->data),
1998  extra->totdata * ptcache_extra_datasize[extra->type]);
1999  }
2000  else {
2001  ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
2002  }
2003 
2004  BLI_addtail(&pm->extradata, extra);
2005  }
2006  }
2007 
2008  if (error && pm) {
2009  ptcache_mem_clear(pm);
2010  MEM_freeN(pm);
2011  pm = NULL;
2012  }
2013 
2015 
2016  if (error && G.debug & G_DEBUG) {
2017  printf("Error reading from disk cache\n");
2018  }
2019 
2020  return pm;
2021 }
2023 {
2024  PTCacheFile *pf = NULL;
2025  unsigned int i, error = 0;
2026 
2028 
2030 
2031  if (pf == NULL) {
2032  if (G.debug & G_DEBUG) {
2033  printf("Error opening disk cache file for writing\n");
2034  }
2035  return 0;
2036  }
2037 
2038  pf->data_types = pm->data_types;
2039  pf->totpoint = pm->totpoint;
2040  pf->type = pid->type;
2041  pf->flag = 0;
2042 
2043  if (pm->extradata.first) {
2044  pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
2045  }
2046 
2047  if (pid->cache->compression) {
2048  pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
2049  }
2050 
2052  error = 1;
2053  }
2054 
2055  if (!error) {
2056  if (pid->cache->compression) {
2057  for (i = 0; i < BPHYS_TOT_DATA; i++) {
2058  if (pm->data[i]) {
2059  unsigned int in_len = pm->totpoint * ptcache_data_size[i];
2060  unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4,
2061  "pointcache_lzo_buffer");
2063  pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression);
2064  MEM_freeN(out);
2065  }
2066  }
2067  }
2068  else {
2069  void *cur[BPHYS_TOT_DATA];
2072 
2073  for (i = 0; i < pm->totpoint; i++) {
2074  ptcache_data_copy(cur, pf->cur);
2075  if (!ptcache_file_data_write(pf)) {
2076  error = 1;
2077  break;
2078  }
2080  }
2081  }
2082  }
2083 
2084  if (!error && pm->extradata.first) {
2085  PTCacheExtra *extra = pm->extradata.first;
2086 
2087  for (; extra; extra = extra->next) {
2088  if (extra->data == NULL || extra->totdata == 0) {
2089  continue;
2090  }
2091 
2092  ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
2093  ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
2094 
2095  if (pid->cache->compression) {
2096  unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
2097  unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4,
2098  "pointcache_lzo_buffer");
2100  pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression);
2101  MEM_freeN(out);
2102  }
2103  else {
2104  ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
2105  }
2106  }
2107  }
2108 
2110 
2111  if (error && G.debug & G_DEBUG) {
2112  printf("Error writing to disk cache\n");
2113  }
2114 
2115  return error == 0;
2116 }
2117 
2118 static int ptcache_read_stream(PTCacheID *pid, int cfra)
2119 {
2121  int error = 0;
2122 
2123  if (pid->read_stream == NULL) {
2124  return 0;
2125  }
2126 
2127  if (pf == NULL) {
2128  if (G.debug & G_DEBUG) {
2129  printf("Error opening disk cache file for reading\n");
2130  }
2131  return 0;
2132  }
2133 
2135  pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file");
2136  error = 1;
2137  }
2138  else if (pf->type != pid->type) {
2139  pid->error(pid->owner_id, pid->calldata, "Point cache file has wrong type");
2140  error = 1;
2141  }
2142  else if (!pid->read_header(pf)) {
2143  pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file header");
2144  error = 1;
2145  }
2146  else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) {
2147  pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh");
2148  error = 1;
2149  }
2150 
2151  if (!error) {
2153 
2154  /* We have stream reading here. */
2155  if (!pid->read_stream(pf, pid->calldata)) {
2156  pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file data");
2157  error = 1;
2158  }
2159  }
2160 
2162 
2163  return error == 0;
2164 }
2165 
2166 static int ptcache_read(PTCacheID *pid, int cfra)
2167 {
2168  PTCacheMem *pm = NULL;
2169  int i;
2170  int *index = &i;
2171 
2172  /* get a memory cache to read from */
2173  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2174  pm = ptcache_disk_frame_to_mem(pid, cfra);
2175  }
2176  else {
2177  pm = pid->cache->mem_cache.first;
2178 
2179  while (pm && pm->frame != cfra) {
2180  pm = pm->next;
2181  }
2182  }
2183 
2184  /* read the cache */
2185  if (pm) {
2186  int totpoint = pm->totpoint;
2187 
2188  if ((pid->data_types & (1 << BPHYS_DATA_INDEX)) == 0) {
2189  int pid_totpoint = pid->totpoint(pid->calldata, cfra);
2190 
2191  if (totpoint != pid_totpoint) {
2192  pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh");
2193  totpoint = MIN2(totpoint, pid_totpoint);
2194  }
2195  }
2196 
2197  void *cur[BPHYS_TOT_DATA];
2199 
2200  for (i = 0; i < totpoint; i++) {
2201  if (pm->data_types & (1 << BPHYS_DATA_INDEX)) {
2202  index = cur[BPHYS_DATA_INDEX];
2203  }
2204 
2205  pid->read_point(*index, pid->calldata, cur, (float)pm->frame, NULL);
2206 
2208  }
2209 
2210  if (pid->read_extra_data && pm->extradata.first) {
2211  pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
2212  }
2213 
2214  /* clean up temporary memory cache */
2215  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2216  ptcache_mem_clear(pm);
2217  MEM_freeN(pm);
2218  }
2219  }
2220 
2221  return 1;
2222 }
2223 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
2224 {
2225  PTCacheMem *pm = NULL;
2226  int i;
2227  int *index = &i;
2228 
2229  /* get a memory cache to read from */
2230  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2231  pm = ptcache_disk_frame_to_mem(pid, cfra2);
2232  }
2233  else {
2234  pm = pid->cache->mem_cache.first;
2235 
2236  while (pm && pm->frame != cfra2) {
2237  pm = pm->next;
2238  }
2239  }
2240 
2241  /* read the cache */
2242  if (pm) {
2243  int totpoint = pm->totpoint;
2244 
2245  if ((pid->data_types & (1 << BPHYS_DATA_INDEX)) == 0) {
2246  int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra);
2247 
2248  if (totpoint != pid_totpoint) {
2249  pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh");
2250  totpoint = MIN2(totpoint, pid_totpoint);
2251  }
2252  }
2253 
2254  void *cur[BPHYS_TOT_DATA];
2256 
2257  for (i = 0; i < totpoint; i++) {
2258  if (pm->data_types & (1 << BPHYS_DATA_INDEX)) {
2259  index = cur[BPHYS_DATA_INDEX];
2260  }
2261 
2262  pid->interpolate_point(*index, pid->calldata, cur, cfra, (float)cfra1, (float)cfra2, NULL);
2264  }
2265 
2266  if (pid->interpolate_extra_data && pm->extradata.first) {
2267  pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
2268  }
2269 
2270  /* clean up temporary memory cache */
2271  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2272  ptcache_mem_clear(pm);
2273  MEM_freeN(pm);
2274  }
2275  }
2276 
2277  return 1;
2278 }
2279 /* reads cache from disk or memory */
2280 int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
2281 {
2282  int cfrai = (int)floor(cfra), cfra1 = 0, cfra2 = 0;
2283  int ret = 0;
2284 
2285  /* nothing to read to */
2286  if (pid->totpoint(pid->calldata, cfrai) == 0) {
2287  return 0;
2288  }
2289 
2290  if (pid->cache->flag & PTCACHE_READ_INFO) {
2291  pid->cache->flag &= ~PTCACHE_READ_INFO;
2292  ptcache_read(pid, 0);
2293  }
2294 
2295  /* first check if we have the actual frame cached */
2296  if (cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai)) {
2297  cfra1 = cfrai;
2298  }
2299 
2300  /* no exact cache frame found so try to find cached frames around cfra */
2301  if (cfra1 == 0) {
2302  ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
2303  }
2304 
2305  if (cfra1 == 0 && cfra2 == 0) {
2306  return 0;
2307  }
2308 
2309  /* don't read old cache if already simulated past cached frame */
2310  if (no_extrapolate_old) {
2311  if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) {
2312  return 0;
2313  }
2314  if (cfra1 && cfra1 == cfra2) {
2315  return 0;
2316  }
2317  }
2318  else {
2319  /* avoid calling interpolate between the same frame values */
2320  if (cfra1 && cfra1 == cfra2) {
2321  cfra1 = 0;
2322  }
2323  }
2324 
2325  if (cfra1) {
2326  if (pid->read_stream) {
2327  if (!ptcache_read_stream(pid, cfra1)) {
2328  return 0;
2329  }
2330  }
2331  else if (pid->read_point) {
2332  ptcache_read(pid, cfra1);
2333  }
2334  }
2335 
2336  if (cfra2) {
2337  if (pid->read_stream) {
2338  if (!ptcache_read_stream(pid, cfra2)) {
2339  return 0;
2340  }
2341  }
2342  else if (pid->read_point) {
2343  if (cfra1 && cfra2 && pid->interpolate_point) {
2344  ptcache_interpolate(pid, cfra, cfra1, cfra2);
2345  }
2346  else {
2347  ptcache_read(pid, cfra2);
2348  }
2349  }
2350  }
2351 
2352  if (cfra1) {
2354  }
2355  else if (cfra2) {
2357  pid->cache->simframe = cfra2;
2358  }
2359 
2360  cfrai = (int)cfra;
2361  /* clear invalid cache frames so that better stuff can be simulated */
2362  if (pid->cache->flag & PTCACHE_OUTDATED) {
2364  }
2365  else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
2366  if (cfra <= pid->cache->last_exact) {
2367  pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2368  }
2369 
2371  }
2372 
2373  return ret;
2374 }
2375 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
2376 {
2377  PTCacheFile *pf = NULL;
2378  int error = 0;
2379 
2381 
2382  pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
2383 
2384  if (pf == NULL) {
2385  if (G.debug & G_DEBUG) {
2386  printf("Error opening disk cache file for writing\n");
2387  }
2388  return 0;
2389  }
2390 
2391  pf->data_types = pid->data_types;
2392  pf->totpoint = totpoint;
2393  pf->type = pid->type;
2394  pf->flag = 0;
2395 
2396  if (!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))) {
2397  error = 1;
2398  }
2399 
2400  if (!error && pid->write_stream) {
2401  pid->write_stream(pf, pid->calldata);
2402  }
2403 
2405 
2406  if (error && G.debug & G_DEBUG) {
2407  printf("Error writing to disk cache\n");
2408  }
2409 
2410  return error == 0;
2411 }
2412 
2413 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
2414 {
2415  PointCache *cache = pid->cache;
2416  PTCacheMem *pm = NULL, *pm2 = NULL;
2417  int totpoint = pid->totpoint(pid->calldata, cfra);
2418  int i, error = 0;
2419 
2420  pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2421 
2422  pm->totpoint = pid->totwrite(pid->calldata, cfra);
2423  pm->data_types = cfra ? pid->data_types : pid->info_types;
2424 
2425  ptcache_data_alloc(pm);
2426  void *cur[BPHYS_TOT_DATA];
2428 
2429  if (overwrite) {
2430  if (cache->flag & PTCACHE_DISK_CACHE) {
2431  int fra = cfra - 1;
2432 
2433  while (fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) {
2434  fra--;
2435  }
2436 
2437  pm2 = ptcache_disk_frame_to_mem(pid, fra);
2438  }
2439  else {
2440  pm2 = cache->mem_cache.last;
2441  }
2442  }
2443 
2444  if (pid->write_point) {
2445  for (i = 0; i < totpoint; i++) {
2446  int write = pid->write_point(i, pid->calldata, cur, cfra);
2447  if (write) {
2449 
2450  void *cur2[BPHYS_TOT_DATA];
2451  /* newly born particles have to be copied to previous cached frame */
2452  if (overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2, cur2)) {
2453  pid->write_point(i, pid->calldata, cur2, cfra);
2454  }
2455  }
2456  }
2457  }
2458 
2459  if (pid->write_extra_data) {
2460  pid->write_extra_data(pid->calldata, pm, cfra);
2461  }
2462 
2463  pm->frame = cfra;
2464 
2465  if (cache->flag & PTCACHE_DISK_CACHE) {
2466  error += !ptcache_mem_frame_to_disk(pid, pm);
2467 
2468  // if (pm) /* pm is always set */
2469  {
2470  ptcache_mem_clear(pm);
2471  MEM_freeN(pm);
2472  }
2473 
2474  if (pm2) {
2475  error += !ptcache_mem_frame_to_disk(pid, pm2);
2476  ptcache_mem_clear(pm2);
2477  MEM_freeN(pm2);
2478  }
2479  }
2480  else {
2481  BLI_addtail(&cache->mem_cache, pm);
2482  }
2483 
2484  return error;
2485 }
2486 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
2487 {
2488  PointCache *cache = pid->cache;
2489  int ofra = 0, efra = cache->endframe;
2490 
2491  /* always start from scratch on the first frame */
2492  if (cfra && cfra == cache->startframe) {
2494  cache->flag &= ~PTCACHE_REDO_NEEDED;
2495  return 1;
2496  }
2497 
2498  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2499  if (cfra == 0 && cache->startframe > 0) {
2500  return 1;
2501  }
2502 
2503  /* find last cached frame */
2504  while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) {
2505  efra--;
2506  }
2507 
2508  /* find second last cached frame */
2509  ofra = efra - 1;
2510  while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) {
2511  ofra--;
2512  }
2513  }
2514  else {
2515  PTCacheMem *pm = cache->mem_cache.last;
2516  /* don't write info file in memory */
2517  if (cfra == 0) {
2518  return 0;
2519  }
2520 
2521  if (pm == NULL) {
2522  return 1;
2523  }
2524 
2525  efra = pm->frame;
2526  ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
2527  }
2528 
2529  if (efra >= cache->startframe && cfra > efra) {
2530  if (ofra >= cache->startframe && efra - ofra < cache->step) {
2531  /* overwrite previous frame */
2533  *overwrite = 1;
2534  }
2535  return 1;
2536  }
2537 
2538  return 0;
2539 }
2540 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
2541 {
2542  PointCache *cache = pid->cache;
2543  if (!pid->totpoint) {
2544  /* This happens when `pid->type == PTCACHE_TYPE_SMOKE_DOMAIN`. The fluid system does not
2545  * actually use the pointcache anymore for caching. */
2546  return 0;
2547  }
2548 
2549  int totpoint = pid->totpoint(pid->calldata, cfra);
2550  int overwrite = 0, error = 0;
2551 
2552  if (totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) {
2553  return 0;
2554  }
2555 
2556  if (ptcache_write_needed(pid, cfra, &overwrite) == 0) {
2557  return 0;
2558  }
2559 
2560  if (pid->write_stream) {
2561  ptcache_write_stream(pid, cfra, totpoint);
2562  }
2563  else if (pid->write_point) {
2564  error += ptcache_write(pid, cfra, overwrite);
2565  }
2566 
2567  /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
2568  if (cfra - cache->last_exact == 1 || cfra == cache->startframe) {
2569  cache->last_exact = cfra;
2570  cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2571  }
2572  /* Don't mark skipped when writing info file (frame 0) */
2573  else if (cfra) {
2574  cache->flag |= PTCACHE_FRAMES_SKIPPED;
2575  }
2576 
2577  /* Update timeline cache display */
2578  if (cfra && cache->cached_frames) {
2579  cache->cached_frames[cfra - cache->startframe] = 1;
2580  }
2581 
2582  cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
2583 
2584  return !error;
2585 }
2586 /* you'll need to close yourself after!
2587  * mode - PTCACHE_CLEAR_ALL,
2588  */
2589 
2590 /* Clears & resets. */
2591 
2592 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
2593 {
2594  unsigned int len; /* store the length of the string */
2595  unsigned int sta, end;
2596 
2597  /* mode is same as fopen's modes */
2598  DIR *dir;
2599  struct dirent *de;
2600  char path[MAX_PTCACHE_PATH];
2601  char filename[MAX_PTCACHE_FILE];
2602  char path_full[MAX_PTCACHE_FILE];
2603  char ext[MAX_PTCACHE_PATH];
2604 
2605  if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) {
2606  return;
2607  }
2608 
2609  if (pid->cache->flag & PTCACHE_IGNORE_CLEAR) {
2610  return;
2611  }
2612 
2613  sta = pid->cache->startframe;
2614  end = pid->cache->endframe;
2615 
2616 #ifndef DURIAN_POINTCACHE_LIB_OK
2617  /* don't allow clearing for linked objects */
2618  if (pid->owner_id->lib) {
2619  return;
2620  }
2621 #endif
2622 
2623  /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
2624  switch (mode) {
2625  case PTCACHE_CLEAR_ALL:
2626  case PTCACHE_CLEAR_BEFORE:
2627  case PTCACHE_CLEAR_AFTER:
2628  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2629  ptcache_path(pid, path);
2630 
2631  dir = opendir(path);
2632  if (dir == NULL) {
2633  return;
2634  }
2635 
2636  len = ptcache_filename(pid, filename, cfra, false, false); /* no path */
2637  /* append underscore terminator to ensure we don't match similar names
2638  * from objects whose names start with the same prefix
2639  */
2640  if (len < sizeof(filename) - 2) {
2641  BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len);
2642  len += 1;
2643  }
2644 
2645  ptcache_filename_ext_append(pid, ext, 0, false, 0);
2646 
2647  while ((de = readdir(dir)) != NULL) {
2648  if (strstr(de->d_name, ext)) { /* Do we have the right extension? */
2649  if (STREQLEN(filename, de->d_name, len)) { /* Do we have the right prefix. */
2650  if (mode == PTCACHE_CLEAR_ALL) {
2651  pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2652  BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2653  BLI_delete(path_full, false, false);
2654  }
2655  else {
2656  /* read the number of the file */
2657  const int frame = ptcache_frame_from_filename(de->d_name, ext);
2658 
2659  if (frame != -1) {
2660  if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
2661  (mode == PTCACHE_CLEAR_AFTER && frame > cfra)) {
2662  BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2663  BLI_delete(path_full, false, false);
2664  if (pid->cache->cached_frames && frame >= sta && frame <= end) {
2665  pid->cache->cached_frames[frame - sta] = 0;
2666  }
2667  }
2668  }
2669  }
2670  }
2671  }
2672  }
2673  closedir(dir);
2674 
2675  if (mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames) {
2676  memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2677  }
2678  }
2679  else {
2680  PTCacheMem *pm = pid->cache->mem_cache.first;
2681  PTCacheMem *link = NULL;
2682 
2683  if (mode == PTCACHE_CLEAR_ALL) {
2684  /* We want startframe if the cache starts before zero. */
2685  pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2686  for (; pm; pm = pm->next) {
2687  ptcache_mem_clear(pm);
2688  }
2689  BLI_freelistN(&pid->cache->mem_cache);
2690 
2691  if (pid->cache->cached_frames) {
2692  memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2693  }
2694  }
2695  else {
2696  while (pm) {
2697  if ((mode == PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
2698  (mode == PTCACHE_CLEAR_AFTER && pm->frame > cfra)) {
2699  link = pm;
2700  if (pid->cache->cached_frames && pm->frame >= sta && pm->frame <= end) {
2701  pid->cache->cached_frames[pm->frame - sta] = 0;
2702  }
2703  ptcache_mem_clear(pm);
2704  pm = pm->next;
2705  BLI_freelinkN(&pid->cache->mem_cache, link);
2706  }
2707  else {
2708  pm = pm->next;
2709  }
2710  }
2711  }
2712  }
2713  break;
2714 
2715  case PTCACHE_CLEAR_FRAME:
2716  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2717  if (BKE_ptcache_id_exist(pid, cfra)) {
2718  ptcache_filename(pid, filename, cfra, true, true); /* no path */
2719  BLI_delete(filename, false, false);
2720  }
2721  }
2722  else {
2723  PTCacheMem *pm = pid->cache->mem_cache.first;
2724 
2725  for (; pm; pm = pm->next) {
2726  if (pm->frame == cfra) {
2727  ptcache_mem_clear(pm);
2728  BLI_freelinkN(&pid->cache->mem_cache, pm);
2729  break;
2730  }
2731  }
2732  }
2733  if (pid->cache->cached_frames && cfra >= sta && cfra <= end) {
2734  pid->cache->cached_frames[cfra - sta] = 0;
2735  }
2736  break;
2737  }
2738 
2740 }
2741 
2742 bool BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
2743 {
2744  if (!pid->cache) {
2745  return false;
2746  }
2747 
2748  if (cfra < pid->cache->startframe || cfra > pid->cache->endframe) {
2749  return false;
2750  }
2751 
2752  if (pid->cache->cached_frames && pid->cache->cached_frames[cfra - pid->cache->startframe] == 0) {
2753  return false;
2754  }
2755 
2756  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2757  char filename[MAX_PTCACHE_FILE];
2758 
2759  ptcache_filename(pid, filename, cfra, true, true);
2760 
2761  return BLI_exists(filename);
2762  }
2763 
2764  PTCacheMem *pm = pid->cache->mem_cache.first;
2765 
2766  for (; pm; pm = pm->next) {
2767  if (pm->frame == cfra) {
2768  return true;
2769  }
2770  }
2771  return false;
2772 }
2774  PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
2775 {
2776  /* Object *ob; */ /* UNUSED */
2777  PointCache *cache;
2778  /* float offset; unused for now */
2779  float time, nexttime;
2780 
2781  /* TODO: this has to be sorted out once bsystem_time gets redone, */
2782  /* now caches can handle interpolating etc. too - jahka */
2783 
2784  /* time handling for point cache:
2785  * - simulation time is scaled by result of bsystem_time
2786  * - for offsetting time only time offset is taken into account, since
2787  * that's always the same and can't be animated. a timeoffset which
2788  * varies over time is not simple to support.
2789  * - field and motion blur offsets are currently ignored, proper solution
2790  * is probably to interpolate results from two frames for that ..
2791  */
2792 
2793  cache = pid->cache;
2794 
2795  if (timescale) {
2797  nexttime = BKE_scene_frame_to_ctime(scene, scene->r.cfra + 1);
2798 
2799  *timescale = MAX2(nexttime - time, 0.0f);
2800  }
2801 
2802  if (startframe && endframe) {
2803  *startframe = cache->startframe;
2804  *endframe = cache->endframe;
2805  }
2806 
2807  /* verify cached_frames array is up to date */
2808  if (cache->cached_frames) {
2809  if (cache->cached_frames_len != (cache->endframe - cache->startframe + 1)) {
2810  MEM_freeN(cache->cached_frames);
2811  cache->cached_frames = NULL;
2812  cache->cached_frames_len = 0;
2813  }
2814  }
2815 
2816  if (cache->cached_frames == NULL && cache->endframe > cache->startframe) {
2817  unsigned int sta = cache->startframe;
2818  unsigned int end = cache->endframe;
2819 
2820  cache->cached_frames_len = cache->endframe - cache->startframe + 1;
2821  cache->cached_frames = MEM_callocN(sizeof(char) * cache->cached_frames_len,
2822  "cached frames array");
2823 
2824  if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2825  /* mode is same as fopen's modes */
2826  DIR *dir;
2827  struct dirent *de;
2828  char path[MAX_PTCACHE_PATH];
2829  char filename[MAX_PTCACHE_FILE];
2830  char ext[MAX_PTCACHE_PATH];
2831  unsigned int len; /* store the length of the string */
2832 
2833  ptcache_path(pid, path);
2834 
2835  len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */
2836 
2837  dir = opendir(path);
2838  if (dir == NULL) {
2839  return;
2840  }
2841 
2842  ptcache_filename_ext_append(pid, ext, 0, false, 0);
2843 
2844  while ((de = readdir(dir)) != NULL) {
2845  if (strstr(de->d_name, ext)) { /* Do we have the right extension? */
2846  if (STREQLEN(filename, de->d_name, len)) { /* Do we have the right prefix. */
2847  /* read the number of the file */
2848  const int frame = ptcache_frame_from_filename(de->d_name, ext);
2849 
2850  if ((frame != -1) && (frame >= sta && frame <= end)) {
2851  cache->cached_frames[frame - sta] = 1;
2852  }
2853  }
2854  }
2855  }
2856  closedir(dir);
2857  }
2858  else {
2859  PTCacheMem *pm = pid->cache->mem_cache.first;
2860 
2861  while (pm) {
2862  if (pm->frame >= sta && pm->frame <= end) {
2863  cache->cached_frames[pm->frame - sta] = 1;
2864  }
2865  pm = pm->next;
2866  }
2867  }
2868  }
2869 }
2871 {
2872  PointCache *cache;
2873  int reset, clear, after;
2874 
2875  if (!pid->cache) {
2876  return 0;
2877  }
2878 
2879  cache = pid->cache;
2880  reset = 0;
2881  clear = 0;
2882  after = 0;
2883 
2884  if (mode == PTCACHE_RESET_DEPSGRAPH) {
2885  if (!(cache->flag & PTCACHE_BAKED)) {
2886 
2887  after = 1;
2888  }
2889 
2890  cache->flag |= PTCACHE_OUTDATED;
2891  }
2892  else if (mode == PTCACHE_RESET_BAKED) {
2893  cache->flag |= PTCACHE_OUTDATED;
2894  }
2895  else if (mode == PTCACHE_RESET_OUTDATED) {
2896  reset = 1;
2897 
2898  if (cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
2899  clear = 1;
2900  cache->flag &= ~PTCACHE_OUTDATED;
2901  }
2902  }
2903 
2904  if (reset) {
2905  BKE_ptcache_invalidate(cache);
2906  cache->flag &= ~PTCACHE_REDO_NEEDED;
2907 
2908  if (pid->type == PTCACHE_TYPE_CLOTH) {
2910  }
2911  else if (pid->type == PTCACHE_TYPE_SOFTBODY) {
2912  sbFreeSimulation(pid->calldata);
2913  }
2914  else if (pid->type == PTCACHE_TYPE_PARTICLES) {
2916  }
2917  else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) {
2919  }
2920  }
2921  if (clear) {
2923  }
2924  else if (after) {
2926  }
2927 
2928  return (reset || clear || after);
2929 }
2931 {
2932  PTCacheID pid;
2933  ParticleSystem *psys;
2934  ModifierData *md;
2935  int reset, skip;
2936 
2937  reset = 0;
2938  skip = 0;
2939 
2940  if (ob->soft) {
2941  BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
2942  reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2943  }
2944 
2945  for (psys = ob->particlesystem.first; psys; psys = psys->next) {
2946  /* children or just redo can be calculated without resetting anything */
2947  if (psys->recalc & ID_RECALC_PSYS_REDO || psys->recalc & ID_RECALC_PSYS_CHILD) {
2948  skip = 1;
2949  /* Baked cloth hair has to be checked too, because we don't want to reset */
2950  /* particles or cloth in that case -jahka */
2951  }
2952  else if (psys->clmd) {
2953  BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
2954  if (mode == PSYS_RESET_ALL ||
2955  !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) {
2956  reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2957  }
2958  else {
2959  skip = 1;
2960  }
2961  }
2962 
2963  if (skip == 0 && psys->part) {
2964  BKE_ptcache_id_from_particles(&pid, ob, psys);
2965  reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2966  }
2967  }
2968 
2969  for (md = ob->modifiers.first; md; md = md->next) {
2970  if (md->type == eModifierType_Cloth) {
2972  reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2973  }
2974  if (md->type == eModifierType_DynamicPaint) {
2976  if (pmd->canvas) {
2978 
2979  for (; surface; surface = surface->next) {
2981  reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2982  }
2983  }
2984  }
2985  if (md->type == eModifierType_Fluid) {
2986  FluidModifierData *fmd = (FluidModifierData *)md;
2987  FluidDomainSettings *fds = fmd->domain;
2988  if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fds &&
2990  BKE_ptcache_id_from_smoke(&pid, ob, fmd);
2991  reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2992  }
2993  }
2994  }
2995 
2997  if (ob->rigidbody_object) {
2999  }
3001  /* only flag as outdated, resetting should happen on start frame */
3002  pid.cache->flag |= PTCACHE_OUTDATED;
3003  }
3004 
3005  if (ob->type == OB_ARMATURE) {
3006  BIK_clear_cache(ob->pose);
3007  }
3008 
3009  return reset;
3010 }
3011 
3012 /* Point Cache handling */
3013 
3015 {
3016  PointCache *cache;
3017 
3018  cache = MEM_callocN(sizeof(PointCache), "PointCache");
3019  cache->startframe = 1;
3020  cache->endframe = 250;
3021  cache->step = 1;
3022  cache->index = -1;
3023 
3024  BLI_addtail(ptcaches, cache);
3025 
3026  return cache;
3027 }
3028 
3030 {
3031  PTCacheMem *pm = mem_cache->first;
3032 
3033  if (pm) {
3034  for (; pm; pm = pm->next) {
3035  ptcache_mem_clear(pm);
3036  }
3037 
3038  BLI_freelistN(mem_cache);
3039  }
3040 }
3042 {
3044  if (cache->edit && cache->free_edit) {
3045  cache->free_edit(cache->edit);
3046  }
3047  if (cache->cached_frames) {
3048  MEM_freeN(cache->cached_frames);
3049  }
3050  MEM_freeN(cache);
3051 }
3053 {
3054  PointCache *cache;
3055 
3056  while ((cache = BLI_pophead(ptcaches))) {
3057  BKE_ptcache_free(cache);
3058  }
3059 }
3060 
3061 static PointCache *ptcache_copy(PointCache *cache, const bool copy_data)
3062 {
3063  PointCache *ncache;
3064 
3065  ncache = MEM_dupallocN(cache);
3066 
3067  BLI_listbase_clear(&ncache->mem_cache);
3068 
3069  if (copy_data == false) {
3070  ncache->cached_frames = NULL;
3071  ncache->cached_frames_len = 0;
3072 
3073  /* flag is a mix of user settings and simulator/baking state */
3075  ncache->simframe = 0;
3076  }
3077  else {
3078  PTCacheMem *pm;
3079 
3080  for (pm = cache->mem_cache.first; pm; pm = pm->next) {
3081  PTCacheMem *pmn = MEM_dupallocN(pm);
3082  int i;
3083 
3084  for (i = 0; i < BPHYS_TOT_DATA; i++) {
3085  if (pmn->data[i]) {
3086  pmn->data[i] = MEM_dupallocN(pm->data[i]);
3087  }
3088  }
3089 
3090  BLI_addtail(&ncache->mem_cache, pmn);
3091  }
3092 
3093  if (ncache->cached_frames) {
3094  ncache->cached_frames = MEM_dupallocN(cache->cached_frames);
3095  }
3096  }
3097 
3098  /* hmm, should these be copied over instead? */
3099  ncache->edit = NULL;
3100 
3101  return ncache;
3102 }
3103 
3105  const ListBase *ptcaches_old,
3106  const int flag)
3107 {
3108  PointCache *cache = ptcaches_old->first;
3109 
3110  BLI_listbase_clear(ptcaches_new);
3111 
3112  for (; cache; cache = cache->next) {
3113  BLI_addtail(ptcaches_new, ptcache_copy(cache, (flag & LIB_ID_COPY_CACHES) != 0));
3114  }
3115 
3116  return ptcaches_new->first;
3117 }
3118 
3119 /* Disabled this code; this is being called on scene_update_tagged, and that in turn gets called on
3120  * every user action changing stuff, and then it runs a complete bake??? (ton) */
3121 
3122 /* Baking */
3123 
3125 {
3126  PTCacheBaker baker;
3127 
3128  memset(&baker, 0, sizeof(baker));
3129  baker.bmain = bmain;
3130  baker.scene = scene;
3131  baker.view_layer = view_layer;
3132  baker.bake = 0;
3133  baker.render = 0;
3134  baker.anim_init = 0;
3136 
3137  BKE_ptcache_bake(&baker);
3138 }
3139 
3140 static void ptcache_dt_to_str(char *str, double dtime)
3141 {
3142  if (dtime > 60.0) {
3143  if (dtime > 3600.0) {
3144  sprintf(
3145  str, "%ih %im %is", (int)(dtime / 3600), ((int)(dtime / 60)) % 60, ((int)dtime) % 60);
3146  }
3147  else {
3148  sprintf(str, "%im %is", ((int)(dtime / 60)) % 60, ((int)dtime) % 60);
3149  }
3150  }
3151  else {
3152  sprintf(str, "%is", ((int)dtime) % 60);
3153  }
3154 }
3155 
3157 {
3158  Scene *scene = baker->scene;
3159  ViewLayer *view_layer = baker->view_layer;
3160  struct Depsgraph *depsgraph = baker->depsgraph;
3161  Scene *sce_iter; /* SETLOOPER macro only */
3162  Base *base;
3163  ListBase pidlist;
3164  PTCacheID *pid = &baker->pid;
3165  PointCache *cache = NULL;
3166  float frameleno = scene->r.framelen;
3167  int cfrao = scene->r.cfra;
3168  int startframe = MAXFRAME, endframe = baker->anim_init ? scene->r.sfra : scene->r.cfra;
3169  int bake = baker->bake;
3170  int render = baker->render;
3171 
3172  G.is_break = false;
3173 
3174  /* set caches to baking mode and figure out start frame */
3175  if (pid->owner_id) {
3176  /* cache/bake a single object */
3177  cache = pid->cache;
3178  if ((cache->flag & PTCACHE_BAKED) == 0) {
3179  if (pid->type == PTCACHE_TYPE_PARTICLES) {
3180  ParticleSystem *psys = pid->calldata;
3181 
3182  /* a bit confusing, could make this work better in the UI */
3183  if (psys->part->type == PART_EMITTER) {
3185  scene, pid->calldata, &cache->startframe, &cache->endframe);
3186  }
3187  }
3188  else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
3189  /* get all pids from the object and search for smoke low res */
3190  ListBase pidlist2;
3191  PTCacheID *pid2;
3192  BLI_assert(GS(pid->owner_id->name) == ID_OB);
3194  for (pid2 = pidlist2.first; pid2; pid2 = pid2->next) {
3195  if (pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
3196  if (pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) {
3197  if (bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) {
3199  }
3200  if (bake) {
3201  pid2->cache->flag |= PTCACHE_BAKING;
3202  pid2->cache->flag &= ~PTCACHE_BAKED;
3203  }
3204  }
3205  }
3206  }
3207  BLI_freelistN(&pidlist2);
3208  }
3209 
3210  if (bake || cache->flag & PTCACHE_REDO_NEEDED) {
3212  }
3213 
3214  startframe = MAX2(cache->last_exact, cache->startframe);
3215 
3216  if (bake) {
3217  endframe = cache->endframe;
3218  cache->flag |= PTCACHE_BAKING;
3219  }
3220  else {
3221  endframe = MIN2(endframe, cache->endframe);
3222  }
3223 
3224  cache->flag &= ~PTCACHE_BAKED;
3225  }
3226  }
3227  else {
3228  for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
3229  /* cache/bake everything in the scene */
3231 
3232  for (pid = pidlist.first; pid; pid = pid->next) {
3233  cache = pid->cache;
3234  if ((cache->flag & PTCACHE_BAKED) == 0) {
3235  if (pid->type == PTCACHE_TYPE_PARTICLES) {
3236  ParticleSystem *psys = (ParticleSystem *)pid->calldata;
3237  /* skip hair & keyed particles */
3238  if (psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED) {
3239  continue;
3240  }
3241 
3243  scene, pid->calldata, &cache->startframe, &cache->endframe);
3244  }
3245 
3246  /* XXX: workaround for regression introduced in ee3fadd, needs looking into. */
3247  if (pid->type == PTCACHE_TYPE_RIGIDBODY) {
3248  if ((cache->flag & PTCACHE_REDO_NEEDED ||
3249  (cache->flag & PTCACHE_SIMULATION_VALID) == 0) &&
3250  (render || bake)) {
3252  }
3253  }
3254  else if (((cache->flag & PTCACHE_BAKED) == 0) && (render || bake)) {
3256  }
3257 
3258  startframe = MIN2(startframe, cache->startframe);
3259 
3260  if (bake || render) {
3261  cache->flag |= PTCACHE_BAKING;
3262 
3263  if (bake) {
3264  endframe = MAX2(endframe, cache->endframe);
3265  }
3266  }
3267 
3268  cache->flag &= ~PTCACHE_BAKED;
3269  }
3270  }
3271  BLI_freelistN(&pidlist);
3272  }
3273  }
3274 
3275  scene->r.cfra = startframe;
3276  scene->r.framelen = 1.0;
3277 
3278  /* bake */
3279 
3280  bool use_timer = false;
3281  double stime, ptime, ctime, fetd;
3282  char run[32], cur[32], etd[32];
3283  int cancel = 0;
3284 
3285  stime = ptime = PIL_check_seconds_timer();
3286 
3287  for (int fr = scene->r.cfra; fr <= endframe; fr += baker->quick_step, scene->r.cfra = fr) {
3289 
3290  if (baker->update_progress) {
3291  float progress = ((float)(scene->r.cfra - startframe) / (float)(endframe - startframe));
3292  baker->update_progress(baker->bake_job, progress, &cancel);
3293  }
3294 
3295  if (G.background) {
3296  printf("bake: frame %d :: %d\n", scene->r.cfra, endframe);
3297  }
3298  else {
3299  ctime = PIL_check_seconds_timer();
3300 
3301  fetd = (ctime - ptime) * (endframe - scene->r.cfra) / baker->quick_step;
3302 
3303  if (use_timer || fetd > 60.0) {
3304  use_timer = true;
3305 
3306  ptcache_dt_to_str(cur, ctime - ptime);
3307  ptcache_dt_to_str(run, ctime - stime);
3308  ptcache_dt_to_str(etd, fetd);
3309 
3310  printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r",
3311  run,
3312  scene->r.cfra - startframe + 1,
3313  endframe - startframe + 1,
3314  ctime - ptime,
3315  etd);
3316  }
3317 
3318  ptime = ctime;
3319  }
3320 
3321  /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
3322  if (cancel || G.is_break) {
3323  break;
3324  }
3325 
3326  scene->r.cfra += 1;
3327  }
3328 
3329  if (use_timer) {
3330  /* start with newline because of \r above */
3332  printf("\nBake %s %s (%i frames simulated).\n",
3333  (cancel ? "canceled after" : "finished in"),
3334  run,
3335  scene->r.cfra - startframe);
3336  }
3337 
3338  /* clear baking flag */
3339  if (pid) {
3340  cache->flag &= ~(PTCACHE_BAKING | PTCACHE_REDO_NEEDED);
3341  cache->flag |= PTCACHE_SIMULATION_VALID;
3342  if (bake) {
3343  cache->flag |= PTCACHE_BAKED;
3344  /* write info file */
3345  if (cache->flag & PTCACHE_DISK_CACHE) {
3346  if (pid->type == PTCACHE_TYPE_PARTICLES) {
3347  /* Since writing this from outside the bake job, make sure the ParticleSystem and
3348  * PTCacheID is in a fully evaluated state. */
3349  PTCacheID pid_eval;
3350  Object *ob = (Object *)pid->owner_id;
3351  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
3352  ParticleSystem *psys = (ParticleSystem *)pid->calldata;
3353  ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
3354  BKE_ptcache_id_from_particles(&pid_eval, ob_eval, psys_eval);
3355  BKE_ptcache_write(&pid_eval, 0);
3356  }
3357  else {
3358  BKE_ptcache_write(pid, 0);
3359  }
3360  }
3361  }
3362  }
3363  else {
3364  for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
3366 
3367  for (pid = pidlist.first; pid; pid = pid->next) {
3368  /* skip hair particles */
3369  if (pid->type == PTCACHE_TYPE_PARTICLES &&
3370  ((ParticleSystem *)pid->calldata)->part->type == PART_HAIR) {
3371  continue;
3372  }
3373 
3374  cache = pid->cache;
3375 
3376  if (baker->quick_step > 1) {
3377  cache->flag &= ~(PTCACHE_BAKING | PTCACHE_OUTDATED);
3378  }
3379  else {
3380  cache->flag &= ~(PTCACHE_BAKING | PTCACHE_REDO_NEEDED);
3381  }
3382 
3383  cache->flag |= PTCACHE_SIMULATION_VALID;
3384 
3385  if (bake) {
3386  cache->flag |= PTCACHE_BAKED;
3387  if (cache->flag & PTCACHE_DISK_CACHE) {
3388  if (pid->type == PTCACHE_TYPE_PARTICLES) {
3389  /* Since writing this from outside the bake job, make sure the ParticleSystem and
3390  * PTCacheID is in a fully evaluated state. */
3391  PTCacheID pid_eval;
3392  Object *ob = (Object *)pid->owner_id;
3393  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
3394  ParticleSystem *psys = (ParticleSystem *)pid->calldata;
3395  ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
3396  BKE_ptcache_id_from_particles(&pid_eval, ob_eval, psys_eval);
3397  BKE_ptcache_write(&pid_eval, 0);
3398  }
3399  else {
3400  BKE_ptcache_write(pid, 0);
3401  }
3402  }
3403  }
3404  }
3405  BLI_freelistN(&pidlist);
3406  }
3407  }
3408 
3409  scene->r.framelen = frameleno;
3410  scene->r.cfra = cfrao;
3411 
3412  if (bake) { /* already on cfra unless baking */
3414  }
3415 
3416  /* TODO: call redraw all windows somehow */
3417 }
3418 
3419 /* Helpers */
3420 
3422 {
3423  PointCache *cache = pid->cache;
3424  PTCacheMem *pm = NULL;
3425  int baked = cache->flag & PTCACHE_BAKED;
3426  int cfra, sfra = cache->startframe, efra = cache->endframe;
3427 
3428  /* Remove possible bake flag to allow clear */
3429  cache->flag &= ~PTCACHE_BAKED;
3430 
3431  /* PTCACHE_DISK_CACHE flag was cleared already */
3433 
3434  /* restore possible bake flag */
3435  cache->flag |= baked;
3436 
3437  for (cfra = sfra; cfra <= efra; cfra++) {
3438  pm = ptcache_disk_frame_to_mem(pid, cfra);
3439 
3440  if (pm) {
3441  BLI_addtail(&pid->cache->mem_cache, pm);
3442  }
3443  }
3444 }
3446 {
3447  PointCache *cache = pid->cache;
3448  PTCacheMem *pm = cache->mem_cache.first;
3449  int baked = cache->flag & PTCACHE_BAKED;
3450 
3451  /* Remove possible bake flag to allow clear */
3452  cache->flag &= ~PTCACHE_BAKED;
3453 
3454  /* PTCACHE_DISK_CACHE flag was set already */
3456 
3457  /* restore possible bake flag */
3458  cache->flag |= baked;
3459 
3460  for (; pm; pm = pm->next) {
3461  if (ptcache_mem_frame_to_disk(pid, pm) == 0) {
3462  cache->flag &= ~PTCACHE_DISK_CACHE;
3463  break;
3464  }
3465  }
3466 
3467  /* write info file */
3468  if (cache->flag & PTCACHE_BAKED) {
3469  BKE_ptcache_write(pid, 0);
3470  }
3471 }
3473 {
3474  PointCache *cache = pid->cache;
3475  int last_exact = cache->last_exact;
3476  const char *blendfile_path = BKE_main_blendfile_path_from_global();
3477 
3478  if (blendfile_path[0] == '\0') {
3479  cache->flag &= ~PTCACHE_DISK_CACHE;
3480  if (G.debug & G_DEBUG) {
3481  printf("File must be saved before using disk cache!\n");
3482  }
3483  return;
3484  }
3485 
3486  if (cache->cached_frames) {
3487  MEM_freeN(cache->cached_frames);
3488  cache->cached_frames = NULL;
3489  cache->cached_frames_len = 0;
3490  }
3491 
3492  if (cache->flag & PTCACHE_DISK_CACHE) {
3494  }
3495  else {
3497  }
3498 
3499  cache->flag ^= PTCACHE_DISK_CACHE;
3501  cache->flag ^= PTCACHE_DISK_CACHE;
3502 
3503  cache->last_exact = last_exact;
3504 
3505  BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL);
3506 
3507  cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
3508 
3509  if ((cache->flag & PTCACHE_DISK_CACHE) == 0) {
3510  if (cache->index) {
3512  cache->index = -1;
3513  }
3514  }
3515 }
3516 
3517 void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const char *name_dst)
3518 {
3519  char old_name[80];
3520  int len; /* store the length of the string */
3521  /* mode is same as fopen's modes */
3522  DIR *dir;
3523  struct dirent *de;
3524  char path[MAX_PTCACHE_PATH];
3525  char old_filename[MAX_PTCACHE_FILE];
3526  char new_path_full[MAX_PTCACHE_FILE];
3527  char old_path_full[MAX_PTCACHE_FILE];
3528  char ext[MAX_PTCACHE_PATH];
3529 
3530  /* If both names are the same, there is nothing to do. */
3531  if (STREQ(name_src, name_dst)) {
3532  return;
3533  }
3534 
3535  /* save old name */
3536  BLI_strncpy(old_name, pid->cache->name, sizeof(old_name));
3537 
3538  /* get "from" filename */
3539  BLI_strncpy(pid->cache->name, name_src, sizeof(pid->cache->name));
3540 
3541  len = ptcache_filename(pid, old_filename, 0, false, false); /* no path */
3542 
3543  ptcache_path(pid, path);
3544  dir = opendir(path);
3545  if (dir == NULL) {
3546  BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name));
3547  return;
3548  }
3549 
3550  ptcache_filename_ext_append(pid, ext, 0, false, 0);
3551 
3552  /* put new name into cache */
3553  BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name));
3554 
3555  while ((de = readdir(dir)) != NULL) {
3556  if (strstr(de->d_name, ext)) { /* Do we have the right extension? */
3557  if (STREQLEN(old_filename, de->d_name, len)) { /* Do we have the right prefix. */
3558  /* read the number of the file */
3559  const int frame = ptcache_frame_from_filename(de->d_name, ext);
3560 
3561  if (frame != -1) {
3562  BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name);
3563  ptcache_filename(pid, new_path_full, frame, true, true);
3564  BLI_rename(old_path_full, new_path_full);
3565  }
3566  }
3567  }
3568  }
3569  closedir(dir);
3570 
3571  BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name));
3572 }
3573 
3575 {
3576  /* TODO: */
3577  PointCache *cache = pid->cache;
3578  int len; /* store the length of the string */
3579  int info = 0;
3580  int start = MAXFRAME;
3581  int end = -1;
3582 
3583  /* mode is same as fopen's modes */
3584  DIR *dir;
3585  struct dirent *de;
3586  char path[MAX_PTCACHE_PATH];
3587  char filename[MAX_PTCACHE_FILE];
3588  char ext[MAX_PTCACHE_PATH];
3589 
3590  if (!cache) {
3591  return;
3592  }
3593 
3594  ptcache_path(pid, path);
3595 
3596  len = ptcache_filename(pid, filename, 1, false, false); /* no path */
3597 
3598  dir = opendir(path);
3599  if (dir == NULL) {
3600  return;
3601  }
3602 
3603  const char *fext = ptcache_file_extension(pid);
3604 
3605  if (cache->index >= 0) {
3606  BLI_snprintf(ext, sizeof(ext), "_%02d%s", cache->index, fext);
3607  }
3608  else {
3609  BLI_strncpy(ext, fext, sizeof(ext));
3610  }
3611 
3612  while ((de = readdir(dir)) != NULL) {
3613  if (strstr(de->d_name, ext)) { /* Do we have the right extension? */
3614  if (STREQLEN(filename, de->d_name, len)) { /* Do we have the right prefix. */
3615  /* read the number of the file */
3616  const int frame = ptcache_frame_from_filename(de->d_name, ext);
3617 
3618  if (frame != -1) {
3619  if (frame) {
3620  start = MIN2(start, frame);
3621  end = MAX2(end, frame);
3622  }
3623  else {
3624  info = 1;
3625  }
3626  }
3627  }
3628  }
3629  }
3630  closedir(dir);
3631 
3632  if (start != MAXFRAME) {
3633  PTCacheFile *pf;
3634 
3635  cache->startframe = start;
3636  cache->endframe = end;
3637  cache->totpoint = 0;
3638 
3639  if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
3640  /* necessary info in every file */
3641  }
3642  /* read totpoint from info file (frame 0) */
3643  else if (info) {
3645 
3646  if (pf) {
3648  if (pf->type == pid->type && pid->read_header(pf)) {
3649  cache->totpoint = pf->totpoint;
3650  cache->flag |= PTCACHE_READ_INFO;
3651  }
3652  else {
3653  cache->totpoint = 0;
3654  }
3655  }
3657  }
3658  }
3659  /* or from any old format cache file */
3660  else {
3661  float old_data[14];
3662  int elemsize = ptcache_old_elemsize(pid);
3664 
3665  if (pf) {
3666  while (ptcache_file_read(pf, old_data, 1, elemsize)) {
3667  cache->totpoint++;
3668  }
3669 
3671  }
3672  }
3675  }
3676 
3677  /* make sure all new frames are loaded */
3678  if (cache->cached_frames) {
3679  MEM_freeN(cache->cached_frames);
3680  cache->cached_frames = NULL;
3681  cache->cached_frames_len = 0;
3682  }
3683 
3684  cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
3685 }
3686 
3688 {
3689  PointCache *cache = pid->cache;
3690  PTCacheExtra *extra = NULL;
3691  int totframes = 0;
3692  char mem_info[sizeof(((PointCache *)0)->info) / sizeof(*(((PointCache *)0)->info))];
3693 
3694  cache->flag &= ~PTCACHE_FLAG_INFO_DIRTY;
3695 
3696  if (cache->flag & PTCACHE_EXTERNAL) {
3697  int cfra = cache->startframe;
3698 
3699  for (; cfra <= cache->endframe; cfra++) {
3700  if (BKE_ptcache_id_exist(pid, cfra)) {
3701  totframes++;
3702  }
3703  }
3704 
3705  /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */
3706  if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) {
3707  BLI_snprintf(cache->info, sizeof(cache->info), TIP_("%i frames found!"), totframes);
3708  }
3709  else if (totframes && cache->totpoint) {
3710  BLI_snprintf(cache->info, sizeof(cache->info), TIP_("%i points found!"), cache->totpoint);
3711  }
3712  else {
3713  BLI_strncpy(cache->info, TIP_("No valid data to read!"), sizeof(cache->info));
3714  }
3715  return;
3716  }
3717 
3718  if (cache->flag & PTCACHE_DISK_CACHE) {
3719  if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
3720  int totpoint = pid->totpoint(pid->calldata, 0);
3721 
3722  if (cache->totpoint > totpoint) {
3723  BLI_snprintf(
3724  mem_info, sizeof(mem_info), TIP_("%i cells + High Resolution cached"), totpoint);
3725  }
3726  else {
3727  BLI_snprintf(mem_info, sizeof(mem_info), TIP_("%i cells cached"), totpoint);
3728  }
3729  }
3730  else {
3731  int cfra = cache->startframe;
3732 
3733  for (; cfra <= cache->endframe; cfra++) {
3734  if (BKE_ptcache_id_exist(pid, cfra)) {
3735  totframes++;
3736  }
3737  }
3738 
3739  BLI_snprintf(mem_info, sizeof(mem_info), TIP_("%i frames on disk"), totframes);
3740  }
3741  }
3742  else {
3743  PTCacheMem *pm = cache->mem_cache.first;
3744  char formatted_tot[16];
3745  char formatted_mem[15];
3746  long long int bytes = 0.0f;
3747  int i;
3748 
3749  for (; pm; pm = pm->next) {
3750  for (i = 0; i < BPHYS_TOT_DATA; i++) {
3751  bytes += MEM_allocN_len(pm->data[i]);
3752  }
3753 
3754  for (extra = pm->extradata.first; extra; extra = extra->next) {
3755  bytes += MEM_allocN_len(extra->data);
3756  bytes += sizeof(PTCacheExtra);
3757  }
3758 
3759  bytes += sizeof(PTCacheMem);
3760 
3761  totframes++;
3762  }
3763 
3764  BLI_str_format_int_grouped(formatted_tot, totframes);
3765  BLI_str_format_byte_unit(formatted_mem, bytes, false);
3766 
3767  BLI_snprintf(mem_info,
3768  sizeof(mem_info),
3769  TIP_("%s frames in memory (%s)"),
3770  formatted_tot,
3771  formatted_mem);
3772  }
3773 
3774  if (cache->flag & PTCACHE_OUTDATED) {
3775  BLI_snprintf(cache->info, sizeof(cache->info), TIP_("%s, cache is outdated!"), mem_info);
3776  }
3777  else if (cache->flag & PTCACHE_FRAMES_SKIPPED) {
3778  BLI_snprintf(cache->info,
3779  sizeof(cache->info),
3780  TIP_("%s, not exact since frame %i"),
3781  mem_info,
3782  cache->last_exact);
3783  }
3784  else {
3785  BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info);
3786  }
3787 }
3788 
3789 void BKE_ptcache_validate(PointCache *cache, int framenr)
3790 {
3791  if (cache) {
3792  cache->flag |= PTCACHE_SIMULATION_VALID;
3793  cache->simframe = framenr;
3794  }
3795 }
3797 {
3798  if (cache) {
3799  cache->flag &= ~PTCACHE_SIMULATION_VALID;
3800  cache->simframe = 0;
3801  cache->last_exact = MIN2(cache->startframe, 0);
3802  }
3803 }
3804 
3805 static const char *ptcache_data_struct[] = {
3806  "", // BPHYS_DATA_INDEX
3807  "", // BPHYS_DATA_LOCATION
3808  "", // BPHYS_DATA_VELOCITY
3809  "", // BPHYS_DATA_ROTATION
3810  "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
3811  "", // BPHYS_DATA_SIZE:
3812  "", // BPHYS_DATA_TIMES:
3813  "BoidData", // case BPHYS_DATA_BOIDS:
3814 };
3815 static const char *ptcache_extra_struct[] = {
3816  "",
3817  "ParticleSpring",
3818  "vec3f",
3819 };
3821 {
3822  LISTBASE_FOREACH (PointCache *, cache, ptcaches) {
3823  BLO_write_struct(writer, PointCache, cache);
3824 
3825  if ((cache->flag & PTCACHE_DISK_CACHE) == 0) {
3826  LISTBASE_FOREACH (PTCacheMem *, pm, &cache->mem_cache) {
3827  BLO_write_struct(writer, PTCacheMem, pm);
3828 
3829  for (int i = 0; i < BPHYS_TOT_DATA; i++) {
3830  if (pm->data[i] && pm->data_types & (1 << i)) {
3831  if (ptcache_data_struct[i][0] == '\0') {
3832  BLO_write_raw(writer, MEM_allocN_len(pm->data[i]), pm->data[i]);
3833  }
3834  else {
3836  writer, ptcache_data_struct[i], pm->totpoint, pm->data[i]);
3837  }
3838  }
3839  }
3840 
3841  LISTBASE_FOREACH (PTCacheExtra *, extra, &pm->extradata) {
3842  if (ptcache_extra_struct[extra->type][0] == '\0') {
3843  continue;
3844  }
3845  BLO_write_struct(writer, PTCacheExtra, extra);
3847  writer, ptcache_extra_struct[extra->type], extra->totdata, extra->data);
3848  }
3849  }
3850  }
3851  }
3852 }
3853 
3855 {
3856  PTCacheMem *pm = data;
3857  for (int i = 0; i < BPHYS_TOT_DATA; i++) {
3858  BLO_read_data_address(reader, &pm->data[i]);
3859 
3860  /* the cache saves non-struct data without DNA */
3861  if (pm->data[i] && ptcache_data_struct[i][0] == '\0' &&
3863  /* data_size returns bytes. */
3864  int tot = (BKE_ptcache_data_size(i) * pm->totpoint) / sizeof(int);
3865 
3866  int *poin = pm->data[i];
3867 
3868  BLI_endian_switch_int32_array(poin, tot);
3869  }
3870  }
3871 
3872  BLO_read_list(reader, &pm->extradata);
3873 
3874  LISTBASE_FOREACH (PTCacheExtra *, extra, &pm->extradata) {
3875  BLO_read_data_address(reader, &extra->data);
3876  }
3877 }
3878 
3880 {
3881  if ((cache->flag & PTCACHE_DISK_CACHE) == 0) {
3883  }
3884  else {
3885  BLI_listbase_clear(&cache->mem_cache);
3886  }
3887 
3888  cache->flag &= ~PTCACHE_SIMULATION_VALID;
3889  cache->simframe = 0;
3890  cache->edit = NULL;
3891  cache->free_edit = NULL;
3892  cache->cached_frames = NULL;
3893  cache->cached_frames_len = 0;
3894 }
3895 
3897  ListBase *ptcaches,
3898  PointCache **ocache,
3899  int force_disk)
3900 {
3901  if (ptcaches->first) {
3902  BLO_read_list(reader, ptcaches);
3903  LISTBASE_FOREACH (PointCache *, cache, ptcaches) {
3904  direct_link_pointcache(reader, cache);
3905  if (force_disk) {
3906  cache->flag |= PTCACHE_DISK_CACHE;
3907  cache->step = 1;
3908  }
3909  }
3910 
3911  BLO_read_data_address(reader, ocache);
3912  }
3913  else if (*ocache) {
3914  /* old "single" caches need to be linked too */
3915  BLO_read_data_address(reader, ocache);
3916  direct_link_pointcache(reader, *ocache);
3917  if (force_disk) {
3918  (*ocache)->flag |= PTCACHE_DISK_CACHE;
3919  (*ocache)->step = 1;
3920  }
3921 
3922  ptcaches->first = ptcaches->last = *ocache;
3923  }
3924 }
typedef float(TangentPoint)[2]
void BIK_clear_cache(struct bPose *pose)
Definition: ikplugin_api.c:103
void cloth_free_modifier(struct ClothModifierData *clmd)
Definition: cloth.c:421
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
struct PaintPoint PaintPoint
struct PaintWavePoint PaintWavePoint
void dynamicPaint_clearSurface(const struct Scene *scene, struct DynamicPaintSurface *surface)
@ G_DEBUG
Definition: BKE_global.h:174
@ LIB_ID_COPY_CACHES
Definition: BKE_lib_id.h:152
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:562
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
General operations, lookup, etc. for blender objects.
int BKE_object_insert_ptcache(struct Object *ob)
Definition: object.cc:4524
void BKE_object_delete_ptcache(struct Object *ob, int index)
Definition: object.cc:4567
struct ParticleSystem * psys_eval_get(struct Depsgraph *depsgraph, struct Object *object, struct ParticleSystem *psys)
Definition: particle.c:761
void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, bool velocity)
Definition: particle.c:1231
void psys_reset(struct ParticleSystem *psys, int mode)
#define PSYS_RESET_ALL
Definition: BKE_particle.h:666
#define PSYS_RESET_DEPSGRAPH
Definition: BKE_particle.h:667
#define PTCACHE_TYPEFLAG_TYPEMASK
#define PTCACHE_FILE_READ
#define PTCACHE_TYPE_SMOKE_HIGHRES
#define PTCACHE_VEL_PER_SEC
#define PTCACHE_FILE_WRITE
#define PTCACHE_CLEAR_BEFORE
#define PTCACHE_CLEAR_AFTER
@ PTCACHE_FILE_PTCACHE
#define PTCACHE_EXT
#define PTCACHE_TYPE_CLOTH
#define PTCACHE_TYPE_DYNAMICPAINT
#define PTCACHE_CLEAR_ALL
#define PTCACHE_READ_INTERPOLATED
#define PTCACHE_TYPE_PARTICLES
#define PTCACHE_TYPEFLAG_FLAGMASK
#define PTCACHE_TYPE_SOFTBODY
#define PTCACHE_READ_OLD
#define PTCACHE_TYPEFLAG_COMPRESS
#define PTCACHE_FILE_UPDATE
#define PTCACHE_CLEAR_FRAME
#define PTCACHE_TYPE_SMOKE_DOMAIN
#define PTCACHE_RESET_OUTDATED
#define PTCACHE_PATH
#define PTCACHE_TYPE_RIGIDBODY
#define PTCACHE_RESET_DEPSGRAPH
#define PTCACHE_RESET_BAKED
#define PTCACHE_READ_EXACT
#define PTCACHE_TYPEFLAG_EXTRADATA
void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph)
Definition: scene.cc:2728
float BKE_scene_ctime_get(const struct Scene *scene)
#define SETLOOPER_VIEW_LAYER(_sce_basis, _view_layer, _sce_iter, _base)
Definition: BKE_scene.h:43
float BKE_scene_frame_to_ctime(const struct Scene *scene, int frame)
void sbFreeSimulation(struct SoftBody *sb)
Definition: softbody.c:3173
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_endian_switch_int32_array(int *val, int size) ATTR_NONNULL(1)
Definition: endian_switch.c:31
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:314
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:906
int BLI_delete(const char *file, bool dir, bool recursive) ATTR_NONNULL()
Definition: fileops.c:934
int BLI_rename(const char *from, const char *to) ATTR_NONNULL()
Definition: fileops.c:1268
int BLI_fseek(FILE *stream, int64_t offset, int whence)
Definition: storage.c:160
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:221
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void vec_to_quat(float q[4], const float vec[3], short axis, short upflag)
void unit_qt(float q[4])
Definition: math_rotation.c:27
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void zero_v3(float r[3])
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:347
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1197
int BLI_path_slash_ensure(char *string) ATTR_NONNULL()
Definition: path_util.c:1780
void BLI_split_file_part(const char *string, char *file, size_t filelen)
Definition: path_util.c:1495
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
void BLI_join_dirfile(char *__restrict dst, size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1531
size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL()
Definition: string.c:1114
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) ATTR_NONNULL()
Definition: string.c:1132
#define UNPACK4(a)
#define STREQLEN(a, b, n)
#define UNUSED(x)
#define MAX2(a, b)
#define ELEM(...)
#define MIN2(a, b)
#define STREQ(a, b)
Compatibility-like things for windows.
struct __dirstream DIR
Definition: BLI_winstuff.h:84
int closedir(DIR *dp)
struct dirent * readdir(DIR *dp)
DIR * opendir(const char *path)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5172
void BLO_read_list_cb(BlendDataReader *reader, struct ListBase *list, BlendReadListFn callback)
Definition: readfile.c:5148
void BLO_write_struct_array_by_name(BlendWriter *writer, const char *struct_name, int array_size, const void *data_ptr)
Definition: writefile.c:1499
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
Definition: readfile.c:5143
void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_ptr)
Definition: writefile.c:1489
#define TIP_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
ID and Library types, which are fundamental for sdna.
@ ID_RECALC_PSYS_REDO
Definition: DNA_ID.h:798
@ ID_RECALC_PSYS_CHILD
Definition: DNA_ID.h:802
@ ID_OB
Definition: DNA_ID_enums.h:47
Object groups, one object can be in many groups at once.
@ MOD_DPAINT_SURFACE_T_WEIGHT
@ MOD_DPAINT_SURFACE_T_PAINT
@ MOD_DPAINT_SURFACE_T_DISPLACE
@ MOD_DPAINT_SURFACE_T_WAVE
@ MOD_DPAINT_SURFACE_F_IMAGESEQ
@ FLUID_DOMAIN_CACHE_REPLAY
@ eModifierType_Cloth
@ eModifierType_Fluid
@ eModifierType_DynamicPaint
@ MOD_FLUID_TYPE_DOMAIN
Object is a sort of wrapper for general info.
#define MAX_DUPLI_RECUR
@ OB_ARMATURE
@ OB_NEGX
@ OB_POSZ
#define PART_PHYS_KEYED
#define SPH_VISCOELASTIC_SPRINGS
#define PART_PHYS_FLUID
#define PART_PHYS_BOIDS
#define PSYS_HAIR_DYNAMICS
struct ParticleKey ParticleKey
@ PART_EMITTER
@ PART_FLUID
@ PART_HAIR
#define PART_PHYS_NO
#define PART_DIED
#define PART_ROTATIONS
struct ParticleSpring ParticleSpring
#define PART_ROT_VEL
#define PART_AVE_RAND
struct PTCacheMem PTCacheMem
#define BPHYS_DATA_LOCATION
#define BPHYS_EXTRA_FLUID_SPRINGS
#define BPHYS_DATA_INDEX
#define BPHYS_DATA_DYNAMICPAINT
#define BPHYS_DATA_TIMES
#define BPHYS_DATA_BOIDS
#define BPHYS_DATA_SIZE
struct PTCacheExtra PTCacheExtra
#define BPHYS_DATA_VELOCITY
@ PTCACHE_READ_INFO
@ PTCACHE_IGNORE_CLEAR
@ PTCACHE_EXTERNAL
@ PTCACHE_IGNORE_LIBPATH
@ PTCACHE_BAKED
@ PTCACHE_FRAMES_SKIPPED
@ PTCACHE_FLAG_INFO_DIRTY
@ PTCACHE_BAKING
@ PTCACHE_OUTDATED
@ PTCACHE_DISK_CACHE
@ PTCACHE_SIMULATION_VALID
@ PTCACHE_REDO_NEEDED
#define BPHYS_DATA_ROTATION
#define BPHYS_DATA_AVELOCITY
#define BPHYS_TOT_DATA
#define BPHYS_EXTRA_CLOTH_ACCELERATION
#define BPHYS_DATA_XCONST
Types and defines for representing Rigid Body entities.
@ RBO_TYPE_ACTIVE
@ RBO_FLAG_NEEDS_RESHAPE
#define MAXFRAME
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
static float frame_len(const Frame *frame)
Definition: MOD_skin.c:379
Platform independent time functions.
Rigid Body API for interfacing with external Physics Engines.
__forceinline ssef low(const avxf &a)
Definition: avxf.h:264
__forceinline ssef high(const avxf &a)
Definition: avxf.h:268
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
StackEntry * from
FILE * file
double time
Scene scene
const Depsgraph * depsgraph
DEGForeachIDComponentCallback callback
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
DRWShaderLibrary * lib
struct @211::@212 surface
#define rot(x, k)
#define str(s)
#define pf(_x, _i)
Prefetch 64.
Definition: gim_memory.h:48
uint pos
int count
void * BKE_tempdir_session
#define GS(x)
Definition: iris.c:225
ccl_gpu_kernel_postfix ccl_global float int int int int float bool reset
clear internal cached data and reset random seed
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:26
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define G(x, y, z)
static void error(const char *str)
Definition: meshlaplacian.c:51
static void clear(Message *msg)
Definition: msgfmt.c:278
T floor(const T &a)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
static int bake(const BakeAPIRender *bkr, Object *ob_low, const ListBase *selected_objects, ReportList *reports)
static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
Definition: pointcache.c:1625
int BKE_ptcache_data_size(int data_type)
Definition: pointcache.c:1707
static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
Definition: pointcache.c:658
struct PTCacheIDsFromObjectData PTCacheIDsFromObjectData
#define PTCACHE_DATA_FROM(data, type, from)
Definition: pointcache.c:88
static int ptcache_basic_header_read(PTCacheFile *pf)
Definition: pointcache.c:132
static void ptcache_data_copy(void *from[], void *to[])
Definition: pointcache.c:1825
void BKE_ptcache_disk_to_mem(PTCacheID *pid)
Definition: pointcache.c:3421
void BKE_ptcache_mem_pointers_incr(void *cur[BPHYS_TOT_DATA])
Definition: pointcache.c:1772
static bool foreach_object_modifier_ptcache(Object *object, ForeachPtcacheCb callback, void *callback_user_data)
Definition: pointcache.c:1153
static size_t ptcache_filename_ext_append(PTCacheID *pid, char *filename, const size_t filename_len, const bool use_frame_number, const int cfra)
Definition: pointcache.c:1352
bool(* ForeachPtcacheCb)(PTCacheID *pid, void *userdata)
Definition: pointcache.c:1121
static bool ptcache_ids_from_object_cb(PTCacheID *pid, void *userdata)
Definition: pointcache.c:1241
static int ptcache_particle_totwrite(void *psys_v, int cfra)
Definition: pointcache.c:478
int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
Definition: pointcache.c:1727
static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, const float *old_data)
Definition: pointcache.c:387
PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
Definition: pointcache.c:1092
void BKE_ptcache_invalidate(PointCache *cache)
Definition: pointcache.c:3796
void BKE_ptcache_load_external(PTCacheID *pid)
Definition: pointcache.c:3574
static void ptcache_file_close(PTCacheFile *pf)
Definition: pointcache.c:1497
static int ptcache_read(PTCacheID *pid, int cfra)
Definition: pointcache.c:2166
bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis)
Definition: pointcache.c:1263
#define MAX_PTCACHE_PATH
Definition: pointcache.c:1306
static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, const bool do_path, const bool do_ext)
Definition: pointcache.c:1404
void BKE_ptcache_mem_to_disk(PTCacheID *pid)
Definition: pointcache.c:3445
void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
Definition: pointcache.c:257
static int ptcache_path(PTCacheID *pid, char *filename)
Definition: pointcache.c:1309
static PTCacheMem * ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
Definition: pointcache.c:1931
static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
Definition: pointcache.c:678
static int ptcache_data_size[]
Definition: pointcache.c:107
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
Definition: pointcache.c:1054
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
Definition: pointcache.c:1016
PointCache * BKE_ptcache_add(ListBase *ptcaches)
Definition: pointcache.c:3014
static void ptcache_data_alloc(PTCacheMem *pm)
Definition: pointcache.c:1802
static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
Definition: pointcache.c:2413
void BKE_ptcache_update_info(PTCacheID *pid)
Definition: pointcache.c:3687
static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
Definition: pointcache.c:2022
static const char * ptcache_file_extension(const PTCacheID *pid)
Definition: pointcache.c:1270
static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
Definition: pointcache.c:2375
static PointCache * ptcache_copy(PointCache *cache, const bool copy_data)
Definition: pointcache.c:3061
static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
Definition: pointcache.c:178
static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), const float *old_data)
Definition: pointcache.c:783
#define MAX_PTCACHE_FILE
Definition: pointcache.c:1307
static void direct_link_pointcache_cb(BlendDataReader *reader, void *data)
Definition: pointcache.c:3854
void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
Definition: pointcache.c:2773
static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
Definition: pointcache.c:848
static void direct_link_pointcache(BlendDataReader *reader, PointCache *cache)
Definition: pointcache.c:3879
static const char * ptcache_extra_struct[]
Definition: pointcache.c:3815
static int ptcache_file_data_write(PTCacheFile *pf)
Definition: pointcache.c:1646
static void ptcache_file_pointers_init(PTCacheFile *pf)
Definition: pointcache.c:1712
bool BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
Definition: pointcache.c:2742
static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size)
Definition: pointcache.c:1629
void BKE_ptcache_free_mem(ListBase *mem_cache)
Definition: pointcache.c:3029
static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
Definition: pointcache.c:1505
void BKE_ptcache_free_list(ListBase *ptcaches)
Definition: pointcache.c:3052
static int ptcache_read_stream(PTCacheID *pid, int cfra)
Definition: pointcache.c:2118
static void ptcache_cloth_extra_write(void *cloth_v, PTCacheMem *pm, int UNUSED(cfra))
Definition: pointcache.c:615
static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
Definition: pointcache.c:541
static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, const float *old_data)
Definition: pointcache.c:571
void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition: pointcache.c:3124
static bool foreach_object_ptcache(Scene *scene, Object *object, int duplis, ForeachPtcacheCb callback, void *callback_user_data)
Definition: pointcache.c:1191
void BKE_ptcache_mem_pointers_init(PTCacheMem *pm, void *cur[BPHYS_TOT_DATA])
Definition: pointcache.c:1762
static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
Definition: pointcache.c:715
void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
Definition: pointcache.c:962
static void ptcache_softbody_error(const ID *UNUSED(owner_id), void *UNUSED(soft_v), const char *UNUSED(message))
Definition: pointcache.c:248
static int ptcache_extra_datasize[]
Definition: pointcache.c:118
static int ptcache_frame_from_filename(const char *filename, const char *ext)
Definition: pointcache.c:1282
void BKE_ptcache_blend_read_data(BlendDataReader *reader, ListBase *ptcaches, PointCache **ocache, int force_disk)
Definition: pointcache.c:3896
static PTCacheFile * ptcache_file_open(PTCacheID *pid, int mode, int cfra)
Definition: pointcache.c:1451
static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
Definition: pointcache.c:1873
int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm, void *cur[BPHYS_TOT_DATA])
Definition: pointcache.c:1782
static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
Definition: pointcache.c:520
void BKE_ptcache_bake(PTCacheBaker *baker)
Definition: pointcache.c:3156
static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
Definition: pointcache.c:1554
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
Definition: pointcache.c:2280
static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
Definition: pointcache.c:243
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
Definition: pointcache.c:1250
static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, const float *old_data)
Definition: pointcache.c:319
static void ptcache_rigidbody_error(const struct ID *UNUSED(owner_id), void *UNUSED(rb_v), const char *UNUSED(message))
Definition: pointcache.c:855
static void ptcache_cloth_error(const ID *owner_id, void *cloth_v, const char *message)
Definition: pointcache.c:648
static void ptcache_add_extra_data(PTCacheMem *pm, unsigned int type, unsigned int count, void *data)
Definition: pointcache.c:160
void BKE_ptcache_free(PointCache *cache)
Definition: pointcache.c:3041
static void ptcache_particle_error(const ID *UNUSED(owner_id), void *UNUSED(psys_v), const char *UNUSED(message))
Definition: pointcache.c:471
static void ptcache_cloth_extra_read(void *cloth_v, PTCacheMem *pm, float UNUSED(cfra))
Definition: pointcache.c:624
static const char * ptcache_data_struct[]
Definition: pointcache.c:3805
void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
Definition: pointcache.c:2592
static int ptcache_old_elemsize(PTCacheID *pid)
Definition: pointcache.c:1858
static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
Definition: pointcache.c:759
void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const char *name_dst)
Definition: pointcache.c:3517
static void ptcache_dynamicpaint_error(const ID *UNUSED(owner_id), void *UNUSED(sd), const char *UNUSED(message))
Definition: pointcache.c:669
static CLG_LogRef LOG
Definition: pointcache.c:105
static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
Definition: pointcache.c:642
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
Definition: pointcache.c:2540
static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
Definition: pointcache.c:2223
void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
Definition: pointcache.c:864
void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
Definition: pointcache.c:3472
int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
Definition: pointcache.c:2870
PointCache * BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, const int flag)
Definition: pointcache.c:3104
#define PTCACHE_DATA_TO(data, type, index, to)
Definition: pointcache.c:94
static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, const float *old_data)
Definition: pointcache.c:809
#define LZO_OUT_LEN(size)
Definition: pointcache.c:75
static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
Definition: pointcache.c:273
void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *fmd)
Definition: pointcache.c:999
static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
Definition: pointcache.c:508
static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), const float *old_data)
Definition: pointcache.c:553
#define DPAINT_CACHE_VERSION
Definition: pointcache.c:676
static bool ptcache_object_has_cb(PTCacheID *UNUSED(pid), void *UNUSED(userdata))
Definition: pointcache.c:1258
static int ptcache_file_header_begin_write(PTCacheFile *pf)
Definition: pointcache.c:1689
void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
Definition: pointcache.c:900
static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, const float *old_data)
Definition: pointcache.c:203
static bool foreach_object_particle_ptcache(Object *object, ForeachPtcacheCb callback, void *callback_user_data)
Definition: pointcache.c:1123
static void ptcache_mem_clear(PTCacheMem *pm)
Definition: pointcache.c:1852
static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), const float *old_data)
Definition: pointcache.c:188
static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
Definition: pointcache.c:2486
static void ptcache_dt_to_str(char *str, double dtime)
Definition: pointcache.c:3140
void BKE_ptcache_validate(PointCache *cache, int framenr)
Definition: pointcache.c:3789
static void ptcache_data_free(PTCacheMem *pm)
Definition: pointcache.c:1814
static int ptcache_file_header_begin_read(PTCacheFile *pf)
Definition: pointcache.c:1659
static void ptcache_extra_free(PTCacheMem *pm)
Definition: pointcache.c:1837
int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
Definition: pointcache.c:2930
static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
Definition: pointcache.c:465
static int ptcache_basic_header_write(PTCacheFile *pf)
Definition: pointcache.c:147
void BKE_ptcache_blend_write(BlendWriter *writer, ListBase *ptcaches)
Definition: pointcache.c:3820
static int ptcache_file_data_read(PTCacheFile *pf)
Definition: pointcache.c:1633
return ret
void RB_body_get_orientation(rbRigidBody *object, float v_out[4])
void RB_body_get_position(rbRigidBody *object, float v_out[3])
struct Object * object
float pos[3]
Definition: BKE_softbody.h:19
float vec[3]
Definition: BKE_softbody.h:19
struct BoidData data
struct ListBase ptcaches
struct ClothHairData * hairdata
struct Cloth * clothObject
struct PointCache * point_cache
float x[3]
Definition: BKE_cloth.h:93
float v[3]
Definition: BKE_cloth.h:91
float xconst[3]
Definition: BKE_cloth.h:92
float average_acceleration[3]
Definition: BKE_cloth.h:81
unsigned int mvert_num
Definition: BKE_cloth.h:69
struct ClothVertex * verts
Definition: BKE_cloth.h:66
struct DynamicPaintCanvasSettings * canvas
struct ListBase ptcaches[2]
struct PointCache * point_cache[2]
struct FluidDomainSettings * domain
Definition: DNA_ID.h:368
struct Library * lib
Definition: DNA_ID.h:372
char name[66]
Definition: DNA_ID.h:378
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct ModifierData * next
ListBase particlesystem
struct Collection * instance_collection
struct bPose * pose
ListBase modifiers
struct RigidBodyOb * rigidbody_object
struct SoftBody * soft
struct RigidBodyCon * rigidbody_constraint
struct PTCacheID pid
struct Scene * scene
struct Main * bmain
void(* update_progress)(void *data, float progress, int *cancel)
struct Depsgraph * depsgraph
struct ViewLayer * view_layer
unsigned int type
unsigned int totdata
struct PTCacheExtra * next
struct PointCache ** cache_ptr
int(* write_stream)(PTCacheFile *pf, void *calldata)
int(* write_point)(int index, void *calldata, void **data, int cfra)
unsigned int data_types
struct ID * owner_id
unsigned int info_types
int(* write_header)(PTCacheFile *pf)
void(* read_point)(int index, void *calldata, void **data, float cfra, const float *old_data)
void * calldata
unsigned int type
void(* interpolate_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra, float cfra1, float cfra2)
unsigned int stack_index
struct ListBase * ptcaches
unsigned int flag
void(* read_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra)
void(* interpolate_point)(int index, void *calldata, void **data, float cfra, float cfra1, float cfra2, const float *old_data)
unsigned int default_step
int(* totpoint)(void *calldata, int cfra)
unsigned int file_type
int(* totwrite)(void *calldata, int cfra)
void(* write_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra)
int(* read_stream)(PTCacheFile *pf, void *calldata)
unsigned int max_step
void(* error)(const struct ID *owner_id, void *calldata, const char *message)
struct PTCacheID * next
int(* read_header)(PTCacheFile *pf)
struct PointCache * cache
unsigned int data_types
unsigned int frame
struct ListBase extradata
struct PTCacheMem * next
struct PTCacheMem * prev
unsigned int totpoint
BoidParticle * boid
ParticleKey state
ParticleKey prev_state
struct SPHFluidSettings * fluid
ParticleSpring * fluid_springs
struct ListBase ptcaches
ParticleData * particles
ParticleSettings * part
struct ParticleSystem * next
struct PointCache * pointcache
struct ClothModifierData * clmd
struct PointCache * next
struct ListBase mem_cache
struct PTCacheEdit * edit
void(* free_edit)(struct PTCacheEdit *edit)
struct RigidBodyOb_Shared * shared
struct PointCache * pointcache
struct RigidBodyWorld_Shared * shared
struct Object ** objects
struct PhysicsSettings physics_settings
struct RigidBodyWorld * rigidbody_world
struct RenderData r
struct PointCache * pointcache
struct ListBase ptcaches
struct SoftBody_Shared * shared
struct BodyPoint * bpoint
char * d_name
Definition: BLI_winstuff.h:80
double PIL_check_seconds_timer(void)
Definition: time.c:64