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