Merging r58266 through r58279 from trunk into soc-2013-depsgraph_mt
[blender-staging.git] / source / blender / blenkernel / intern / pointcache.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Campbell Barton <ideasman42@gmail.com>
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/blenkernel/intern/pointcache.c
27  *  \ingroup bke
28  */
29
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_ID.h"
40 #include "DNA_cloth_types.h"
41 #include "DNA_dynamicpaint_types.h"
42 #include "DNA_modifier_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_object_force.h"
45 #include "DNA_particle_types.h"
46 #include "DNA_rigidbody_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_smoke_types.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_threads.h"
52 #include "BLI_math.h"
53 #include "BLI_utildefines.h"
54
55 #include "BLF_translation.h"
56
57 #include "PIL_time.h"
58
59 #include "WM_api.h"
60
61 #include "BKE_anim.h"
62 #include "BKE_blender.h"
63 #include "BKE_cloth.h"
64 #include "BKE_depsgraph.h"
65 #include "BKE_dynamicpaint.h"
66 #include "BKE_global.h"
67 #include "BKE_library.h"
68 #include "BKE_main.h"
69 #include "BKE_object.h"
70 #include "BKE_particle.h"
71 #include "BKE_pointcache.h"
72 #include "BKE_scene.h"
73 #include "BKE_smoke.h"
74 #include "BKE_softbody.h"
75
76 #include "BIK_api.h"
77
78 #ifdef WITH_BULLET
79 #  include "RBI_api.h"
80 #endif
81
82 /* both in intern */
83 #ifdef WITH_SMOKE
84 #include "smoke_API.h"
85 #endif
86
87 #ifdef WITH_LZO
88 #include "minilzo.h"
89 #else
90 /* used for non-lzo cases */
91 #define LZO_OUT_LEN(size)     ((size) + (size) / 16 + 64 + 3)
92 #endif
93
94 #ifdef WITH_LZMA
95 #include "LzmaLib.h"
96 #endif
97
98 /* needed for directory lookup */
99 /* untitled blend's need getpid for a unique name */
100 #ifndef WIN32
101 #  include <dirent.h>
102 #  include <unistd.h>
103 #else
104 #  include <process.h>
105 #  include "BLI_winstuff.h"
106 #endif
107
108 #define PTCACHE_DATA_FROM(data, type, from)  \
109         if (data[type]) { \
110                 memcpy(data[type], from, ptcache_data_size[type]); \
111         } (void)0
112
113 #define PTCACHE_DATA_TO(data, type, index, to)  \
114         if (data[type]) { \
115                 memcpy(to, (char *)(data)[type] + ((index) ? (index) * ptcache_data_size[type] : 0), ptcache_data_size[type]); \
116         } (void)0
117
118 /* could be made into a pointcache option */
119 #define DURIAN_POINTCACHE_LIB_OK 1
120
121 static int ptcache_data_size[] = {      
122                 sizeof(unsigned int), // BPHYS_DATA_INDEX
123                 3 * sizeof(float), // BPHYS_DATA_LOCATION
124                 3 * sizeof(float), // BPHYS_DATA_VELOCITY
125                 4 * sizeof(float), // BPHYS_DATA_ROTATION
126                 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST
127                 sizeof(float), // BPHYS_DATA_SIZE
128                 3 * sizeof(float), // BPHYS_DATA_TIMES
129                 sizeof(BoidData) // case BPHYS_DATA_BOIDS
130 };
131
132 static int ptcache_extra_datasize[] = {
133         0,
134         sizeof(ParticleSpring)
135 };
136
137 /* forward declerations */
138 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len);
139 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode);
140 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size);
141 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
142
143 /* Common functions */
144 static int ptcache_basic_header_read(PTCacheFile *pf)
145 {
146         int error=0;
147
148         /* Custom functions should read these basic elements too! */
149         if (!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
150                 error = 1;
151         
152         if (!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
153                 error = 1;
154
155         return !error;
156 }
157 static int ptcache_basic_header_write(PTCacheFile *pf)
158 {
159         /* Custom functions should write these basic elements too! */
160         if (!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
161                 return 0;
162         
163         if (!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
164                 return 0;
165
166         return 1;
167 }
168 /* Softbody functions */
169 static int  ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
170 {
171         SoftBody *soft= soft_v;
172         BodyPoint *bp = soft->bpoint + index;
173
174         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos);
175         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec);
176
177         return 1;
178 }
179 static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data)
180 {
181         SoftBody *soft= soft_v;
182         BodyPoint *bp = soft->bpoint + index;
183
184         if (old_data) {
185                 memcpy(bp->pos, data, 3 * sizeof(float));
186                 memcpy(bp->vec, data + 3, 3 * sizeof(float));
187         }
188         else {
189                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos);
190                 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
191         }
192 }
193 static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
194 {
195         SoftBody *soft= soft_v;
196         BodyPoint *bp = soft->bpoint + index;
197         ParticleKey keys[4];
198         float dfra;
199
200         if (cfra1 == cfra2)
201                 return;
202
203         copy_v3_v3(keys[1].co, bp->pos);
204         copy_v3_v3(keys[1].vel, bp->vec);
205
206         if (old_data) {
207                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
208                 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
209         }
210         else
211                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
212
213         dfra = cfra2 - cfra1;
214
215         mul_v3_fl(keys[1].vel, dfra);
216         mul_v3_fl(keys[2].vel, dfra);
217
218         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
219
220         mul_v3_fl(keys->vel, 1.0f / dfra);
221
222         copy_v3_v3(bp->pos, keys->co);
223         copy_v3_v3(bp->vec, keys->vel);
224 }
225 static int  ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
226 {
227         SoftBody *soft= soft_v;
228         return soft->totpoint;
229 }
230 /* Particle functions */
231 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
232 {
233         PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
234         PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
235         
236         /* no rotation info, so make something nice up */
237         if (data[BPHYS_DATA_ROTATION]==NULL) {
238                 vec_to_quat(key->rot, key->vel, OB_NEGX, OB_POSZ);
239         }
240         else {
241                 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
242         }
243
244         PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
245         key->time = time;
246 }
247 static int  ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
248 {
249         ParticleSystem *psys= psys_v;
250         ParticleData *pa = psys->particles + index;
251         BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
252         float times[3];
253         int step = psys->pointcache->step;
254
255         /* No need to store unborn or died particles outside cache step bounds */
256         if (data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step))
257                 return 0;
258
259         times[0] = pa->time;
260         times[1] = pa->dietime;
261         times[2] = pa->lifetime;
262
263         PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
264         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
265         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
266         PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
267         PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
268         PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
269         PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
270
271         if (boid)
272                 PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
273
274         /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */
275         return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
276 }
277 static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data)
278 {
279         ParticleSystem *psys= psys_v;
280         ParticleData *pa;
281         BoidParticle *boid;
282         float timestep = 0.04f * psys->part->timetweak;
283
284         if (index >= psys->totpart)
285                 return;
286
287         pa = psys->particles + index;
288         boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
289
290         if (cfra > pa->state.time)
291                 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
292
293         if (old_data) {
294                 /* old format cache */
295                 memcpy(&pa->state, old_data, sizeof(ParticleKey));
296                 return;
297         }
298
299         BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
300
301         /* set frames cached before birth to birth time */
302         if (cfra < pa->time)
303                 pa->state.time = pa->time;
304         else if (cfra > pa->dietime)
305                 pa->state.time = pa->dietime;
306
307         if (data[BPHYS_DATA_SIZE])
308                 PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
309         
310         if (data[BPHYS_DATA_TIMES]) {
311                 float times[3];
312                 PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, &times);
313                 pa->time = times[0];
314                 pa->dietime = times[1];
315                 pa->lifetime = times[2];
316         }
317
318         if (boid) {
319                 PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
320         }
321
322         /* determine velocity from previous location */
323         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
324                 if (cfra > pa->prev_state.time) {
325                         sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
326                         mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep);
327                 }
328                 else {
329                         sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
330                         mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep);
331                 }
332         }
333
334         /* default to no rotation */
335         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
336                 unit_qt(pa->state.rot);
337         }
338 }
339 static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
340 {
341         ParticleSystem *psys= psys_v;
342         ParticleData *pa;
343         ParticleKey keys[4];
344         float dfra, timestep = 0.04f * psys->part->timetweak;
345
346         if (index >= psys->totpart)
347                 return;
348
349         pa = psys->particles + index;
350
351         /* particle wasn't read from first cache so can't interpolate */
352         if ((int)cfra1 < pa->time - psys->pointcache->step || (int)cfra1 > pa->dietime + psys->pointcache->step)
353                 return;
354
355         cfra = MIN2(cfra, pa->dietime);
356         cfra1 = MIN2(cfra1, pa->dietime);
357         cfra2 = MIN2(cfra2, pa->dietime);
358
359         if (cfra1 == cfra2)
360                 return;
361
362         memcpy(keys+1, &pa->state, sizeof(ParticleKey));
363         if (old_data)
364                 memcpy(keys+2, old_data, sizeof(ParticleKey));
365         else
366                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
367
368         /* determine velocity from previous location */
369         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
370                 if (keys[1].time > keys[2].time) {
371                         sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
372                         mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep);
373                 }
374                 else {
375                         sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
376                         mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep);
377                 }
378         }
379
380         /* determine rotation from velocity */
381         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
382                 vec_to_quat(keys[2].rot, keys[2].vel, OB_NEGX, OB_POSZ);
383         }
384
385         if (cfra > pa->time)
386                 cfra1 = MAX2(cfra1, pa->time);
387
388         dfra = cfra2 - cfra1;
389
390         mul_v3_fl(keys[1].vel, dfra * timestep);
391         mul_v3_fl(keys[2].vel, dfra * timestep);
392
393         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
394         interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
395
396         mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep));
397
398         pa->state.time = cfra;
399 }
400
401 static int  ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
402 {
403         ParticleSystem *psys = psys_v;
404         return psys->totpart;
405 }
406 static int  ptcache_particle_totwrite(void *psys_v, int cfra)
407 {
408         ParticleSystem *psys = psys_v;
409         ParticleData *pa= psys->particles;
410         int p, step = psys->pointcache->step;
411         int totwrite = 0;
412
413         if (cfra == 0)
414                 return psys->totpart;
415
416         for (p=0; p<psys->totpart; p++, pa++)
417                 totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step);
418
419         return totwrite;
420 }
421
422 static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
423 {
424         ParticleSystem *psys = psys_v;
425         PTCacheExtra *extra = NULL;
426
427         if (psys->part->phystype == PART_PHYS_FLUID &&
428                 psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS &&
429                 psys->tot_fluidsprings && psys->fluid_springs) {
430
431                 extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data");
432
433                 extra->type = BPHYS_EXTRA_FLUID_SPRINGS;
434                 extra->totdata = psys->tot_fluidsprings;
435
436                 extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data");
437                 memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]);
438
439                 BLI_addtail(&pm->extradata, extra);
440         }
441 }
442
443 static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
444 {
445         ParticleSystem *psys = psys_v;
446         PTCacheExtra *extra = pm->extradata.first;
447
448         for (; extra; extra=extra->next) {
449                 switch (extra->type) {
450                         case BPHYS_EXTRA_FLUID_SPRINGS:
451                         {
452                                 if (psys->fluid_springs)
453                                         MEM_freeN(psys->fluid_springs);
454
455                                 psys->fluid_springs = MEM_dupallocN(extra->data);
456                                 psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata;
457                                 break;
458                         }
459                 }
460         }
461 }
462
463 /* Cloth functions */
464 static int  ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
465 {
466         ClothModifierData *clmd= cloth_v;
467         Cloth *cloth= clmd->clothObject;
468         ClothVertex *vert = cloth->verts + index;
469
470         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x);
471         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v);
472         PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst);
473
474         return 1;
475 }
476 static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data)
477 {
478         ClothModifierData *clmd= cloth_v;
479         Cloth *cloth= clmd->clothObject;
480         ClothVertex *vert = cloth->verts + index;
481         
482         if (old_data) {
483                 memcpy(vert->x, data, 3 * sizeof(float));
484                 memcpy(vert->xconst, data + 3, 3 * sizeof(float));
485                 memcpy(vert->v, data + 6, 3 * sizeof(float));
486         }
487         else {
488                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x);
489                 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v);
490                 PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst);
491         }
492 }
493 static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
494 {
495         ClothModifierData *clmd= cloth_v;
496         Cloth *cloth= clmd->clothObject;
497         ClothVertex *vert = cloth->verts + index;
498         ParticleKey keys[4];
499         float dfra;
500
501         if (cfra1 == cfra2)
502                 return;
503
504         copy_v3_v3(keys[1].co, vert->x);
505         copy_v3_v3(keys[1].vel, vert->v);
506
507         if (old_data) {
508                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
509                 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
510         }
511         else
512                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
513
514         dfra = cfra2 - cfra1;
515
516         mul_v3_fl(keys[1].vel, dfra);
517         mul_v3_fl(keys[2].vel, dfra);
518
519         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
520
521         mul_v3_fl(keys->vel, 1.0f / dfra);
522
523         copy_v3_v3(vert->x, keys->co);
524         copy_v3_v3(vert->v, keys->vel);
525
526         /* should vert->xconst be interpolated somehow too? - jahka */
527 }
528
529 static int  ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
530 {
531         ClothModifierData *clmd= cloth_v;
532         return clmd->clothObject ? clmd->clothObject->numverts : 0;
533 }
534
535 #ifdef WITH_SMOKE
536 /* Smoke functions */
537 static int  ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
538 {
539         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
540         SmokeDomainSettings *sds = smd->domain;
541         
542         if (sds->fluid) {
543                 return sds->base_res[0]*sds->base_res[1]*sds->base_res[2];
544         }
545         else
546                 return 0;
547 }
548
549 #define SMOKE_CACHE_VERSION "1.04"
550
551 static int  ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
552 {       
553         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
554         SmokeDomainSettings *sds = smd->domain;
555         int ret = 0;
556         int fluid_fields = smoke_get_data_flags(sds);
557
558         /* version header */
559         ptcache_file_write(pf, SMOKE_CACHE_VERSION, 4, sizeof(char));
560         ptcache_file_write(pf, &fluid_fields, 1, sizeof(int));
561         ptcache_file_write(pf, &sds->active_fields, 1, sizeof(int));
562         ptcache_file_write(pf, &sds->res, 3, sizeof(int));
563         ptcache_file_write(pf, &sds->dx, 1, sizeof(float));
564         
565         if (sds->fluid) {
566                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
567                 float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
568                 unsigned char *obstacles;
569                 unsigned int in_len = sizeof(float)*(unsigned int)res;
570                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
571                 //int mode = res >= 1000000 ? 2 : 1;
572                 int mode=1;             // light
573                 if (sds->cache_comp == SM_CACHE_HEAVY) mode=2;  // heavy
574
575                 smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
576
577                 ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
578                 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode);
579                 if (fluid_fields & SM_ACTIVE_HEAT) {
580                         ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode);
581                         ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode);
582                 }
583                 if (fluid_fields & SM_ACTIVE_FIRE) {
584                         ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len, out, mode);
585                         ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len, out, mode);
586                         ptcache_file_compressed_write(pf, (unsigned char *)react, in_len, out, mode);
587                 }
588                 if (fluid_fields & SM_ACTIVE_COLORS) {
589                         ptcache_file_compressed_write(pf, (unsigned char *)r, in_len, out, mode);
590                         ptcache_file_compressed_write(pf, (unsigned char *)g, in_len, out, mode);
591                         ptcache_file_compressed_write(pf, (unsigned char *)b, in_len, out, mode);
592                 }
593                 ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode);
594                 ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode);
595                 ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode);
596                 ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
597                 ptcache_file_write(pf, &dt, 1, sizeof(float));
598                 ptcache_file_write(pf, &dx, 1, sizeof(float));
599                 ptcache_file_write(pf, &sds->p0, 3, sizeof(float));
600                 ptcache_file_write(pf, &sds->p1, 3, sizeof(float));
601                 ptcache_file_write(pf, &sds->dp0, 3, sizeof(float));
602                 ptcache_file_write(pf, &sds->shift, 3, sizeof(int));
603                 ptcache_file_write(pf, &sds->obj_shift_f, 3, sizeof(float));
604                 ptcache_file_write(pf, &sds->obmat, 16, sizeof(float));
605                 ptcache_file_write(pf, &sds->base_res, 3, sizeof(int));
606                 ptcache_file_write(pf, &sds->res_min, 3, sizeof(int));
607                 ptcache_file_write(pf, &sds->res_max, 3, sizeof(int));
608                 ptcache_file_write(pf, &sds->active_color, 3, sizeof(float));
609
610                 MEM_freeN(out);
611                 
612                 ret = 1;
613         }
614
615         if (sds->wt) {
616                 int res_big_array[3];
617                 int res_big;
618                 int res = sds->res[0]*sds->res[1]*sds->res[2];
619                 float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
620                 unsigned int in_len = sizeof(float)*(unsigned int)res;
621                 unsigned int in_len_big;
622                 unsigned char *out;
623                 int mode;
624
625                 smoke_turbulence_get_res(sds->wt, res_big_array);
626                 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
627                 //mode =  res_big >= 1000000 ? 2 : 1;
628                 mode = 1;       // light
629                 if (sds->cache_high_comp == SM_CACHE_HEAVY) mode=2;     // heavy
630
631                 in_len_big = sizeof(float) * (unsigned int)res_big;
632
633                 smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
634
635                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
636                 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode);
637                 if (fluid_fields & SM_ACTIVE_FIRE) {
638                         ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len_big, out, mode);
639                         ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len_big, out, mode);
640                         ptcache_file_compressed_write(pf, (unsigned char *)react, in_len_big, out, mode);
641                 }
642                 if (fluid_fields & SM_ACTIVE_COLORS) {
643                         ptcache_file_compressed_write(pf, (unsigned char *)r, in_len_big, out, mode);
644                         ptcache_file_compressed_write(pf, (unsigned char *)g, in_len_big, out, mode);
645                         ptcache_file_compressed_write(pf, (unsigned char *)b, in_len_big, out, mode);
646                 }
647                 MEM_freeN(out);
648
649                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
650                 ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode);
651                 ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode);
652                 ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode);
653                 MEM_freeN(out);
654                 
655                 ret = 1;
656         }
657
658         return ret;
659 }
660
661 /* read old smoke cache from 2.64 */
662 static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
663 {
664         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
665         SmokeDomainSettings *sds = smd->domain;
666         
667         if (sds->fluid) {
668                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
669                 float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz;
670                 unsigned char *obstacles;
671                 unsigned int out_len = (unsigned int)res * sizeof(float);
672                 float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp");
673
674                 int fluid_fields = smoke_get_data_flags(sds);
675
676                 /* Part part of the new cache header */
677                 sds->active_color[0] = 0.7f;
678                 sds->active_color[1] = 0.7f;
679                 sds->active_color[2] = 0.7f;
680                 
681                 smoke_export(sds->fluid, &dt, &dx, &dens, NULL, NULL, NULL, &heat, &heatold, &vx, &vy, &vz, NULL, NULL, NULL, &obstacles);
682
683                 ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
684                 ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
685                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
686
687                 if (fluid_fields & SM_ACTIVE_HEAT)
688                 {
689                         ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
690                         ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
691                 }
692                 else
693                 {
694                         ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
695                         ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
696                 }
697                 ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
698                 ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
699                 ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
700                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
701                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
702                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
703                 ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
704                 ptcache_file_read(pf, &dt, 1, sizeof(float));
705                 ptcache_file_read(pf, &dx, 1, sizeof(float));
706
707                 MEM_freeN(tmp_array);
708
709                 if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
710                         int res = sds->res[0]*sds->res[1]*sds->res[2];
711                         int res_big, res_big_array[3];
712                         float *dens, *tcu, *tcv, *tcw;
713                         unsigned int out_len = sizeof(float)*(unsigned int)res;
714                         unsigned int out_len_big;
715                         unsigned char *tmp_array_big;
716
717                         smoke_turbulence_get_res(sds->wt, res_big_array);
718                         res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
719                         out_len_big = sizeof(float) * (unsigned int)res_big;
720
721                         tmp_array_big = MEM_callocN(out_len_big, "Smoke old cache tmp");
722
723                         smoke_turbulence_export(sds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw);
724
725                         ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
726                         ptcache_file_compressed_read(pf, (unsigned char*)tmp_array_big, out_len_big);
727
728                         ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
729                         ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
730                         ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
731
732                         MEM_freeN(tmp_array_big);
733                 }
734         }
735
736         return 1;       
737 }
738
739 static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
740 {
741         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
742         SmokeDomainSettings *sds = smd->domain;
743         char version[4];
744         int ch_res[3];
745         float ch_dx;
746         int fluid_fields = smoke_get_data_flags(sds);
747         int cache_fields = 0;
748         int active_fields = 0;
749         int reallocate = 0;
750
751         /* version header */
752         ptcache_file_read(pf, version, 4, sizeof(char));
753         if (strncmp(version, SMOKE_CACHE_VERSION, 4))
754         {
755                 /* reset file pointer */
756                 fseek(pf->fp, -4, SEEK_CUR);
757                 return ptcache_smoke_read_old(pf, smoke_v);
758         }
759
760         /* fluid info */
761         ptcache_file_read(pf, &cache_fields, 1, sizeof(int));
762         ptcache_file_read(pf, &active_fields, 1, sizeof(int));
763         ptcache_file_read(pf, &ch_res, 3, sizeof(int));
764         ptcache_file_read(pf, &ch_dx, 1, sizeof(float));
765
766         /* check if resolution has changed */
767         if (sds->res[0] != ch_res[0] ||
768                 sds->res[1] != ch_res[1] ||
769                 sds->res[2] != ch_res[2]) {
770                 if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)
771                         reallocate = 1;
772                 else
773                         return 0;
774         }
775         /* check if active fields have changed */
776         if (fluid_fields != cache_fields ||
777                 active_fields != sds->active_fields)
778                 reallocate = 1;
779
780         /* reallocate fluid if needed*/
781         if (reallocate) {
782                 sds->active_fields = active_fields | cache_fields;
783                 smoke_reallocate_fluid(sds, ch_dx, ch_res, 1);
784                 sds->dx = ch_dx;
785                 VECCOPY(sds->res, ch_res);
786                 sds->total_cells = ch_res[0]*ch_res[1]*ch_res[2];
787                 if (sds->flags & MOD_SMOKE_HIGHRES) {
788                         smoke_reallocate_highres_fluid(sds, ch_dx, ch_res, 1);
789                 }
790         }
791         
792         if (sds->fluid) {
793                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
794                 float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
795                 unsigned char *obstacles;
796                 unsigned int out_len = (unsigned int)res * sizeof(float);
797                 
798                 smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
799
800                 ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
801                 ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len);
802                 if (cache_fields & SM_ACTIVE_HEAT) {
803                         ptcache_file_compressed_read(pf, (unsigned char *)heat, out_len);
804                         ptcache_file_compressed_read(pf, (unsigned char *)heatold, out_len);
805                 }
806                 if (cache_fields & SM_ACTIVE_FIRE) {
807                         ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len);
808                         ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len);
809                         ptcache_file_compressed_read(pf, (unsigned char *)react, out_len);
810                 }
811                 if (cache_fields & SM_ACTIVE_COLORS) {
812                         ptcache_file_compressed_read(pf, (unsigned char *)r, out_len);
813                         ptcache_file_compressed_read(pf, (unsigned char *)g, out_len);
814                         ptcache_file_compressed_read(pf, (unsigned char *)b, out_len);
815                 }
816                 ptcache_file_compressed_read(pf, (unsigned char *)vx, out_len);
817                 ptcache_file_compressed_read(pf, (unsigned char *)vy, out_len);
818                 ptcache_file_compressed_read(pf, (unsigned char *)vz, out_len);
819                 ptcache_file_compressed_read(pf, (unsigned char *)obstacles, (unsigned int)res);
820                 ptcache_file_read(pf, &dt, 1, sizeof(float));
821                 ptcache_file_read(pf, &dx, 1, sizeof(float));
822                 ptcache_file_read(pf, &sds->p0, 3, sizeof(float));
823                 ptcache_file_read(pf, &sds->p1, 3, sizeof(float));
824                 ptcache_file_read(pf, &sds->dp0, 3, sizeof(float));
825                 ptcache_file_read(pf, &sds->shift, 3, sizeof(int));
826                 ptcache_file_read(pf, &sds->obj_shift_f, 3, sizeof(float));
827                 ptcache_file_read(pf, &sds->obmat, 16, sizeof(float));
828                 ptcache_file_read(pf, &sds->base_res, 3, sizeof(int));
829                 ptcache_file_read(pf, &sds->res_min, 3, sizeof(int));
830                 ptcache_file_read(pf, &sds->res_max, 3, sizeof(int));
831                 ptcache_file_read(pf, &sds->active_color, 3, sizeof(float));
832         }
833
834         if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
835                         int res = sds->res[0]*sds->res[1]*sds->res[2];
836                         int res_big, res_big_array[3];
837                         float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
838                         unsigned int out_len = sizeof(float)*(unsigned int)res;
839                         unsigned int out_len_big;
840
841                         smoke_turbulence_get_res(sds->wt, res_big_array);
842                         res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
843                         out_len_big = sizeof(float) * (unsigned int)res_big;
844
845                         smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
846
847                         ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len_big);
848                         if (cache_fields & SM_ACTIVE_FIRE) {
849                                 ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len_big);
850                                 ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len_big);
851                                 ptcache_file_compressed_read(pf, (unsigned char *)react, out_len_big);
852                         }
853                         if (cache_fields & SM_ACTIVE_COLORS) {
854                                 ptcache_file_compressed_read(pf, (unsigned char *)r, out_len_big);
855                                 ptcache_file_compressed_read(pf, (unsigned char *)g, out_len_big);
856                                 ptcache_file_compressed_read(pf, (unsigned char *)b, out_len_big);
857                         }
858
859                         ptcache_file_compressed_read(pf, (unsigned char *)tcu, out_len);
860                         ptcache_file_compressed_read(pf, (unsigned char *)tcv, out_len);
861                         ptcache_file_compressed_read(pf, (unsigned char *)tcw, out_len);
862                 }
863
864         return 1;
865 }
866 #else // WITH_SMOKE
867 static int  ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; }
868 static int  ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
869 static int  ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
870 #endif // WITH_SMOKE
871
872 static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
873 {
874         DynamicPaintSurface *surface = (DynamicPaintSurface*)sd;
875
876         if (!surface->data) return 0;
877         else return surface->data->total_points;
878 }
879
880 #define DPAINT_CACHE_VERSION "1.01"
881
882 static int  ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
883 {       
884         DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
885         int cache_compress = 1;
886
887         /* version header */
888         ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char) * 4);
889
890         if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
891                 int total_points=surface->data->total_points;
892                 unsigned int in_len;
893                 unsigned char *out;
894
895                 /* cache type */
896                 ptcache_file_write(pf, &surface->type, 1, sizeof(int));
897
898                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
899                         in_len = sizeof(PaintPoint) * total_points;
900                 }
901                 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
902                          surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
903                 {
904                         in_len = sizeof(float) * total_points;
905                 }
906                 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
907                         in_len = sizeof(PaintWavePoint) * total_points;
908                 }
909                 else {
910                         return 0;
911                 }
912
913                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
914
915                 ptcache_file_compressed_write(pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress);
916                 MEM_freeN(out);
917
918         }
919         return 1;
920 }
921 static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
922 {
923         DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
924         char version[4];
925         
926         /* version header */
927         ptcache_file_read(pf, version, 1, sizeof(char) * 4);
928         if (strncmp(version, DPAINT_CACHE_VERSION, 4)) {
929                 printf("Dynamic Paint: Invalid cache version: %s!\n", version);
930                 return 0;
931         }
932
933         if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
934                 unsigned int data_len;
935                 int surface_type;
936
937                 /* cache type */
938                 ptcache_file_read(pf, &surface_type, 1, sizeof(int));
939
940                 if (surface_type != surface->type)
941                         return 0;
942
943                 /* read surface data */
944                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
945                         data_len = sizeof(PaintPoint);
946                 }
947                 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
948                          surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
949                 {
950                         data_len = sizeof(float);
951                 }
952                 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
953                         data_len = sizeof(PaintWavePoint);
954                 }
955                 else {
956                         return 0;
957                 }
958
959                 ptcache_file_compressed_read(pf, (unsigned char *)surface->data->type_data, data_len*surface->data->total_points);
960
961         }
962         return 1;
963 }
964
965 /* Rigid Body functions */
966 static int  ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
967 {
968         RigidBodyWorld *rbw = rb_v;
969         Object *ob = NULL;
970         
971         if (rbw->objects)
972                 ob = rbw->objects[index];
973         
974         if (ob && ob->rigidbody_object) {
975                 RigidBodyOb *rbo = ob->rigidbody_object;
976                 
977                 if (rbo->type == RBO_TYPE_ACTIVE) {
978 #ifdef WITH_BULLET
979                         RB_body_get_position(rbo->physics_object, rbo->pos);
980                         RB_body_get_orientation(rbo->physics_object, rbo->orn);
981 #endif
982                         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
983                         PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
984                 }
985         }
986
987         return 1;
988 }
989 static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data)
990 {
991         RigidBodyWorld *rbw = rb_v;
992         Object *ob = NULL;
993         
994         if (rbw->objects)
995                 ob = rbw->objects[index];
996         
997         if (ob && ob->rigidbody_object) {
998                 RigidBodyOb *rbo = ob->rigidbody_object;
999                 
1000                 if (rbo->type == RBO_TYPE_ACTIVE) {
1001                         
1002                         if (old_data) {
1003                                 memcpy(rbo->pos, data, 3 * sizeof(float));
1004                                 memcpy(rbo->orn, data + 3, 4 * sizeof(float));
1005                         }
1006                         else {
1007                                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos);
1008                                 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn);
1009                         }
1010                 }
1011         }
1012 }
1013 static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
1014 {
1015         RigidBodyWorld *rbw = rb_v;
1016         Object *ob = NULL;
1017         ParticleKey keys[4];
1018         float dfra;
1019         
1020         if (rbw->objects)
1021                 ob = rbw->objects[index];
1022         
1023         if (ob && ob->rigidbody_object) {
1024                 RigidBodyOb *rbo = ob->rigidbody_object;
1025                 
1026                 if (rbo->type == RBO_TYPE_ACTIVE) {
1027                         
1028                         copy_v3_v3(keys[1].co, rbo->pos);
1029                         copy_v3_v3(keys[1].rot, rbo->orn);
1030                         
1031                         if (old_data) {
1032                                 memcpy(keys[2].co, data, 3 * sizeof(float));
1033                                 memcpy(keys[2].rot, data + 3, 4 * sizeof(float));
1034                         }
1035                         else {
1036                                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
1037                         }
1038                         
1039                         dfra = cfra2 - cfra1;
1040                 
1041                         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
1042                         interp_qt_qtqt(keys->rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
1043                         
1044                         copy_v3_v3(rbo->pos, keys->co);
1045                         copy_v3_v3(rbo->orn, keys->rot);
1046                 }
1047         }
1048 }
1049 static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
1050 {
1051         RigidBodyWorld *rbw = rb_v;
1052         
1053         return rbw->numbodies;
1054 }
1055
1056 /* Creating ID's */
1057 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
1058 {
1059         memset(pid, 0, sizeof(PTCacheID));
1060
1061         pid->ob= ob;
1062         pid->calldata= sb;
1063         pid->type= PTCACHE_TYPE_SOFTBODY;
1064         pid->cache= sb->pointcache;
1065         pid->cache_ptr= &sb->pointcache;
1066         pid->ptcaches= &sb->ptcaches;
1067         pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
1068
1069         pid->write_point                        = ptcache_softbody_write;
1070         pid->read_point                         = ptcache_softbody_read;
1071         pid->interpolate_point          = ptcache_softbody_interpolate;
1072
1073         pid->write_stream                       = NULL;
1074         pid->read_stream                        = NULL;
1075
1076         pid->write_extra_data           = NULL;
1077         pid->read_extra_data            = NULL;
1078         pid->interpolate_extra_data     = NULL;
1079
1080         pid->write_header                       = ptcache_basic_header_write;
1081         pid->read_header                        = ptcache_basic_header_read;
1082
1083         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
1084         pid->info_types= 0;
1085
1086         pid->stack_index = pid->cache->index;
1087
1088         pid->default_step = 10;
1089         pid->max_step = 20;
1090 }
1091 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
1092 {
1093         memset(pid, 0, sizeof(PTCacheID));
1094
1095         pid->ob= ob;
1096         pid->calldata= psys;
1097         pid->type= PTCACHE_TYPE_PARTICLES;
1098         pid->stack_index= psys->pointcache->index;
1099         pid->cache= psys->pointcache;
1100         pid->cache_ptr= &psys->pointcache;
1101         pid->ptcaches= &psys->ptcaches;
1102
1103         if (psys->part->type != PART_HAIR)
1104                 pid->flag |= PTCACHE_VEL_PER_SEC;
1105
1106         pid->totpoint                           = ptcache_particle_totpoint;
1107         pid->totwrite                           = ptcache_particle_totwrite;
1108
1109         pid->write_point                                = ptcache_particle_write;
1110         pid->read_point                         = ptcache_particle_read;
1111         pid->interpolate_point          = ptcache_particle_interpolate;
1112
1113         pid->write_stream                       = NULL;
1114         pid->read_stream                        = NULL;
1115
1116         pid->write_extra_data           = NULL;
1117         pid->read_extra_data            = NULL;
1118         pid->interpolate_extra_data     = NULL;
1119
1120         pid->write_header                       = ptcache_basic_header_write;
1121         pid->read_header                        = ptcache_basic_header_read;
1122
1123         pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
1124
1125         if (psys->part->phystype == PART_PHYS_BOIDS)
1126                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
1127         else if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) {
1128                 pid->write_extra_data = ptcache_particle_extra_write;
1129                 pid->read_extra_data = ptcache_particle_extra_read;
1130         }
1131
1132         if (psys->part->flag & PART_ROTATIONS) {
1133                 pid->data_types|= (1<<BPHYS_DATA_ROTATION);
1134
1135                 if (psys->part->rotmode != PART_ROT_VEL  ||
1136                     psys->part->avemode == PART_AVE_RAND ||
1137                     psys->part->avefac != 0.0f)
1138                 {
1139                         pid->data_types |= (1 << BPHYS_DATA_AVELOCITY);
1140                 }
1141         }
1142
1143         pid->info_types= (1<<BPHYS_DATA_TIMES);
1144
1145         pid->default_step = 10;
1146         pid->max_step = 20;
1147 }
1148 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
1149 {
1150         memset(pid, 0, sizeof(PTCacheID));
1151
1152         pid->ob= ob;
1153         pid->calldata= clmd;
1154         pid->type= PTCACHE_TYPE_CLOTH;
1155         pid->stack_index= clmd->point_cache->index;
1156         pid->cache= clmd->point_cache;
1157         pid->cache_ptr= &clmd->point_cache;
1158         pid->ptcaches= &clmd->ptcaches;
1159         pid->totpoint= pid->totwrite= ptcache_cloth_totpoint;
1160
1161         pid->write_point                        = ptcache_cloth_write;
1162         pid->read_point                         = ptcache_cloth_read;
1163         pid->interpolate_point          = ptcache_cloth_interpolate;
1164
1165         pid->write_stream                       = NULL;
1166         pid->read_stream                        = NULL;
1167
1168         pid->write_extra_data           = NULL;
1169         pid->read_extra_data            = NULL;
1170         pid->interpolate_extra_data     = NULL;
1171
1172         pid->write_header                       = ptcache_basic_header_write;
1173         pid->read_header                        = ptcache_basic_header_read;
1174
1175         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
1176         pid->info_types= 0;
1177
1178         pid->default_step = 1;
1179         pid->max_step = 1;
1180 }
1181 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
1182 {
1183         SmokeDomainSettings *sds = smd->domain;
1184
1185         memset(pid, 0, sizeof(PTCacheID));
1186
1187         pid->ob= ob;
1188         pid->calldata= smd;
1189         
1190         pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
1191         pid->stack_index= sds->point_cache[0]->index;
1192
1193         pid->cache= sds->point_cache[0];
1194         pid->cache_ptr= &(sds->point_cache[0]);
1195         pid->ptcaches= &(sds->ptcaches[0]);
1196
1197         pid->totpoint= pid->totwrite= ptcache_smoke_totpoint;
1198
1199         pid->write_point                        = NULL;
1200         pid->read_point                         = NULL;
1201         pid->interpolate_point          = NULL;
1202
1203         pid->read_stream                        = ptcache_smoke_read;
1204         pid->write_stream                       = ptcache_smoke_write;
1205
1206         pid->write_extra_data           = NULL;
1207         pid->read_extra_data            = NULL;
1208         pid->interpolate_extra_data     = NULL;
1209
1210         pid->write_header                       = ptcache_basic_header_write;
1211         pid->read_header                        = ptcache_basic_header_read;
1212
1213         pid->data_types= 0;
1214         pid->info_types= 0;
1215
1216         if (sds->fluid)
1217                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW);
1218         if (sds->wt)
1219                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH);
1220
1221         pid->default_step = 1;
1222         pid->max_step = 1;
1223 }
1224
1225 void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
1226 {
1227
1228         memset(pid, 0, sizeof(PTCacheID));
1229
1230         pid->ob= ob;
1231         pid->calldata= surface;
1232         pid->type= PTCACHE_TYPE_DYNAMICPAINT;
1233         pid->cache= surface->pointcache;
1234         pid->cache_ptr= &surface->pointcache;
1235         pid->ptcaches= &surface->ptcaches;
1236         pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint;
1237
1238         pid->write_point                        = NULL;
1239         pid->read_point                         = NULL;
1240         pid->interpolate_point          = NULL;
1241
1242         pid->write_stream                       = ptcache_dynamicpaint_write;
1243         pid->read_stream                        = ptcache_dynamicpaint_read;
1244
1245         pid->write_extra_data           = NULL;
1246         pid->read_extra_data            = NULL;
1247         pid->interpolate_extra_data     = NULL;
1248
1249         pid->write_header                       = ptcache_basic_header_write;
1250         pid->read_header                        = ptcache_basic_header_read;
1251
1252         pid->data_types= BPHYS_DATA_DYNAMICPAINT;
1253         pid->info_types= 0;
1254
1255         pid->stack_index = pid->cache->index;
1256
1257         pid->default_step = 1;
1258         pid->max_step = 1;
1259 }
1260
1261 void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
1262 {
1263         
1264         memset(pid, 0, sizeof(PTCacheID));
1265         
1266         pid->ob= ob;
1267         pid->calldata= rbw;
1268         pid->type= PTCACHE_TYPE_RIGIDBODY;
1269         pid->cache= rbw->pointcache;
1270         pid->cache_ptr= &rbw->pointcache;
1271         pid->ptcaches= &rbw->ptcaches;
1272         pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
1273         
1274         pid->write_point                        = ptcache_rigidbody_write;
1275         pid->read_point                         = ptcache_rigidbody_read;
1276         pid->interpolate_point          = ptcache_rigidbody_interpolate;
1277         
1278         pid->write_stream                       = NULL;
1279         pid->read_stream                        = NULL;
1280         
1281         pid->write_extra_data           = NULL;
1282         pid->read_extra_data            = NULL;
1283         pid->interpolate_extra_data     = NULL;
1284         
1285         pid->write_header                       = ptcache_basic_header_write;
1286         pid->read_header                        = ptcache_basic_header_read;
1287         
1288         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_ROTATION);
1289         pid->info_types= 0;
1290         
1291         pid->stack_index = pid->cache->index;
1292         
1293         pid->default_step = 1;
1294         pid->max_step = 1;
1295 }
1296
1297 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
1298 {
1299         PTCacheID *pid;
1300         ParticleSystem *psys;
1301         ModifierData *md;
1302
1303         lb->first= lb->last= NULL;
1304
1305         if (ob->soft) {
1306                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1307                 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
1308                 BLI_addtail(lb, pid);
1309         }
1310
1311         for (psys=ob->particlesystem.first; psys; psys=psys->next) {
1312                 if (psys->part==NULL)
1313                         continue;
1314                 
1315                 /* check to make sure point cache is actually used by the particles */
1316                 if (ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
1317                         continue;
1318
1319                 /* hair needs to be included in id-list for cache edit mode to work */
1320                 /* if (psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */
1321                 /*      continue; */
1322                         
1323                 if (psys->part->type == PART_FLUID)
1324                         continue;
1325
1326                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1327                 BKE_ptcache_id_from_particles(pid, ob, psys);
1328                 BLI_addtail(lb, pid);
1329         }
1330
1331         for (md=ob->modifiers.first; md; md=md->next) {
1332                 if (md->type == eModifierType_Cloth) {
1333                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1334                         BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
1335                         BLI_addtail(lb, pid);
1336                 }
1337                 else if (md->type == eModifierType_Smoke) {
1338                         SmokeModifierData *smd = (SmokeModifierData *)md;
1339                         if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1340                                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1341                                 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md);
1342                                 BLI_addtail(lb, pid);
1343                         }
1344                 }
1345                 else if (md->type == eModifierType_DynamicPaint) {
1346                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
1347                         if (pmd->canvas) {
1348                                 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
1349
1350                                 for (; surface; surface=surface->next) {
1351                                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1352                                         BKE_ptcache_id_from_dynamicpaint(pid, ob, surface);
1353                                         BLI_addtail(lb, pid);
1354                                 }
1355                         }
1356                 }
1357         }
1358         
1359         if (scene && ob->rigidbody_object && scene->rigidbody_world) {
1360                 pid = MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1361                 BKE_ptcache_id_from_rigidbody(pid, ob, scene->rigidbody_world);
1362                 BLI_addtail(lb, pid);
1363         }
1364
1365         if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
1366                 ListBase *lb_dupli_ob;
1367
1368                 /* don't update the dupli groups, we only want their pid's */
1369                 if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE, FALSE))) {
1370                         DupliObject *dob;
1371                         for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
1372                                 if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
1373                                         ListBase lb_dupli_pid;
1374                                         BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
1375                                         BLI_movelisttolist(lb, &lb_dupli_pid);
1376                                         if (lb_dupli_pid.first)
1377                                                 printf("Adding Dupli\n");
1378                                 }
1379                         }
1380
1381                         free_object_duplilist(lb_dupli_ob);     /* does restore */
1382                 }
1383         }
1384 }
1385
1386 /* File handling */
1387
1388 /* Takes an Object ID and returns a unique name
1389  * - id: object id
1390  * - cfra: frame for the cache, can be negative
1391  * - stack_index: index in the modifier stack. we can have cache for more than one stack_index
1392  */
1393
1394 #define MAX_PTCACHE_PATH FILE_MAX
1395 #define MAX_PTCACHE_FILE (FILE_MAX * 2)
1396
1397 static int ptcache_path(PTCacheID *pid, char *filename)
1398 {
1399         Library *lib = (pid->ob) ? pid->ob->id.lib : NULL;
1400         const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name;
1401         size_t i;
1402
1403         if (pid->cache->flag & PTCACHE_EXTERNAL) {
1404                 strcpy(filename, pid->cache->path);
1405
1406                 if (BLI_path_is_rel(filename)) {
1407                         BLI_path_abs(filename, blendfilename);
1408                 }
1409
1410                 return BLI_add_slash(filename); /* new strlen() */
1411         }
1412         else if (G.relbase_valid || lib) {
1413                 char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
1414
1415                 BLI_split_file_part(blendfilename, file, sizeof(file));
1416                 i = strlen(file);
1417                 
1418                 /* remove .blend */
1419                 if (i > 6)
1420                         file[i-6] = '\0';
1421                 
1422                 BLI_snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
1423                 BLI_path_abs(filename, blendfilename);
1424                 return BLI_add_slash(filename); /* new strlen() */
1425         }
1426         
1427         /* use the temp path. this is weak but better then not using point cache at all */
1428         /* temporary directory is assumed to exist and ALWAYS has a trailing slash */
1429         BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", BLI_temporary_dir(), abs(getpid()));
1430         
1431         return BLI_add_slash(filename); /* new strlen() */
1432 }
1433
1434 static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
1435 {
1436         int len=0;
1437         char *idname;
1438         char *newname;
1439         filename[0] = '\0';
1440         newname = filename;
1441         
1442         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
1443         
1444         /* start with temp dir */
1445         if (do_path) {
1446                 len = ptcache_path(pid, filename);
1447                 newname += len;
1448         }
1449         if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
1450                 idname = (pid->ob->id.name + 2);
1451                 /* convert chars to hex so they are always a valid filename */
1452                 while ('\0' != *idname) {
1453                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
1454                         newname+=2;
1455                         len += 2;
1456                 }
1457         }
1458         else {
1459                 int temp = (int)strlen(pid->cache->name); 
1460                 strcpy(newname, pid->cache->name); 
1461                 newname+=temp;
1462                 len += temp;
1463         }
1464
1465         if (do_ext) {
1466
1467                 if (pid->cache->index < 0)
1468                         pid->cache->index =  pid->stack_index = BKE_object_insert_ptcache(pid->ob);
1469
1470                 if (pid->cache->flag & PTCACHE_EXTERNAL) {
1471                         if (pid->cache->index >= 0)
1472                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1473                         else
1474                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
1475                 }
1476                 else {
1477                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1478                 }
1479                 len += 16;
1480         }
1481         
1482         return len; /* make sure the above string is always 16 chars */
1483 }
1484
1485 /* youll need to close yourself after! */
1486 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
1487 {
1488         PTCacheFile *pf;
1489         FILE *fp = NULL;
1490         char filename[FILE_MAX * 2];
1491
1492 #ifndef DURIAN_POINTCACHE_LIB_OK
1493         /* don't allow writing for linked objects */
1494         if (pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
1495                 return NULL;
1496 #endif
1497         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
1498         
1499         ptcache_filename(pid, filename, cfra, 1, 1);
1500
1501         if (mode==PTCACHE_FILE_READ) {
1502                 if (!BLI_exists(filename)) {
1503                         return NULL;
1504                 }
1505                 fp = BLI_fopen(filename, "rb");
1506         }
1507         else if (mode==PTCACHE_FILE_WRITE) {
1508                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
1509                 fp = BLI_fopen(filename, "wb");
1510         }
1511         else if (mode==PTCACHE_FILE_UPDATE) {
1512                 BLI_make_existing_file(filename);
1513                 fp = BLI_fopen(filename, "rb+");
1514         }
1515
1516         if (!fp)
1517                 return NULL;
1518
1519         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
1520         pf->fp= fp;
1521         pf->old_format = 0;
1522         pf->frame = cfra;
1523
1524         return pf;
1525 }
1526 static void ptcache_file_close(PTCacheFile *pf)
1527 {
1528         if (pf) {
1529                 fclose(pf->fp);
1530                 MEM_freeN(pf);
1531         }
1532 }
1533
1534 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
1535 {
1536         int r = 0;
1537         unsigned char compressed = 0;
1538         size_t in_len;
1539 #ifdef WITH_LZO
1540         size_t out_len = len;
1541 #endif
1542         unsigned char *in;
1543         unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
1544
1545         ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
1546         if (compressed) {
1547                 unsigned int size;
1548                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1549                 in_len = (size_t)size;
1550                 if (in_len==0) {
1551                         /* do nothing */
1552                 }
1553                 else {
1554                         in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
1555                         ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
1556 #ifdef WITH_LZO
1557                         if (compressed == 1)
1558                                 r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
1559 #endif
1560 #ifdef WITH_LZMA
1561                         if (compressed == 2) {
1562                                 size_t sizeOfIt;
1563                                 size_t leni = in_len, leno = len;
1564                                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1565                                 sizeOfIt = (size_t)size;
1566                                 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
1567                                 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
1568                         }
1569 #endif
1570                         MEM_freeN(in);
1571                 }
1572         }
1573         else {
1574                 ptcache_file_read(pf, result, len, sizeof(unsigned char));
1575         }
1576
1577         MEM_freeN(props);
1578
1579         return r;
1580 }
1581 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
1582 {
1583         int r = 0;
1584         unsigned char compressed = 0;
1585         size_t out_len= 0;
1586         unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
1587         size_t sizeOfIt = 5;
1588
1589         (void)mode; /* unused when building w/o compression */
1590
1591 #ifdef WITH_LZO
1592         out_len= LZO_OUT_LEN(in_len);
1593         if (mode == 1) {
1594                 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
1595                 
1596                 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
1597                 if (!(r == LZO_E_OK) || (out_len >= in_len))
1598                         compressed = 0;
1599                 else
1600                         compressed = 1;
1601         }
1602 #endif
1603 #ifdef WITH_LZMA
1604         if (mode == 2) {
1605                 
1606                 r = LzmaCompress(out, &out_len, in, in_len, //assume sizeof(char)==1....
1607                                  props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
1608
1609                 if (!(r == SZ_OK) || (out_len >= in_len))
1610                         compressed = 0;
1611                 else
1612                         compressed = 2;
1613         }
1614 #endif
1615         
1616         ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
1617         if (compressed) {
1618                 unsigned int size = out_len;
1619                 ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
1620                 ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
1621         }
1622         else
1623                 ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
1624
1625         if (compressed == 2) {
1626                 unsigned int size = sizeOfIt;
1627                 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
1628                 ptcache_file_write(pf, props, size, sizeof(unsigned char));
1629         }
1630
1631         MEM_freeN(props);
1632
1633         return r;
1634 }
1635 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
1636 {
1637         return (fread(f, size, tot, pf->fp) == tot);
1638 }
1639 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size)
1640 {
1641         return (fwrite(f, size, tot, pf->fp) == tot);
1642 }
1643 static int ptcache_file_data_read(PTCacheFile *pf)
1644 {
1645         int i;
1646
1647         for (i=0; i<BPHYS_TOT_DATA; i++) {
1648                 if ((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
1649                         return 0;
1650         }
1651         
1652         return 1;
1653 }
1654 static int ptcache_file_data_write(PTCacheFile *pf)
1655 {               
1656         int i;
1657
1658         for (i=0; i<BPHYS_TOT_DATA; i++) {
1659                 if ((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
1660                         return 0;
1661         }
1662         
1663         return 1;
1664 }
1665 static int ptcache_file_header_begin_read(PTCacheFile *pf)
1666 {
1667         unsigned int typeflag=0;
1668         int error=0;
1669         char bphysics[8];
1670         
1671         pf->data_types = 0;
1672         
1673         if (fread(bphysics, sizeof(char), 8, pf->fp) != 8)
1674                 error = 1;
1675         
1676         if (!error && strncmp(bphysics, "BPHYSICS", 8))
1677                 error = 1;
1678
1679         if (!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp))
1680                 error = 1;
1681
1682         pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
1683         pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
1684         
1685         /* if there was an error set file as it was */
1686         if (error)
1687                 fseek(pf->fp, 0, SEEK_SET);
1688
1689         return !error;
1690 }
1691 static int ptcache_file_header_begin_write(PTCacheFile *pf)
1692 {
1693         const char *bphysics = "BPHYSICS";
1694         unsigned int typeflag = pf->type + pf->flag;
1695         
1696         if (fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
1697                 return 0;
1698
1699         if (!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp))
1700                 return 0;
1701         
1702         return 1;
1703 }
1704
1705 /* Data pointer handling */
1706 int BKE_ptcache_data_size(int data_type)
1707 {
1708         return ptcache_data_size[data_type];
1709 }
1710
1711 static void ptcache_file_pointers_init(PTCacheFile *pf)
1712 {
1713         int data_types = pf->data_types;
1714
1715         pf->cur[BPHYS_DATA_INDEX] =             (data_types & (1<<BPHYS_DATA_INDEX))    ?               &pf->data.index : NULL;
1716         pf->cur[BPHYS_DATA_LOCATION] =  (data_types & (1<<BPHYS_DATA_LOCATION)) ?               &pf->data.loc   : NULL;
1717         pf->cur[BPHYS_DATA_VELOCITY] =  (data_types & (1<<BPHYS_DATA_VELOCITY)) ?               &pf->data.vel   : NULL;
1718         pf->cur[BPHYS_DATA_ROTATION] =  (data_types & (1<<BPHYS_DATA_ROTATION)) ?               &pf->data.rot   : NULL;
1719         pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))?               &pf->data.ave   : NULL;
1720         pf->cur[BPHYS_DATA_SIZE] =              (data_types & (1<<BPHYS_DATA_SIZE))             ?               &pf->data.size  : NULL;
1721         pf->cur[BPHYS_DATA_TIMES] =             (data_types & (1<<BPHYS_DATA_TIMES))    ?               &pf->data.times : NULL;
1722         pf->cur[BPHYS_DATA_BOIDS] =             (data_types & (1<<BPHYS_DATA_BOIDS))    ?               &pf->data.boids : NULL;
1723 }
1724
1725 /* Check to see if point number "index" is in pm, uses binary search for index data. */
1726 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
1727 {
1728         if (pm->data[BPHYS_DATA_INDEX]) {
1729                 unsigned int *data = pm->data[BPHYS_DATA_INDEX];
1730                 unsigned int mid, low = 0, high = pm->totpoint - 1;
1731
1732                 if (index < *data || index > *(data+high))
1733                         return -1;
1734
1735                 /* check simple case for continuous indexes first */
1736                 if (index-*data < high && data[index-*data] == index)
1737                         return index-*data;
1738
1739                 while (low <= high) {
1740                         mid= (low + high)/2;
1741
1742                         if (data[mid] > index)
1743                                 high = mid - 1;
1744                         else if (data[mid] < index)
1745                                 low = mid + 1;
1746                         else
1747                                 return mid;
1748                 }
1749
1750                 return -1;
1751         }
1752         else {
1753                 return (index < pm->totpoint ? index : -1);
1754         }
1755 }
1756
1757 void BKE_ptcache_mem_pointers_init(PTCacheMem *pm)
1758 {
1759         int data_types = pm->data_types;
1760         int i;
1761
1762         for (i=0; i<BPHYS_TOT_DATA; i++)
1763                 pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL);
1764 }
1765
1766 void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
1767 {
1768         int i;
1769
1770         for (i=0; i<BPHYS_TOT_DATA; i++) {
1771                 if (pm->cur[i])
1772                         pm->cur[i] = (char *)pm->cur[i] + ptcache_data_size[i];
1773         }
1774 }
1775 int  BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
1776 {
1777         int data_types = pm->data_types;
1778         int i, index = BKE_ptcache_mem_index_find(pm, point_index);
1779
1780         if (index < 0) {
1781                 /* Can't give proper location without reallocation, so don't give any location.
1782                  * Some points will be cached improperly, but this only happens with simulation
1783                  * steps bigger than cache->step, so the cache has to be recalculated anyways
1784                  * at some point.
1785                  */
1786                 return 0;
1787         }
1788
1789         for (i=0; i<BPHYS_TOT_DATA; i++)
1790                 pm->cur[i] = data_types & (1<<i) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL;
1791
1792         return 1;
1793 }
1794 static void ptcache_data_alloc(PTCacheMem *pm)
1795 {
1796         int data_types = pm->data_types;
1797         int totpoint = pm->totpoint;
1798         int i;
1799
1800         for (i=0; i<BPHYS_TOT_DATA; i++) {
1801                 if (data_types & (1<<i))
1802                         pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
1803         }
1804 }
1805 static void ptcache_data_free(PTCacheMem *pm)
1806 {
1807         void **data = pm->data;
1808         int i;
1809
1810         for (i=0; i<BPHYS_TOT_DATA; i++) {
1811                 if (data[i])
1812                         MEM_freeN(data[i]);
1813         }
1814 }
1815 static void ptcache_data_copy(void *from[], void *to[])
1816 {
1817         int i;
1818         for (i=0; i<BPHYS_TOT_DATA; i++) {
1819         /* note, durian file 03.4b_comp crashes if to[i] is not tested
1820          * its NULL, not sure if this should be fixed elsewhere but for now its needed */
1821                 if (from[i] && to[i])
1822                         memcpy(to[i], from[i], ptcache_data_size[i]);
1823         }
1824 }
1825
1826 static void ptcache_extra_free(PTCacheMem *pm)
1827 {
1828         PTCacheExtra *extra = pm->extradata.first;
1829
1830         if (extra) {
1831                 for (; extra; extra=extra->next) {
1832                         if (extra->data)
1833                                 MEM_freeN(extra->data);
1834                 }
1835
1836                 BLI_freelistN(&pm->extradata);
1837         }
1838 }
1839 static int ptcache_old_elemsize(PTCacheID *pid)
1840 {
1841         if (pid->type==PTCACHE_TYPE_SOFTBODY)
1842                 return 6 * sizeof(float);
1843         else if (pid->type==PTCACHE_TYPE_PARTICLES)
1844                 return sizeof(ParticleKey);
1845         else if (pid->type==PTCACHE_TYPE_CLOTH)
1846                 return 9 * sizeof(float);
1847
1848         return 0;
1849 }
1850
1851 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
1852 {
1853         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
1854                 int cfra1=frame, cfra2=frame+1;
1855
1856                 while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1))
1857                         cfra1--;
1858
1859                 if (cfra1 < pid->cache->startframe)
1860                         cfra1 = 0;
1861
1862                 while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2))
1863                         cfra2++;
1864
1865                 if (cfra2 > pid->cache->endframe)
1866                         cfra2 = 0;
1867
1868                 if (cfra1 && !cfra2) {
1869                         *fra1 = 0;
1870                         *fra2 = cfra1;
1871                 }
1872                 else {
1873                         *fra1 = cfra1;
1874                         *fra2 = cfra2;
1875                 }
1876         }
1877         else if (pid->cache->mem_cache.first) {
1878                 PTCacheMem *pm = pid->cache->mem_cache.first;
1879                 PTCacheMem *pm2 = pid->cache->mem_cache.last;
1880
1881                 while (pm->next && pm->next->frame <= frame)
1882                         pm= pm->next;
1883
1884                 if (pm2->frame < frame) {
1885                         pm2 = NULL;
1886                 }
1887                 else {
1888                         while (pm2->prev && pm2->prev->frame > frame) {
1889                                 pm2= pm2->prev;
1890                         }
1891                 }
1892
1893                 if (!pm2) {
1894                         *fra1 = 0;
1895                         *fra2 = pm->frame;
1896                 }
1897                 else {
1898                         *fra1 = pm->frame;
1899                         *fra2 = pm2->frame;
1900                 }
1901         }
1902 }
1903
1904 static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
1905 {
1906         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1907         PTCacheMem *pm = NULL;
1908         unsigned int i, error = 0;
1909
1910         if (pf == NULL)
1911                 return NULL;
1912
1913         if (!ptcache_file_header_begin_read(pf))
1914                 error = 1;
1915
1916         if (!error && (pf->type != pid->type || !pid->read_header(pf)))
1917                 error = 1;
1918
1919         if (!error) {
1920                 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1921
1922                 pm->totpoint = pf->totpoint;
1923                 pm->data_types = pf->data_types;
1924                 pm->frame = pf->frame;
1925
1926                 ptcache_data_alloc(pm);
1927
1928                 if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
1929                         for (i=0; i<BPHYS_TOT_DATA; i++) {
1930                                 unsigned int out_len = pm->totpoint*ptcache_data_size[i];
1931                                 if (pf->data_types & (1<<i))
1932                                         ptcache_file_compressed_read(pf, (unsigned char *)(pm->data[i]), out_len);
1933                         }
1934                 }
1935                 else {
1936                         BKE_ptcache_mem_pointers_init(pm);
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, pm->cur);
1945                                 BKE_ptcache_mem_pointers_incr(pm);
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], "Pointcache extradata->data");
1961
1962                         if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS)
1963                                 ptcache_file_compressed_read(pf, (unsigned char *)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]);
1964                         else
1965                                 ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
1966
1967                         BLI_addtail(&pm->extradata, extra);
1968                 }
1969         }
1970
1971         if (error && pm) {
1972                 ptcache_data_free(pm);
1973                 ptcache_extra_free(pm);
1974                 MEM_freeN(pm);
1975                 pm = NULL;
1976         }
1977
1978         ptcache_file_close(pf);
1979
1980         if (error && G.debug & G_DEBUG)
1981                 printf("Error reading from disk cache\n");
1982         
1983         return pm;
1984 }
1985 static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
1986 {
1987         PTCacheFile *pf = NULL;
1988         unsigned int i, error = 0;
1989         
1990         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame);
1991
1992         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
1993
1994         if (pf==NULL) {
1995                 if (G.debug & G_DEBUG)
1996                         printf("Error opening disk cache file for writing\n");
1997                 return 0;
1998         }
1999
2000         pf->data_types = pm->data_types;
2001         pf->totpoint = pm->totpoint;
2002         pf->type = pid->type;
2003         pf->flag = 0;
2004         
2005         if (pm->extradata.first)
2006                 pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
2007         
2008         if (pid->cache->compression)
2009                 pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
2010
2011         if (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))
2012                 error = 1;
2013
2014         if (!error) {
2015                 if (pid->cache->compression) {
2016                         for (i=0; i<BPHYS_TOT_DATA; i++) {
2017                                 if (pm->data[i]) {
2018                                         unsigned int in_len = pm->totpoint*ptcache_data_size[i];
2019                                         unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
2020                                         ptcache_file_compressed_write(pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression);
2021                                         MEM_freeN(out);
2022                                 }
2023                         }
2024                 }
2025                 else {
2026                         BKE_ptcache_mem_pointers_init(pm);
2027                         ptcache_file_pointers_init(pf);
2028
2029                         for (i=0; i<pm->totpoint; i++) {
2030                                 ptcache_data_copy(pm->cur, pf->cur);
2031                                 if (!ptcache_file_data_write(pf)) {
2032                                         error = 1;
2033                                         break;
2034                                 }
2035                                 BKE_ptcache_mem_pointers_incr(pm);
2036                         }
2037                 }
2038         }
2039
2040         if (!error && pm->extradata.first) {
2041                 PTCacheExtra *extra = pm->extradata.first;
2042
2043                 for (; extra; extra=extra->next) {
2044                         if (extra->data == NULL || extra->totdata == 0)
2045                                 continue;
2046
2047                         ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
2048                         ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
2049
2050                         if (pid->cache->compression) {
2051                                 unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
2052                                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
2053                                 ptcache_file_compressed_write(pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression);
2054                                 MEM_freeN(out);
2055                         }
2056                         else {
2057                                 ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
2058                         }
2059                 }
2060         }
2061
2062         ptcache_file_close(pf);
2063         
2064         if (error && G.debug & G_DEBUG)
2065                 printf("Error writing to disk cache\n");
2066
2067         return error==0;
2068 }
2069
2070 static int ptcache_read_stream(PTCacheID *pid, int cfra)
2071 {
2072         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
2073         int error = 0;
2074
2075         if (pid->read_stream == NULL)
2076                 return 0;
2077
2078         if (pf == NULL) {
2079                 if (G.debug & G_DEBUG)
2080                         printf("Error opening disk cache file for reading\n");
2081                 return 0;
2082         }
2083
2084         if (!ptcache_file_header_begin_read(pf))
2085                 error = 1;
2086
2087         if (!error && (pf->type != pid->type || !pid->read_header(pf)))
2088                 error = 1;
2089
2090         if (!error && pf->totpoint != pid->totpoint(pid->calldata, cfra))
2091                 error = 1;
2092
2093         if (!error) {
2094                 ptcache_file_pointers_init(pf);
2095
2096                 // we have stream reading here
2097                 if (!pid->read_stream(pf, pid->calldata))
2098                         error = 1;
2099         }
2100
2101         ptcache_file_close(pf);
2102         
2103         return error == 0;
2104 }
2105 static int ptcache_read(PTCacheID *pid, int cfra)
2106 {
2107         PTCacheMem *pm = NULL;
2108         int i;
2109         int *index = &i;
2110
2111         /* get a memory cache to read from */
2112         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2113                 pm = ptcache_disk_frame_to_mem(pid, cfra);
2114         }
2115         else {
2116                 pm = pid->cache->mem_cache.first;
2117                 
2118                 while (pm && pm->frame != cfra)
2119                         pm = pm->next;
2120         }
2121
2122         /* read the cache */
2123         if (pm) {
2124                 int totpoint = pm->totpoint;
2125
2126                 if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
2127                         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra));
2128
2129                 BKE_ptcache_mem_pointers_init(pm);
2130
2131                 for (i=0; i<totpoint; i++) {
2132                         if (pm->data_types & (1<<BPHYS_DATA_INDEX))
2133                                 index = pm->cur[BPHYS_DATA_INDEX];
2134
2135                         pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL);
2136                 
2137                         BKE_ptcache_mem_pointers_incr(pm);
2138                 }
2139
2140                 if (pid->read_extra_data && pm->extradata.first)
2141                         pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
2142
2143                 /* clean up temporary memory cache */
2144                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2145                         ptcache_data_free(pm);
2146                         ptcache_extra_free(pm);
2147                         MEM_freeN(pm);
2148                 }
2149         }
2150
2151         return 1;
2152 }
2153 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
2154 {
2155         PTCacheMem *pm = NULL;
2156         int i;
2157         int *index = &i;
2158
2159         /* get a memory cache to read from */
2160         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2161                 pm = ptcache_disk_frame_to_mem(pid, cfra2);
2162         }
2163         else {
2164                 pm = pid->cache->mem_cache.first;
2165                 
2166                 while (pm && pm->frame != cfra2)
2167                         pm = pm->next;
2168         }
2169
2170         /* read the cache */
2171         if (pm) {
2172                 int totpoint = pm->totpoint;
2173
2174                 if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
2175                         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra));
2176
2177                 BKE_ptcache_mem_pointers_init(pm);
2178
2179                 for (i=0; i<totpoint; i++) {
2180                         if (pm->data_types & (1<<BPHYS_DATA_INDEX))
2181                                 index = pm->cur[BPHYS_DATA_INDEX];
2182
2183                         pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL);
2184                         BKE_ptcache_mem_pointers_incr(pm);
2185                 }
2186
2187                 if (pid->interpolate_extra_data && pm->extradata.first)
2188                         pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
2189
2190                 /* clean up temporary memory cache */
2191                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2192                         ptcache_data_free(pm);
2193                         ptcache_extra_free(pm);
2194                         MEM_freeN(pm);
2195                 }
2196         }
2197
2198         return 1;
2199 }
2200 /* reads cache from disk or memory */
2201 /* possible to get old or interpolated result */
2202 int BKE_ptcache_read(PTCacheID *pid, float cfra)
2203 {
2204         int cfrai = (int)floor(cfra), cfra1=0, cfra2=0;
2205         int ret = 0;
2206
2207         /* nothing to read to */
2208         if (pid->totpoint(pid->calldata, cfrai) == 0)
2209                 return 0;
2210
2211         if (pid->cache->flag & PTCACHE_READ_INFO) {
2212                 pid->cache->flag &= ~PTCACHE_READ_INFO;
2213                 ptcache_read(pid, 0);
2214         }
2215
2216         /* first check if we have the actual frame cached */
2217         if (cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai))
2218                 cfra1 = cfrai;
2219
2220         /* no exact cache frame found so try to find cached frames around cfra */
2221         if (cfra1 == 0)
2222                 ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
2223
2224         if (cfra1 == 0 && cfra2 == 0)
2225                 return 0;
2226
2227         /* don't read old cache if already simulated past cached frame */
2228         if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
2229                 return 0;
2230         if (cfra1 && cfra1 == cfra2)
2231                 return 0;
2232
2233         if (cfra1) {
2234                 
2235                 if (pid->read_stream) {
2236                         if (!ptcache_read_stream(pid, cfra1))
2237                                 return 0;
2238                 }
2239                 else if (pid->read_point)
2240                         ptcache_read(pid, cfra1);
2241         }
2242
2243         if (cfra2) {
2244                 
2245                 if (pid->read_stream) {
2246                         if (!ptcache_read_stream(pid, cfra2))
2247                                 return 0;
2248                 }
2249                 else if (pid->read_point) {
2250                         if (cfra1 && cfra2 && pid->interpolate_point)
2251                                 ptcache_interpolate(pid, cfra, cfra1, cfra2);
2252                         else
2253                                 ptcache_read(pid, cfra2);
2254                 }
2255         }
2256
2257         if (cfra1)
2258                 ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT);
2259         else if (cfra2) {
2260                 ret = PTCACHE_READ_OLD;
2261                 pid->cache->simframe = cfra2;
2262         }
2263
2264         cfrai = (int)cfra;
2265         /* clear invalid cache frames so that better stuff can be simulated */
2266         if (pid->cache->flag & PTCACHE_OUTDATED) {
2267                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
2268         }
2269         else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
2270                 if (cfra <= pid->cache->last_exact)
2271                         pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2272
2273                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact));
2274         }
2275
2276         return ret;
2277 }
2278 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
2279 {
2280         PTCacheFile *pf = NULL;
2281         int error = 0;
2282         
2283         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
2284
2285         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
2286
2287         if (pf==NULL) {
2288                 if (G.debug & G_DEBUG)
2289                         printf("Error opening disk cache file for writing\n");
2290                 return 0;
2291         }
2292
2293         pf->data_types = pid->data_types;
2294         pf->totpoint = totpoint;
2295         pf->type = pid->type;
2296         pf->flag = 0;
2297
2298         if (!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)))
2299                 error = 1;
2300
2301         if (!error && pid->write_stream)
2302                 pid->write_stream(pf, pid->calldata);
2303
2304         ptcache_file_close(pf);
2305
2306         if (error && G.debug & G_DEBUG)
2307                 printf("Error writing to disk cache\n");
2308
2309         return error == 0;
2310 }
2311 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
2312 {
2313         PointCache *cache = pid->cache;
2314         PTCacheMem *pm=NULL, *pm2=NULL;
2315         int totpoint = pid->totpoint(pid->calldata, cfra);
2316         int i, error = 0;
2317
2318         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2319
2320         pm->totpoint = pid->totwrite(pid->calldata, cfra);
2321         pm->data_types = cfra ? pid->data_types : pid->info_types;
2322
2323         ptcache_data_alloc(pm);
2324         BKE_ptcache_mem_pointers_init(pm);
2325
2326         if (overwrite) {
2327                 if (cache->flag & PTCACHE_DISK_CACHE) {
2328                         int fra = cfra-1;
2329
2330                         while (fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra))
2331                                 fra--;
2332                         
2333                         pm2 = ptcache_disk_frame_to_mem(pid, fra);
2334                 }
2335                 else
2336                         pm2 = cache->mem_cache.last;
2337         }
2338
2339         if (pid->write_point) {
2340                 for (i=0; i<totpoint; i++) {
2341                         int write = pid->write_point(i, pid->calldata, pm->cur, cfra);
2342                         if (write) {
2343                                 BKE_ptcache_mem_pointers_incr(pm);
2344
2345                                 /* newly born particles have to be copied to previous cached frame */
2346                                 if (overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2))
2347                                         pid->write_point(i, pid->calldata, pm2->cur, cfra);
2348                         }
2349                 }
2350         }
2351
2352         if (pid->write_extra_data)
2353                 pid->write_extra_data(pid->calldata, pm, cfra);
2354
2355         pm->frame = cfra;
2356
2357         if (cache->flag & PTCACHE_DISK_CACHE) {
2358                 error += !ptcache_mem_frame_to_disk(pid, pm);
2359
2360                 // if (pm) /* pm is always set */
2361                 {
2362                         ptcache_data_free(pm);
2363                         ptcache_extra_free(pm);
2364                         MEM_freeN(pm);
2365                 }
2366
2367                 if (pm2) {
2368                         error += !ptcache_mem_frame_to_disk(pid, pm2);
2369                         ptcache_data_free(pm2);
2370                         ptcache_extra_free(pm2);
2371                         MEM_freeN(pm2);
2372                 }
2373         }
2374         else {
2375                 BLI_addtail(&cache->mem_cache, pm);
2376         }
2377
2378         return error;
2379 }
2380 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
2381 {
2382         PointCache *cache = pid->cache;
2383         int ofra = 0, efra = cache->endframe;
2384
2385         /* allways start from scratch on the first frame */
2386         if (cfra && cfra == cache->startframe) {
2387                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
2388                 cache->flag &= ~PTCACHE_REDO_NEEDED;
2389                 return 1;
2390         }
2391
2392         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2393                 if (cfra==0 && cache->startframe > 0)
2394                         return 1;
2395
2396                                 /* find last cached frame */
2397                 while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
2398                         efra--;
2399
2400                 /* find second last cached frame */
2401                 ofra = efra-1;
2402                 while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
2403                         ofra--;
2404         }
2405         else {
2406                 PTCacheMem *pm = cache->mem_cache.last;
2407                 /* don't write info file in memory */
2408                 if (cfra == 0)
2409                         return 0;
2410
2411                 if (pm == NULL)
2412                         return 1;
2413
2414                 efra = pm->frame;
2415                 ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
2416         }
2417
2418         if (efra >= cache->startframe && cfra > efra) {
2419                 if (ofra >= cache->startframe && efra - ofra < cache->step) {
2420                         /* overwrite previous frame */
2421                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
2422                         *overwrite = 1;
2423                 }
2424                 return 1;
2425         }
2426
2427         return 0;
2428 }
2429 /* writes cache to disk or memory */
2430 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
2431 {
2432         PointCache *cache = pid->cache;
2433         int totpoint = pid->totpoint(pid->calldata, cfra);
2434         int overwrite = 0, error = 0;
2435
2436         if (totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
2437                 return 0;
2438
2439         if (ptcache_write_needed(pid, cfra, &overwrite)==0)
2440                 return 0;
2441
2442         if (pid->write_stream) {
2443                 ptcache_write_stream(pid, cfra, totpoint);
2444         }
2445         else if (pid->write_point) {
2446                 error += ptcache_write(pid, cfra, overwrite);
2447         }
2448
2449         /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
2450         if (cfra - cache->last_exact == 1 || cfra == cache->startframe) {
2451                 cache->last_exact = cfra;
2452                 cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2453         }
2454         /* Don't mark skipped when writing info file (frame 0) */
2455         else if (cfra)
2456                 cache->flag |= PTCACHE_FRAMES_SKIPPED;
2457
2458         /* Update timeline cache display */
2459         if (cfra && cache->cached_frames)
2460                 cache->cached_frames[cfra-cache->startframe] = 1;
2461
2462         BKE_ptcache_update_info(pid);
2463
2464         return !error;
2465 }
2466 /* youll need to close yourself after!
2467  * mode - PTCACHE_CLEAR_ALL, 
2468  */
2469
2470 /* Clears & resets */
2471 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
2472 {
2473         unsigned int len; /* store the length of the string */
2474         unsigned int sta, end;
2475
2476         /* mode is same as fopen's modes */
2477         DIR *dir; 
2478         struct dirent *de;
2479         char path[MAX_PTCACHE_PATH];
2480         char filename[MAX_PTCACHE_FILE];
2481         char path_full[MAX_PTCACHE_FILE];
2482         char ext[MAX_PTCACHE_PATH];
2483
2484         if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED)
2485                 return;
2486
2487         if (pid->cache->flag & PTCACHE_IGNORE_CLEAR)
2488                 return;
2489
2490         sta = pid->cache->startframe;
2491         end = pid->cache->endframe;
2492
2493 #ifndef DURIAN_POINTCACHE_LIB_OK
2494         /* don't allow clearing for linked objects */
2495         if (pid->ob->id.lib)
2496                 return;
2497 #endif
2498
2499         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
2500         
2501         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
2502         switch (mode) {
2503         case PTCACHE_CLEAR_ALL:
2504         case PTCACHE_CLEAR_BEFORE:
2505         case PTCACHE_CLEAR_AFTER:
2506                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2507                         ptcache_path(pid, path);
2508                         
2509                         len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
2510                         
2511                         dir = opendir(path);
2512                         if (dir==NULL)
2513                                 return;
2514
2515                         BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
2516                         
2517                         while ((de = readdir(dir)) != NULL) {
2518                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2519                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2520                                                 if (mode == PTCACHE_CLEAR_ALL) {
2521                                                         pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2522                                                         BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2523                                                         BLI_delete(path_full, false, false);
2524                                                 }
2525                                                 else {
2526                                                         /* read the number of the file */
2527                                                         unsigned int frame, len2 = (int)strlen(de->d_name);
2528                                                         char num[7];
2529
2530                                                         if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2531                                                                 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2532                                                                 frame = atoi(num);
2533                                                                 
2534                                                                 if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
2535                                                                     (mode == PTCACHE_CLEAR_AFTER && frame > cfra))
2536                                                                 {
2537                                                                         
2538                                                                         BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2539                                                                         BLI_delete(path_full, false, false);
2540                                                                         if (pid->cache->cached_frames && frame >=sta && frame <= end)
2541                                                                                 pid->cache->cached_frames[frame-sta] = 0;
2542                                                                 }
2543                                                         }
2544                                                 }
2545                                         }
2546                                 }
2547                         }
2548                         closedir(dir);
2549
2550                         if (mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames)
2551                                 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2552                 }
2553                 else {
2554                         PTCacheMem *pm= pid->cache->mem_cache.first;
2555                         PTCacheMem *link= NULL;
2556
2557                         if (mode == PTCACHE_CLEAR_ALL) {
2558                                 /*we want startframe if the cache starts before zero*/
2559                                 pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2560                                 for (; pm; pm=pm->next) {
2561                                         ptcache_data_free(pm);
2562                                         ptcache_extra_free(pm);
2563                                 }
2564                                 BLI_freelistN(&pid->cache->mem_cache);
2565
2566                                 if (pid->cache->cached_frames) 
2567                                         memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2568                         }
2569                         else {
2570                                 while (pm) {
2571                                         if ((mode == PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
2572                                             (mode == PTCACHE_CLEAR_AFTER && pm->frame > cfra))
2573                                         {
2574                                                 link = pm;
2575                                                 if (pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end)
2576                                                         pid->cache->cached_frames[pm->frame-sta] = 0;
2577                                                 ptcache_data_free(pm);
2578                                                 ptcache_extra_free(pm);
2579                                                 pm = pm->next;
2580                                                 BLI_freelinkN(&pid->cache->mem_cache, link);
2581                                         }
2582                                         else
2583                                                 pm = pm->next;
2584                                 }
2585                         }
2586                 }
2587                 break;
2588                 
2589         case PTCACHE_CLEAR_FRAME:
2590                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2591                         if (BKE_ptcache_id_exist(pid, cfra)) {
2592                                 ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
2593                                 BLI_delete(filename, false, false);
2594                         }
2595                 }
2596                 else {
2597                         PTCacheMem *pm = pid->cache->mem_cache.first;
2598
2599                         for (; pm; pm=pm->next) {
2600                                 if (pm->frame == cfra) {
2601                                         ptcache_data_free(pm);
2602                                         ptcache_extra_free(pm);
2603                                         BLI_freelinkN(&pid->cache->mem_cache, pm);
2604                                         break;
2605                                 }
2606                         }
2607                 }
2608                 if (pid->cache->cached_frames && cfra >= sta && cfra <= end)
2609                         pid->cache->cached_frames[cfra-sta] = 0;
2610                 break;
2611         }
2612
2613         BKE_ptcache_update_info(pid);
2614 }
2615 int  BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
2616 {
2617         if (!pid->cache)
2618                 return 0;
2619
2620         if (cfra<pid->cache->startframe || cfra > pid->cache->endframe)
2621                 return 0;
2622
2623         if (pid->cache->cached_frames &&        pid->cache->cached_frames[cfra-pid->cache->startframe]==0)
2624                 return 0;
2625         
2626         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2627                 char filename[MAX_PTCACHE_FILE];
2628                 
2629                 ptcache_filename(pid, filename, cfra, 1, 1);
2630
2631                 return BLI_exists(filename);
2632         }
2633         else {
2634                 PTCacheMem *pm = pid->cache->mem_cache.first;
2635
2636                 for (; pm; pm=pm->next) {
2637                         if (pm->frame==cfra)
2638                                 return 1;
2639                 }
2640                 return 0;
2641         }
2642 }
2643 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
2644 {
2645         /* Object *ob; */ /* UNUSED */
2646         PointCache *cache;
2647         /* float offset; unused for now */
2648         float time, nexttime;
2649
2650         /* TODO: this has to be sorted out once bsystem_time gets redone, */
2651         /*       now caches can handle interpolating etc. too - jahka */
2652
2653         /* time handling for point cache:
2654          * - simulation time is scaled by result of bsystem_time
2655          * - for offsetting time only time offset is taken into account, since
2656          *   that's always the same and can't be animated. a timeoffset which
2657          *   varies over time is not simple to support.
2658          * - field and motion blur offsets are currently ignored, proper solution
2659          *   is probably to interpolate results from two frames for that ..
2660          */
2661
2662         /* ob= pid->ob; */ /* UNUSED */
2663         cache= pid->cache;
2664
2665         if (timescale) {
2666                 time= BKE_scene_frame_get(scene);
2667                 nexttime = BKE_scene_frame_get_from_ctime(scene, CFRA + 1.0f);
2668                 
2669                 *timescale= MAX2(nexttime - time, 0.0f);
2670         }
2671
2672         if (startframe && endframe) {
2673                 *startframe= cache->startframe;
2674                 *endframe= cache->endframe;
2675
2676                 /* TODO: time handling with object offsets and simulated vs. cached
2677                  * particles isn't particularly easy, so for now what you see is what
2678                  * you get. In the future point cache could handle the whole particle
2679                  * system timing. */
2680 #if 0
2681                 if ((ob->partype & PARSLOW)==0) {
2682                         offset= ob->sf;
2683
2684                         *startframe += (int)(offset+0.5f);
2685                         *endframe += (int)(offset+0.5f);
2686                 }
2687 #endif
2688         }
2689
2690         /* verify cached_frames array is up to date */
2691         if (cache->cached_frames) {
2692                 if (MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) {
2693                         MEM_freeN(cache->cached_frames);
2694                         cache->cached_frames = NULL;
2695                 }
2696         }
2697
2698         if (cache->cached_frames==NULL && cache->endframe > cache->startframe) {
2699                 unsigned int sta=cache->startframe;
2700                 unsigned int end=cache->endframe;
2701
2702                 cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array");
2703
2704                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2705                         /* mode is same as fopen's modes */
2706                         DIR *dir; 
2707                         struct dirent *de;
2708                         char path[MAX_PTCACHE_PATH];
2709                         char filename[MAX_PTCACHE_FILE];
2710                         char ext[MAX_PTCACHE_PATH];
2711                         unsigned int len; /* store the length of the string */
2712
2713                         ptcache_path(pid, path);
2714                         
2715                         len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */
2716                         
2717                         dir = opendir(path);
2718                         if (dir==NULL)
2719                                 return;
2720
2721                         BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
2722                         
2723                         while ((de = readdir(dir)) != NULL) {
2724                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2725                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2726                                                 /* read the number of the file */
2727                                                 unsigned int frame, len2 = (int)strlen(de->d_name);
2728                                                 char num[7];
2729
2730                                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2731                                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2732                                                         frame = atoi(num);
2733                                                         
2734                                                         if (frame >= sta && frame <= end)
2735                                                                 cache->cached_frames[frame-sta] = 1;
2736                                                 }
2737                                         }
2738                                 }
2739                         }
2740                         closedir(dir);
2741                 }
2742                 else {
2743                         PTCacheMem *pm= pid->cache->mem_cache.first;
2744
2745                         while (pm) {
2746                                 if (pm->frame >= sta && pm->frame <= end)
2747                                         cache->cached_frames[pm->frame-sta] = 1;
2748                                 pm = pm->next;
2749                         }
2750                 }
2751         }
2752 }
2753 int  BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
2754 {
2755         PointCache *cache;
2756         int reset, clear, after;
2757
2758         if (!pid->cache)
2759                 return 0;
2760
2761         cache= pid->cache;
2762         reset= 0;
2763         clear= 0;
2764         after= 0;
2765
2766         if (mode == PTCACHE_RESET_DEPSGRAPH) {
2767                 if (!(cache->flag & PTCACHE_BAKED)) {
2768
2769                         after= 1;
2770                 }
2771
2772                 cache->flag |= PTCACHE_OUTDATED;
2773         }
2774         else if (mode == PTCACHE_RESET_BAKED) {
2775                 cache->flag |= PTCACHE_OUTDATED;
2776         }
2777         else if (mode == PTCACHE_RESET_OUTDATED) {
2778                 reset = 1;
2779
2780                 if (cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
2781                         clear= 1;
2782                         cache->flag &= ~PTCACHE_OUTDATED;
2783                 }
2784         }
2785
2786         if (reset) {
2787                 BKE_ptcache_invalidate(cache);
2788                 cache->flag &= ~PTCACHE_REDO_NEEDED;
2789
2790                 if (pid->type == PTCACHE_TYPE_CLOTH)
2791                         cloth_free_modifier(pid->calldata);
2792                 else if (pid->type == PTCACHE_TYPE_SOFTBODY)
2793                         sbFreeSimulation(pid->calldata);
2794                 else if (pid->type == PTCACHE_TYPE_PARTICLES)
2795                         psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
2796 #if 0
2797                 else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
2798                         smokeModifier_reset(pid->calldata);
2799                 else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
2800                         smokeModifier_reset_turbulence(pid->calldata);
2801 #endif
2802                 else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT)
2803                         dynamicPaint_clearSurface(scene, (DynamicPaintSurface*)pid->calldata);
2804         }
2805         if (clear)
2806                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2807         else if (after)
2808                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
2809
2810         return (reset || clear || after);
2811 }
2812 int  BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
2813 {
2814         PTCacheID pid;
2815         ParticleSystem *psys;
2816         ModifierData *md;
2817         int reset, skip;
2818
2819         reset= 0;
2820         skip= 0;
2821
2822         if (ob->soft) {
2823                 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
2824                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2825         }
2826
2827         for (psys=ob->particlesystem.first; psys; psys=psys->next) {
2828                 /* children or just redo can be calculated without resetting anything */
2829                 if (psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
2830                         skip = 1;
2831                 /* Baked cloth hair has to be checked too, because we don't want to reset */
2832                 /* particles or cloth in that case -jahka */
2833                 else if (psys->clmd) {
2834                         BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
2835                         if (mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
2836                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2837                         else
2838                                 skip = 1;
2839                 }
2840
2841                 if (skip == 0 && psys->part) {
2842                         BKE_ptcache_id_from_particles(&pid, ob, psys);
2843                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2844                 }
2845         }
2846
2847         for (md=ob->modifiers.first; md; md=md->next) {
2848                 if (md->type == eModifierType_Cloth) {
2849                         BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
2850                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2851                 }
2852                 if (md->type == eModifierType_Smoke) {
2853                         SmokeModifierData *smd = (SmokeModifierData *)md;
2854                         if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
2855                                 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md);
2856                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2857                         }
2858                 }
2859                 if (md->type == eModifierType_DynamicPaint) {
2860                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
2861                         if (pmd->canvas) {
2862                                 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
2863
2864                                 for (; surface; surface=surface->next) {
2865                                         BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
2866                                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2867                                 }
2868                         }
2869                 }
2870         }
2871
2872         if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) {
2873                 if (ob->rigidbody_object)
2874                         ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE;
2875                 BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world);
2876                 /* only flag as outdated, resetting should happen on start frame */
2877                 pid.cache->flag |= PTCACHE_OUTDATED;
2878         }
2879
2880         if (ob->type == OB_ARMATURE)
2881                 BIK_clear_cache(ob->pose);
2882
2883         return reset;
2884 }
2885
2886 /* Use this when quitting blender, with unsaved files */
2887 void BKE_ptcache_remove(void)
2888 {
2889         char path[MAX_PTCACHE_PATH];
2890         char path_full[MAX_PTCACHE_PATH];
2891         int rmdir = 1;
2892         
2893         ptcache_path(NULL, path);
2894
2895         if (BLI_exists(path)) {
2896                 /* The pointcache dir exists? - remove all pointcache */
2897
2898                 DIR *dir; 
2899                 struct dirent *de;
2900
2901                 dir = opendir(path);
2902                 if (dir==NULL)
2903                         return;
2904                 
2905                 while ((de = readdir(dir)) != NULL) {
2906                         if ( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
2907                                 /* do nothing */
2908                         }
2909                         else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
2910                                 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2911                                 BLI_delete(path_full, false, false);
2912                         }
2913                         else {
2914                                 rmdir = 0; /* unknown file, don't remove the dir */
2915                         }
2916                 }
2917
2918                 closedir(dir);
2919         }
2920         else {
2921                 rmdir = 0; /* path dosnt exist  */
2922         }
2923         
2924         if (rmdir) {
2925                 BLI_delete(path, true, false);
2926         }
2927 }
2928
2929 /* Point Cache handling */
2930
2931 PointCache *BKE_ptcache_add(ListBase *ptcaches)
2932 {
2933         PointCache *cache;
2934
2935         cache= MEM_callocN(sizeof(PointCache), "PointCache");
2936         cache->startframe= 1;
2937         cache->endframe= 250;
2938         cache->step= 10;
2939         cache->index = -1;
2940
2941         BLI_addtail(ptcaches, cache);
2942
2943         return cache;
2944 }
2945
2946 void BKE_ptcache_free_mem(ListBase *mem_cache)
2947 {
2948         PTCacheMem *pm = mem_cache->first;
2949
2950         if (pm) {
2951                 for (; pm; pm=pm->next) {
2952                         ptcache_data_free(pm);
2953                         ptcache_extra_free(pm);
2954                 }
2955
2956                 BLI_freelistN(mem_cache);
2957         }
2958 }
2959 void BKE_ptcache_free(PointCache *cache)
2960 {
2961         BKE_ptcache_free_mem(&cache->mem_cache);
2962         if (cache->edit && cache->free_edit)
2963                 cache->free_edit(cache->edit);
2964         if (cache->cached_frames)
2965                 MEM_freeN(cache->cached_frames);
2966         MEM_freeN(cache);
2967 }
2968 void BKE_ptcache_free_list(ListBase *ptcaches)
2969 {
2970         PointCache *cache = ptcaches->first;
2971
2972         while (cache) {
2973                 BLI_remlink(ptcaches, cache);
2974                 BKE_ptcache_free(cache);
2975                 cache = ptcaches->first;
2976         }
2977 }
2978
2979 static PointCache *ptcache_copy(PointCache *cache, int copy_data)
2980 {
2981         PointCache *ncache;
2982
2983         ncache= MEM_dupallocN(cache);
2984
2985         ncache->mem_cache.first = NULL;
2986         ncache->mem_cache.last = NULL;
2987
2988         if (copy_data == FALSE) {
2989                 ncache->mem_cache.first = NULL;
2990                 ncache->mem_cache.last = NULL;
2991                 ncache->cached_frames = NULL;
2992
2993                 /* flag is a mix of user settings and simulator/baking state */
2994                 ncache->flag= ncache->flag & (PTCACHE_DISK_CACHE|PTCACHE_EXTERNAL|PTCACHE_IGNORE_LIBPATH);
2995                 ncache->simframe= 0;
2996         }
2997         else {
2998                 PTCacheMem *pm;
2999
3000                 for (pm = cache->mem_cache.first; pm; pm = pm->next) {
3001                         PTCacheMem *pmn = MEM_dupallocN(pm);
3002                         int i;
3003
3004                         for (i = 0; i < BPHYS_TOT_DATA; i++) {
3005                                 if (pmn->data[i])
3006                                         pmn->data[i] = MEM_dupallocN(pm->data[i]);
3007                         }
3008
3009                         BKE_ptcache_mem_pointers_init(pm);
3010
3011                         BLI_addtail(&ncache->mem_cache, pmn);
3012                 }
3013
3014                 if (ncache->cached_frames)
3015                         ncache->cached_frames = MEM_dupallocN(cache->cached_frames);
3016         }
3017
3018         /* hmm, should these be copied over instead? */
3019         ncache->edit = NULL;
3020
3021         return ncache;
3022 }
3023
3024 /* returns first point cache */
3025 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old, int copy_data)
3026 {
3027         PointCache *cache = ptcaches_old->first;
3028
3029         ptcaches_new->first = ptcaches_new->last = NULL;
3030
3031         for (; cache; cache=cache->next)
3032                 BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data));
3033
3034         return ptcaches_new->first;
3035 }
3036
3037 /* Disabled this code; this is being called on scene_update_tagged, and that in turn gets called on 
3038  * every user action changing stuff, and then it runs a complete bake??? (ton) */
3039
3040 /* Baking */
3041 void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
3042 {
3043         PTCacheBaker baker;
3044
3045         baker.bake=0;
3046         baker.break_data=NULL;
3047         baker.break_test=NULL;
3048         baker.pid=NULL;
3049         baker.progressbar=NULL;
3050         baker.progressend=NULL;
3051         baker.progresscontext=NULL;
3052         baker.render=0;
3053         baker.anim_init = 0;
3054         baker.main=bmain;
3055         baker.scene=scene;
3056         baker.quick_step=scene->physics_settings.quick_cache_step;
3057
3058         BKE_ptcache_bake(&baker);
3059 }
3060
3061 /* Simulation thread, no need for interlocks as data written in both threads
3062  * are only unitary integers (I/O assumed to be atomic for them) */
3063 typedef struct {
3064         int break_operation;
3065         int thread_ended;
3066         int endframe;
3067         int step;
3068         int *cfra_ptr;
3069         Main *main;
3070         Scene *scene;
3071 } ptcache_bake_data;
3072
3073 static void ptcache_dt_to_str(char *str, double dtime)
3074 {
3075         if (dtime > 60.0) {
3076                 if (dtime > 3600.0)
3077                         sprintf(str, "%ih %im %is", (int)(dtime/3600), ((int)(dtime/60))%60, ((int)dtime) % 60);
3078                 else
3079                         sprintf(str, "%im %is", ((int)(dtime/60))%60, ((int)dtime) % 60);
3080         }
3081         else
3082                 sprintf(str, "%is", ((int)dtime) % 60);
3083 }
3084