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