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