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