part 1 of cleaning up my little array macro library to be a formal API. also removed...
[blender.git] / source / blender / blenkernel / intern / pointcache.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22 * Contributor(s): Campbell Barton <ideasman42@gmail.com>
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_ID.h"
36 #include "DNA_cloth_types.h"
37 #include "DNA_modifier_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_object_force.h"
40 #include "DNA_particle_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_smoke_types.h"
43
44 #include "BLI_blenlib.h"
45
46 #include "BKE_cloth.h"
47 #include "BKE_depsgraph.h"
48 #include "BKE_global.h"
49 #include "BKE_library.h"
50 #include "BKE_main.h"
51 #include "BKE_modifier.h"
52 #include "BKE_object.h"
53 #include "BKE_particle.h"
54 #include "BKE_pointcache.h"
55 #include "BKE_scene.h"
56 #include "BKE_smoke.h"
57 #include "BKE_softbody.h"
58 #include "BKE_utildefines.h"
59
60 #include "BLI_blenlib.h"
61
62 /* both in intern */
63 #include "smoke_API.h"
64 #include "minilzo.h"
65
66 #include "LzmaLib.h"
67
68
69 /* needed for directory lookup */
70 /* untitled blend's need getpid for a unique name */
71 #ifndef WIN32
72   #include <dirent.h>
73 #include <unistd.h>
74 #else
75 #include <process.h>
76   #include "BLI_winstuff.h"
77 #endif
78
79 static void ptcache_data_to(void **data, int type, int index, void *to);
80 static void ptcache_data_from(void **data, int type, void *from);
81
82 /* Common functions */
83 static int ptcache_read_basic_header(PTCacheFile *pf)
84 {
85         int error=0;
86
87         /* Custom functions should read these basic elements too! */
88         if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp))
89                 error = 1;
90         
91         if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp))
92                 error = 1;
93
94         return !error;
95 }
96 static int ptcache_write_basic_header(PTCacheFile *pf)
97 {
98         /* Custom functions should write these basic elements too! */
99         if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp))
100                 return 0;
101         
102         if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp))
103                 return 0;
104
105         return 1;
106 }
107 /* Softbody functions */
108 static int ptcache_write_softbody(int index, void *soft_v, void **data)
109 {
110         SoftBody *soft= soft_v;
111         BodyPoint *bp = soft->bpoint + index;
112
113         ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos);
114         ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec);
115
116         return 1;
117 }
118 static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data)
119 {
120         SoftBody *soft= soft_v;
121         BodyPoint *bp = soft->bpoint + index;
122
123         if(old_data) {
124                 memcpy(bp->pos, data, 3 * sizeof(float));
125                 memcpy(bp->vec, data + 3, 3 * sizeof(float));
126         }
127         else {
128                 ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos);
129                 ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
130         }
131 }
132 static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
133 {
134         SoftBody *soft= soft_v;
135         BodyPoint *bp = soft->bpoint + index;
136         ParticleKey keys[4];
137         float dfra;
138
139         if(cfra1 == cfra2)
140                 return;
141
142         VECCOPY(keys[1].co, bp->pos);
143         VECCOPY(keys[1].vel, bp->vec);
144
145         if(old_data) {
146                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
147                 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
148         }
149         else
150                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
151
152         dfra = cfra2 - cfra1;
153
154         VecMulf(keys[1].vel, dfra);
155         VecMulf(keys[2].vel, dfra);
156
157         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
158
159         VecMulf(keys->vel, 1.0f / dfra);
160
161         VECCOPY(bp->pos, keys->co);
162         VECCOPY(bp->vec, keys->vel);
163 }
164 static int ptcache_totpoint_softbody(void *soft_v)
165 {
166         SoftBody *soft= soft_v;
167         return soft->totpoint;
168 }
169 /* Particle functions */
170 static int ptcache_write_particle(int index, void *psys_v, void **data)
171 {
172         ParticleSystem *psys= psys_v;
173         ParticleData *pa = psys->particles + index;
174         BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
175         float times[3] = {pa->time, pa->dietime, pa->lifetime};
176
177         if(data[BPHYS_DATA_INDEX]) {
178                 int step = psys->pointcache->step;
179                 /* No need to store unborn or died particles */
180                 if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time)
181                         return 0;
182         }
183         
184         ptcache_data_from(data, BPHYS_DATA_INDEX, &index);
185         ptcache_data_from(data, BPHYS_DATA_LOCATION, pa->state.co);
186         ptcache_data_from(data, BPHYS_DATA_VELOCITY, pa->state.vel);
187         ptcache_data_from(data, BPHYS_DATA_ROTATION, pa->state.rot);
188         ptcache_data_from(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
189         ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size);
190         ptcache_data_from(data, BPHYS_DATA_TIMES, times);
191
192         if(boid)
193                 ptcache_data_from(data, BPHYS_DATA_BOIDS, &boid->data);
194
195         return 1;
196 }
197 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
198 {
199         ptcache_data_to(data, BPHYS_DATA_LOCATION, index, key->co);
200         ptcache_data_to(data, BPHYS_DATA_VELOCITY, index, key->vel);
201         ptcache_data_to(data, BPHYS_DATA_ROTATION, index, key->rot);
202         ptcache_data_to(data, BPHYS_DATA_AVELOCITY, index, key->ave);
203         key->time = time;
204 }
205 static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data)
206 {
207         ParticleSystem *psys= psys_v;
208         ParticleData *pa = psys->particles + index;
209         BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
210
211         if(cfra > pa->state.time)
212                 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
213
214         if(old_data){
215                 /* old format cache */
216                 memcpy(&pa->state, old_data, sizeof(ParticleKey));
217                 return;
218         }
219
220         BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
221
222         if(data[BPHYS_DATA_SIZE])
223                 ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size);
224         
225         if(data[BPHYS_DATA_TIMES]) {
226                 float times[3];
227                 ptcache_data_to(data, BPHYS_DATA_TIMES, 0, &times);
228                 pa->time = times[0];
229                 pa->dietime = times[1];
230                 pa->lifetime = times[2];
231         }
232
233         if(boid)
234                 ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &boid->data);
235
236         /* determine velocity from previous location */
237         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
238                 if(cfra > pa->prev_state.time) {
239                         VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co);
240                         VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
241                 }
242                 else {
243                         VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co);
244                         VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
245                 }
246         }
247
248         /* determine rotation from velocity */
249         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
250                 vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot);
251         }
252 }
253 static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
254 {
255         ParticleSystem *psys= psys_v;
256         ParticleData *pa = psys->particles + index;
257         ParticleKey keys[4];
258         float dfra;
259
260         cfra = MIN2(cfra, pa->dietime);
261         cfra1 = MIN2(cfra1, pa->dietime);
262         cfra2 = MIN2(cfra2, pa->dietime);
263
264         if(cfra1 == cfra2)
265                 return;
266
267         memcpy(keys+1, &pa->state, sizeof(ParticleKey));
268         if(old_data)
269                 memcpy(keys+2, old_data, sizeof(ParticleKey));
270         else
271                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
272
273         dfra = cfra2 - cfra1;
274
275         VecMulf(keys[1].vel, dfra / frs_sec);
276         VecMulf(keys[2].vel, dfra / frs_sec);
277
278         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
279         QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
280
281         VecMulf(pa->state.vel, frs_sec / dfra);
282
283         pa->state.time = cfra;
284 }
285
286 static int ptcache_totpoint_particle(void *psys_v)
287 {
288         ParticleSystem *psys = psys_v;
289         return psys->totpart;
290 }
291 static int ptcache_totwrite_particle(void *psys_v)
292 {
293         ParticleSystem *psys = psys_v;
294         int totwrite = 0;
295
296         /* TODO for later */
297         //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0) {
298         //      ParticleData *pa= psys->particles;
299         //      int p, step = psys->pointcache->step;
300
301         //      for(p=0; p<psys->totpart; p++,pa++)
302         //              totwrite += (pa->time - step > pa->state.time || pa->dietime + step > pa->state.time);
303         //}
304         //else
305                 totwrite= psys->totpart;
306
307         return totwrite;
308 }
309
310 /* Cloth functions */
311 static int ptcache_write_cloth(int index, void *cloth_v, void **data)
312 {
313         ClothModifierData *clmd= cloth_v;
314         Cloth *cloth= clmd->clothObject;
315         ClothVertex *vert = cloth->verts + index;
316
317         ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x);
318         ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v);
319         ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst);
320
321         return 1;
322 }
323 static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data)
324 {
325         ClothModifierData *clmd= cloth_v;
326         Cloth *cloth= clmd->clothObject;
327         ClothVertex *vert = cloth->verts + index;
328         
329         if(old_data) {
330                 memcpy(vert->x, data, 3 * sizeof(float));
331                 memcpy(vert->xconst, data + 3, 3 * sizeof(float));
332                 memcpy(vert->v, data + 6, 3 * sizeof(float));
333         }
334         else {
335                 ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x);
336                 ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v);
337                 ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst);
338         }
339 }
340 static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
341 {
342         ClothModifierData *clmd= cloth_v;
343         Cloth *cloth= clmd->clothObject;
344         ClothVertex *vert = cloth->verts + index;
345         ParticleKey keys[4];
346         float dfra;
347
348         if(cfra1 == cfra2)
349                 return;
350
351         VECCOPY(keys[1].co, vert->x);
352         VECCOPY(keys[1].vel, vert->v);
353
354         if(old_data) {
355                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
356                 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
357         }
358         else
359                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
360
361         dfra = cfra2 - cfra1;
362
363         VecMulf(keys[1].vel, dfra);
364         VecMulf(keys[2].vel, dfra);
365
366         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
367
368         VecMulf(keys->vel, 1.0f / dfra);
369
370         VECCOPY(vert->x, keys->co);
371         VECCOPY(vert->v, keys->vel);
372
373         /* should vert->xconst be interpolated somehow too? - jahka */
374 }
375
376 static int ptcache_totpoint_cloth(void *cloth_v)
377 {
378         ClothModifierData *clmd= cloth_v;
379         return clmd->clothObject->numverts;
380 }
381
382 /* Creating ID's */
383 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
384 {
385         memset(pid, 0, sizeof(PTCacheID));
386
387         pid->ob= ob;
388         pid->calldata= sb;
389         pid->type= PTCACHE_TYPE_SOFTBODY;
390         pid->cache= sb->pointcache;
391         pid->cache_ptr= &sb->pointcache;
392         pid->ptcaches= &sb->ptcaches;
393         pid->totpoint= pid->totwrite= ptcache_totpoint_softbody;
394
395         pid->write_elem= ptcache_write_softbody;
396         pid->write_stream = NULL;
397         pid->read_stream = NULL;
398         pid->read_elem= ptcache_read_softbody;
399         pid->interpolate_elem= ptcache_interpolate_softbody;
400
401         pid->write_header= ptcache_write_basic_header;
402         pid->read_header= ptcache_read_basic_header;
403
404         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
405         pid->info_types= 0;
406
407         pid->stack_index = pid->cache->index;
408 }
409
410 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
411 {
412         memset(pid, 0, sizeof(PTCacheID));
413
414         pid->ob= ob;
415         pid->calldata= psys;
416         pid->type= PTCACHE_TYPE_PARTICLES;
417         pid->stack_index= psys->pointcache->index;
418         pid->cache= psys->pointcache;
419         pid->cache_ptr= &psys->pointcache;
420         pid->ptcaches= &psys->ptcaches;
421
422         if(psys->part->type != PART_HAIR)
423                 pid->flag |= PTCACHE_VEL_PER_SEC;
424
425         pid->write_elem= ptcache_write_particle;
426         pid->write_stream = NULL;
427         pid->read_stream = NULL;
428         pid->read_elem= ptcache_read_particle;
429         pid->interpolate_elem= ptcache_interpolate_particle;
430
431         pid->totpoint= ptcache_totpoint_particle;
432         pid->totwrite= ptcache_totwrite_particle;
433
434         pid->write_header= ptcache_write_basic_header;
435         pid->read_header= ptcache_read_basic_header;
436
437         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
438
439         /* TODO for later */
440         //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0)
441         //      pid->data_types|= (1<<BPHYS_DATA_INDEX);
442
443         if(psys->part->phystype == PART_PHYS_BOIDS)
444                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
445
446         if(psys->part->rotmode || psys->part->avemode)
447                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
448
449         if(psys->part->flag & PART_ROT_DYN)
450                 pid->data_types|= (1<<BPHYS_DATA_ROTATION);
451
452         pid->info_types= (1<<BPHYS_DATA_TIMES);
453 }
454
455 /* Smoke functions */
456 static int ptcache_totpoint_smoke(void *smoke_v)
457 {
458         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
459         SmokeDomainSettings *sds = smd->domain;
460         
461         if(sds->fluid) {
462                 return sds->res[0]*sds->res[1]*sds->res[2];
463         }
464         else
465                 return 0;
466 }
467
468 /* Smoke functions */
469 static int ptcache_totpoint_smoke_turbulence(void *smoke_v)
470 {
471         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
472         SmokeDomainSettings *sds = smd->domain;
473         
474         if(sds->wt) {
475                 return sds->res_wt[0]*sds->res_wt[1]*sds->res_wt[2];
476         }
477         else
478                 return 0;
479 }
480
481 // forward decleration
482 static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size);
483
484 static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
485 {
486         int r = 0;
487         unsigned char compressed;
488         LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
489         unsigned int out_len = LZO_OUT_LEN(in_len);
490         unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
491         size_t sizeOfIt = 5;
492
493         if(mode == 1) {
494                 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);  
495                 if (!(r == LZO_E_OK) || (out_len >= in_len))
496                         compressed = 0;
497                 else
498                         compressed = 1;
499         }
500         else if(mode == 2) {
501                 
502                 r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1....
503                                                 props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
504
505                 if(!(r == SZ_OK) || (out_len >= in_len))
506                         compressed = 0;
507                 else
508                         compressed = 2;
509         }
510
511         ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
512         if(compressed) {
513                 ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int));
514                 ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
515         }
516         else
517                 ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
518
519         if(compressed == 2)
520         {
521                 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
522                 ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char));
523         }
524
525         MEM_freeN(props);
526
527         return r;
528 }
529
530 static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v)
531 {       
532         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
533         SmokeDomainSettings *sds = smd->domain;
534         
535         if(sds->fluid) {
536                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
537                 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
538                 unsigned char *obstacles;
539                 unsigned int in_len = sizeof(float)*(unsigned int)res;
540                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
541                 int mode = res >= 1000000 ? 2 : 1;
542
543                 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
544
545                 ptcache_compress_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
546                 ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode);
547                 ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode);        
548                 ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode);
549                 ptcache_compress_write(pf, (unsigned char *)heatold, in_len, out, mode);
550                 ptcache_compress_write(pf, (unsigned char *)vx, in_len, out, mode);
551                 ptcache_compress_write(pf, (unsigned char *)vy, in_len, out, mode);
552                 ptcache_compress_write(pf, (unsigned char *)vz, in_len, out, mode);
553                 ptcache_compress_write(pf, (unsigned char *)vxold, in_len, out, mode);
554                 ptcache_compress_write(pf, (unsigned char *)vyold, in_len, out, mode);
555                 ptcache_compress_write(pf, (unsigned char *)vzold, in_len, out, mode);
556                 ptcache_compress_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
557                 ptcache_file_write(pf, &dt, 1, sizeof(float));
558                 ptcache_file_write(pf, &dx, 1, sizeof(float));
559
560                 MEM_freeN(out);
561                 
562                 return 1;
563         }
564         return 0;
565 }
566
567 static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v)
568 {
569         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
570         SmokeDomainSettings *sds = smd->domain;
571         
572         if(sds->wt) {
573                 int res_big_array[3];
574                 int res_big;
575                 int res = sds->res[0]*sds->res[1]*sds->res[2];
576                 float *dens, *densold, *tcu, *tcv, *tcw;
577                 unsigned int in_len = sizeof(float)*(unsigned int)res;
578                 unsigned int in_len_big;
579                 unsigned char *out;
580                 int mode;
581
582                 smoke_turbulence_get_res(sds->wt, res_big_array);
583                 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
584                 mode =  res_big >= 1000000 ? 2 : 1;
585                 in_len_big = sizeof(float) * (unsigned int)res_big;
586
587                 smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
588
589                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
590                 ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode);
591                 ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode);    
592                 MEM_freeN(out);
593
594                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
595                 ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode);
596                 ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode);
597                 ptcache_compress_write(pf, (unsigned char *)tcw, in_len, out, mode);
598                 MEM_freeN(out);
599                 
600                 return 1;
601         }
602         return 0;
603 }
604
605 // forward decleration
606 static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size);
607
608 static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
609 {
610         int r = 0;
611         unsigned char compressed = 0;
612         unsigned int in_len;
613         unsigned int out_len = len;
614         unsigned char *in;
615         unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
616         size_t sizeOfIt = 5;
617
618         ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
619         if(compressed) {
620                 ptcache_file_read(pf, &in_len, 1, sizeof(unsigned int));
621                 in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
622                 ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
623
624                 if(compressed == 1)
625                                 r = lzo1x_decompress(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
626                 else if(compressed == 2)
627                 {
628                         size_t leni = in_len, leno = out_len;
629                         ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int));
630                         ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
631                         r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
632                 }
633
634                 MEM_freeN(in);
635         }
636         else {
637                 ptcache_file_read(pf, result, len, sizeof(unsigned char));
638         }
639
640         MEM_freeN(props);
641
642         return r;
643 }
644
645 static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v)
646 {
647         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
648         SmokeDomainSettings *sds = smd->domain;
649         
650         if(sds->fluid) {
651                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
652                 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
653                 unsigned char *obstacles;
654                 unsigned int out_len = (unsigned int)res * sizeof(float);
655                 
656                 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
657
658                 ptcache_compress_read(pf, (unsigned char *)sds->shadow, out_len);
659                 ptcache_compress_read(pf, (unsigned char*)dens, out_len);
660                 ptcache_compress_read(pf, (unsigned char*)densold, out_len);
661                 ptcache_compress_read(pf, (unsigned char*)heat, out_len);
662                 ptcache_compress_read(pf, (unsigned char*)heatold, out_len);
663                 ptcache_compress_read(pf, (unsigned char*)vx, out_len);
664                 ptcache_compress_read(pf, (unsigned char*)vy, out_len);
665                 ptcache_compress_read(pf, (unsigned char*)vz, out_len);
666                 ptcache_compress_read(pf, (unsigned char*)vxold, out_len);
667                 ptcache_compress_read(pf, (unsigned char*)vyold, out_len);
668                 ptcache_compress_read(pf, (unsigned char*)vzold, out_len);
669                 ptcache_compress_read(pf, (unsigned char*)obstacles, (unsigned int)res);
670                 ptcache_file_read(pf, &dt, 1, sizeof(float));
671                 ptcache_file_read(pf, &dx, 1, sizeof(float));
672         }
673 }
674
675 static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v)
676 {
677         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
678         SmokeDomainSettings *sds = smd->domain;
679         
680         if(sds->fluid) {
681                 int res = sds->res[0]*sds->res[1]*sds->res[2];
682                 int res_big, res_big_array[3];
683                 float *dens, *densold, *tcu, *tcv, *tcw;
684                 unsigned int out_len = sizeof(float)*(unsigned int)res;
685                 unsigned int out_len_big;
686
687                 smoke_turbulence_get_res(sds->wt, res_big_array);
688                 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
689                 out_len_big = sizeof(float) * (unsigned int)res_big;
690
691                 smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
692
693                 ptcache_compress_read(pf, (unsigned char*)dens, out_len_big);
694                 ptcache_compress_read(pf, (unsigned char*)densold, out_len_big);
695
696                 ptcache_compress_read(pf, (unsigned char*)tcu, out_len);
697                 ptcache_compress_read(pf, (unsigned char*)tcv, out_len);
698                 ptcache_compress_read(pf, (unsigned char*)tcw, out_len);                
699         }
700 }
701
702 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
703 {
704         SmokeDomainSettings *sds = smd->domain;
705
706         memset(pid, 0, sizeof(PTCacheID));
707
708         pid->ob= ob;
709         pid->calldata= smd;
710         
711         pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
712         pid->stack_index= sds->point_cache[0]->index;
713
714         pid->cache= sds->point_cache[0];
715         pid->cache_ptr= &(sds->point_cache[0]);
716         pid->ptcaches= &(sds->ptcaches[0]);
717
718         pid->totpoint= pid->totwrite= ptcache_totpoint_smoke;
719
720         pid->write_elem= NULL;
721         pid->read_elem= NULL;
722
723         pid->read_stream = ptcache_read_smoke;
724         pid->write_stream = ptcache_write_smoke;
725         
726         pid->interpolate_elem= NULL;
727
728         pid->write_header= ptcache_write_basic_header;
729         pid->read_header= ptcache_read_basic_header;
730
731         pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values to make pointcache happy
732         pid->info_types= 0;
733 }
734
735 void BKE_ptcache_id_from_smoke_turbulence(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
736 {
737         SmokeDomainSettings *sds = smd->domain;
738
739         memset(pid, 0, sizeof(PTCacheID));
740
741         pid->ob= ob;
742         pid->calldata= smd;
743         
744         pid->type= PTCACHE_TYPE_SMOKE_HIGHRES;
745         pid->stack_index= sds->point_cache[1]->index;
746
747         pid->cache= sds->point_cache[1];
748         pid->cache_ptr= &sds->point_cache[1];
749         pid->ptcaches= &sds->ptcaches[1];
750
751         pid->totpoint= pid->totwrite= ptcache_totpoint_smoke_turbulence;
752
753         pid->write_elem= NULL;
754         pid->read_elem= NULL;
755
756         pid->read_stream = ptcache_read_smoke_turbulence;
757         pid->write_stream = ptcache_write_smoke_turbulence;
758         
759         pid->interpolate_elem= NULL;
760
761         pid->write_header= ptcache_write_basic_header;
762         pid->read_header= ptcache_read_basic_header;
763
764         pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy
765         pid->info_types= 0;
766 }
767
768 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
769 {
770         memset(pid, 0, sizeof(PTCacheID));
771
772         pid->ob= ob;
773         pid->calldata= clmd;
774         pid->type= PTCACHE_TYPE_CLOTH;
775         pid->stack_index= clmd->point_cache->index;
776         pid->cache= clmd->point_cache;
777         pid->cache_ptr= &clmd->point_cache;
778         pid->ptcaches= &clmd->ptcaches;
779         pid->totpoint= pid->totwrite= ptcache_totpoint_cloth;
780
781         pid->write_elem= ptcache_write_cloth;
782         pid->write_stream = NULL;
783         pid->read_stream = NULL;
784         pid->read_elem= ptcache_read_cloth;
785         pid->interpolate_elem= ptcache_interpolate_cloth;
786
787         pid->write_header= ptcache_write_basic_header;
788         pid->read_header= ptcache_read_basic_header;
789
790         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
791         pid->info_types= 0;
792 }
793
794 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
795 {
796         PTCacheID *pid;
797         ParticleSystem *psys;
798         ModifierData *md;
799
800         lb->first= lb->last= NULL;
801
802         if(ob->soft) {
803                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
804                 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
805                 BLI_addtail(lb, pid);
806         }
807
808         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
809                 if(psys->part) {
810                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
811                         BKE_ptcache_id_from_particles(pid, ob, psys);
812                         BLI_addtail(lb, pid);
813                 }
814         }
815
816         for(md=ob->modifiers.first; md; md=md->next) {
817                 if(md->type == eModifierType_Cloth) {
818                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
819                         BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
820                         BLI_addtail(lb, pid);
821                 }
822                 if(md->type == eModifierType_Smoke) {
823                         SmokeModifierData *smd = (SmokeModifierData *)md;
824                         if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
825                         {
826                                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
827                                 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md);
828                                 BLI_addtail(lb, pid);
829
830                                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
831                                 BKE_ptcache_id_from_smoke_turbulence(pid, ob, (SmokeModifierData*)md);
832                                 BLI_addtail(lb, pid);
833                         }
834                 }
835         }
836 }
837
838
839 /* File handling */
840
841 /*      Takes an Object ID and returns a unique name
842         - id: object id
843         - cfra: frame for the cache, can be negative
844         - stack_index: index in the modifier stack. we can have cache for more then one stack_index
845 */
846
847 #define MAX_PTCACHE_PATH FILE_MAX
848 #define MAX_PTCACHE_FILE ((FILE_MAXDIR+FILE_MAXFILE)*2)
849
850 static int ptcache_path(PTCacheID *pid, char *filename)
851 {
852         Library *lib;
853         size_t i;
854
855         lib= (pid)? pid->ob->id.lib: NULL;
856
857         if(pid->cache->flag & PTCACHE_EXTERNAL) {
858                 strcpy(filename, pid->cache->path);
859                 return BLI_add_slash(filename); /* new strlen() */
860         }
861         else if (G.relbase_valid || lib) {
862                 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */
863                 char *blendfilename;
864
865                 blendfilename= (lib)? lib->filename: G.sce;
866
867                 BLI_split_dirfile_basic(blendfilename, NULL, file);
868                 i = strlen(file);
869                 
870                 /* remove .blend */
871                 if (i > 6)
872                         file[i-6] = '\0';
873                 
874                 snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
875                 BLI_convertstringcode(filename, blendfilename);
876                 return BLI_add_slash(filename); /* new strlen() */
877         }
878         
879         /* use the temp path. this is weak but better then not using point cache at all */
880         /* btempdir is assumed to exist and ALWAYS has a trailing slash */
881         snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", btempdir, abs(getpid()));
882         
883         return BLI_add_slash(filename); /* new strlen() */
884 }
885
886 static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
887 {
888         int len=0;
889         char *idname;
890         char *newname;
891         filename[0] = '\0';
892         newname = filename;
893         
894         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
895         
896         /* start with temp dir */
897         if (do_path) {
898                 len = ptcache_path(pid, filename);
899                 newname += len;
900         }
901         if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
902                 idname = (pid->ob->id.name+2);
903                 /* convert chars to hex so they are always a valid filename */
904                 while('\0' != *idname) {
905                         snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
906                         newname+=2;
907                         len += 2;
908                 }
909         }
910         else {
911                 int temp = (int)strlen(pid->cache->name); 
912                 strcpy(newname, pid->cache->name); 
913                 newname+=temp;
914                 len += temp;
915         }
916
917         if (do_ext) {
918
919                 if(pid->cache->index < 0)
920                         pid->cache->index =  pid->stack_index = object_insert_ptcache(pid->ob);
921
922                 if(pid->cache->flag & PTCACHE_EXTERNAL) {
923                         if(pid->cache->index >= 0)
924                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
925                         else
926                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
927                 }
928                 else {
929                         snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
930                 }
931                 len += 16;
932         }
933         
934         return len; /* make sure the above string is always 16 chars */
935 }
936
937 /* youll need to close yourself after! */
938 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
939 {
940         PTCacheFile *pf;
941         FILE *fp = NULL;
942         char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
943
944         /* don't allow writing for linked objects */
945         if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
946                 return NULL;
947
948         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
949         
950         BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
951
952         if (mode==PTCACHE_FILE_READ) {
953                 if (!BLI_exists(filename)) {
954                         return NULL;
955                 }
956                 fp = fopen(filename, "rb");
957         } else if (mode==PTCACHE_FILE_WRITE) {
958                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
959                 fp = fopen(filename, "wb");
960         }
961
962         if (!fp)
963                 return NULL;
964         
965         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
966         pf->fp= fp;
967         
968         return pf;
969 }
970
971 static void ptcache_file_close(PTCacheFile *pf)
972 {
973         fclose(pf->fp);
974         MEM_freeN(pf);
975 }
976
977 static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size)
978 {
979         return (fread(f, size, tot, pf->fp) == tot);
980 }
981 static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size)
982 {
983         return (fwrite(f, size, tot, pf->fp) == tot);
984 }
985 static int ptcache_file_read_data(PTCacheFile *pf)
986 {
987         int i;
988
989         for(i=0; i<BPHYS_TOT_DATA; i++) {
990                 if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
991                         return 0;
992         }
993         
994         return 1;
995 }
996 static int ptcache_file_write_data(PTCacheFile *pf)
997 {               
998         int i;
999
1000         for(i=0; i<BPHYS_TOT_DATA; i++) {
1001                 if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
1002                         return 0;
1003         }
1004         
1005         return 1;
1006 }
1007 static int ptcache_file_read_header_begin(PTCacheFile *pf)
1008 {
1009         int error=0;
1010         char bphysics[8];
1011         
1012         pf->data_types = 0;
1013         
1014         if(fread(bphysics, sizeof(char), 8, pf->fp) != 8)
1015                 error = 1;
1016         
1017         if(!error && strncmp(bphysics, "BPHYSICS", 8))
1018                 error = 1;
1019
1020         if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp))
1021                 error = 1;
1022         
1023         /* if there was an error set file as it was */
1024         if(error)
1025                 fseek(pf->fp, 0, SEEK_SET);
1026
1027         return !error;
1028 }
1029
1030
1031 static int ptcache_file_write_header_begin(PTCacheFile *pf)
1032 {
1033         char *bphysics = "BPHYSICS";
1034         
1035         if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
1036                 return 0;
1037
1038         if(!fwrite(&pf->type, sizeof(int), 1, pf->fp))
1039                 return 0;
1040         
1041         return 1;
1042 }
1043
1044
1045 /* Data pointer handling */
1046 int BKE_ptcache_data_size(int data_type)
1047 {
1048         switch(data_type) {
1049                 case BPHYS_DATA_INDEX:
1050                         return sizeof(int);
1051                 case BPHYS_DATA_LOCATION:
1052                 case BPHYS_DATA_VELOCITY:
1053                 case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */
1054                 case BPHYS_DATA_TIMES:
1055                         return 3 * sizeof(float);
1056                 case BPHYS_DATA_ROTATION:
1057                         return 4 * sizeof(float);
1058                 case BPHYS_DATA_SIZE:
1059                         return sizeof(float);
1060                 case BPHYS_DATA_BOIDS:
1061                         return sizeof(BoidData);
1062                 default:
1063                         return 0;
1064         }
1065 }
1066 static void ptcache_data_to(void **data, int type, int index, void *to)
1067 {
1068         if(data[type]) {
1069                 if(index)
1070                         memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type));
1071                 else
1072                         memcpy(to, data[type], BKE_ptcache_data_size(type));
1073         }
1074 }
1075
1076 static void ptcache_data_from(void **data, int type, void *from)
1077 {
1078         if(data[type])
1079                 memcpy(data[type], from, BKE_ptcache_data_size(type));
1080 }
1081
1082 static void ptcache_file_init_pointers(PTCacheFile *pf)
1083 {
1084         int data_types = pf->data_types;
1085
1086         pf->cur[BPHYS_DATA_INDEX] =             data_types & (1<<BPHYS_DATA_INDEX) ?            &pf->data.index : NULL;
1087         pf->cur[BPHYS_DATA_LOCATION] =  data_types & (1<<BPHYS_DATA_LOCATION) ?         &pf->data.loc   : NULL;
1088         pf->cur[BPHYS_DATA_VELOCITY] =  data_types & (1<<BPHYS_DATA_VELOCITY) ?         &pf->data.vel   : NULL;
1089         pf->cur[BPHYS_DATA_ROTATION] =  data_types & (1<<BPHYS_DATA_ROTATION) ?         &pf->data.rot   : NULL;
1090         pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ?        &pf->data.ave   : NULL;
1091         pf->cur[BPHYS_DATA_SIZE] =              data_types & (1<<BPHYS_DATA_SIZE)       ?               &pf->data.size  : NULL;
1092         pf->cur[BPHYS_DATA_TIMES] =             data_types & (1<<BPHYS_DATA_TIMES) ?            &pf->data.times : NULL;
1093         pf->cur[BPHYS_DATA_BOIDS] =             data_types & (1<<BPHYS_DATA_BOIDS) ?            &pf->data.boids : NULL;
1094 }
1095
1096 void BKE_ptcache_mem_init_pointers(PTCacheMem *pm)
1097 {
1098         int data_types = pm->data_types;
1099         int i;
1100
1101         for(i=0; i<BPHYS_TOT_DATA; i++)
1102                 pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL;
1103 }
1104
1105 void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm)
1106 {
1107         int i;
1108
1109         for(i=0; i<BPHYS_TOT_DATA; i++) {
1110                 if(pm->cur[i])
1111                         pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i);
1112         }
1113 }
1114 static void ptcache_alloc_data(PTCacheMem *pm)
1115 {
1116         int data_types = pm->data_types;
1117         int totpoint = pm->totpoint;
1118         int i;
1119
1120         for(i=0; i<BPHYS_TOT_DATA; i++) {
1121                 if(data_types & (1<<i))
1122                         pm->data[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data");
1123         }
1124 }
1125 static void ptcache_free_data(void *data[])
1126 {
1127         int i;
1128
1129         for(i=0; i<BPHYS_TOT_DATA; i++) {
1130                 if(data[i])
1131                         MEM_freeN(data[i]);
1132         }
1133 }
1134 static void ptcache_copy_data(void *from[], void *to[])
1135 {
1136         int i;
1137         for(i=0; i<BPHYS_TOT_DATA; i++) {
1138                 if(from[i])
1139                         memcpy(to[i], from[i], BKE_ptcache_data_size(i));
1140         }
1141 }
1142
1143
1144
1145 static int ptcache_pid_old_elemsize(PTCacheID *pid)
1146 {
1147         if(pid->type==PTCACHE_TYPE_SOFTBODY)
1148                 return 6 * sizeof(float);
1149         else if(pid->type==PTCACHE_TYPE_PARTICLES)
1150                 return sizeof(ParticleKey);
1151         else if(pid->type==PTCACHE_TYPE_CLOTH)
1152                 return 9 * sizeof(float);
1153
1154         return 0;
1155 }
1156
1157 /* reads cache from disk or memory */
1158 /* possible to get old or interpolated result */
1159 int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec)
1160 {
1161         PTCacheFile *pf=NULL, *pf2=NULL;
1162         PTCacheMem *pm=NULL, *pm2=NULL;
1163         float old_data1[14], old_data2[14];
1164         int cfrai = (int)cfra;
1165         int old_elemsize = ptcache_pid_old_elemsize(pid);
1166         int i;
1167
1168         int cfra1 = 0, cfra2 = 0;
1169         int totpoint = 0, totpoint2 = 0;
1170         int *index = &i, *index2 = &i;
1171         int use_old = 0, old_frame = 0;
1172
1173         int ret = 0, error = 0;
1174
1175         /* nothing to read to */
1176         if(pid->totpoint(pid->calldata) == 0)
1177                 return 0;
1178
1179         if(pid->cache->flag & PTCACHE_READ_INFO) {
1180                 pid->cache->flag &= ~PTCACHE_READ_INFO;
1181                 BKE_ptcache_read_cache(pid, 0, frs_sec);
1182         }
1183
1184
1185         /* first check if we have the actual frame cached */
1186         if(cfra == (float)cfrai) {
1187                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1188                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1189                 }
1190                 else {
1191                         pm = pid->cache->mem_cache.first;
1192
1193                         for(; pm; pm=pm->next) {
1194                                 if(pm->frame == cfrai)
1195                                         break;
1196                         }
1197                 }
1198         }
1199
1200         /* no exact cache frame found so try to find cached frames around cfra */
1201         if(!pm && !pf) {
1202                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1203                         pf=NULL;
1204                         while(cfrai > pid->cache->startframe && !pf) {
1205                                 cfrai--;
1206                                 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1207                                 cfra1 = cfrai;
1208                         }
1209
1210                         old_frame = cfrai;
1211
1212                         cfrai = (int)cfra;
1213                         while(cfrai < pid->cache->endframe && !pf2) {
1214                                 cfrai++;
1215                                 pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1216                                 cfra2 = cfrai;
1217                         }
1218
1219                         if(pf && !pf2) {
1220                                 pf2 = pf;
1221                                 pf = NULL;
1222                         }
1223                 }
1224                 else if(pid->cache->mem_cache.first){
1225                         pm = pid->cache->mem_cache.first;
1226
1227                         while(pm->next && pm->next->frame < cfra)
1228                                 pm= pm->next;
1229
1230                         if(pm) {
1231                                 old_frame = pm->frame;
1232                                 cfra1 = pm->frame;
1233                         }
1234
1235                         pm2 = pid->cache->mem_cache.last;
1236
1237                         if(pm2 && pm2->frame < cfra)
1238                                 pm2 = NULL;
1239                         else {
1240                                 while(pm2->prev && pm2->prev->frame > cfra)
1241                                         pm2= pm2->prev;
1242
1243                                 if(pm2)
1244                                         cfra2 = pm2->frame;
1245                         }
1246
1247                         if(pm && !pm2) {
1248                                 pm2 = pm;
1249                                 pm = NULL;
1250                         }
1251                 }
1252         }
1253
1254         if(!pm && !pm2 && !pf && !pf2)
1255                 return 0;
1256
1257         if(pm) {
1258                 BKE_ptcache_mem_init_pointers(pm);
1259                 totpoint = pm->totpoint;
1260                 index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
1261         }
1262         if(pm2) {
1263                 BKE_ptcache_mem_init_pointers(pm2);
1264                 totpoint2 = pm2->totpoint;
1265                 index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
1266         }
1267         if(pf) {
1268                 if(ptcache_file_read_header_begin(pf)) {
1269                         if(pf->type != pid->type) {
1270                                 /* todo report error */
1271                                 ptcache_file_close(pf);
1272                                 pf = NULL;
1273                         }
1274                         else if(pid->read_header(pf)) {
1275                                 ptcache_file_init_pointers(pf);
1276                                 totpoint = pf->totpoint;
1277                                 index = pf->data_types & BPHYS_DATA_INDEX ? &pf->data.index : &i;
1278                         }
1279                 }
1280                 else {
1281                         /* fall back to old cache file format */
1282                         use_old = 1;
1283                         totpoint = pid->totpoint(pid->calldata);
1284                 }
1285         }
1286         if(pf2) {
1287                 if(ptcache_file_read_header_begin(pf2)) {
1288                         if(pf2->type != pid->type) {
1289                                 /* todo report error */
1290                                 ptcache_file_close(pf2);
1291                                 pf2 = NULL;
1292                         }
1293                         else if(pid->read_header(pf2)) {
1294                                 ptcache_file_init_pointers(pf2);
1295                                 totpoint2 = pf2->totpoint;
1296                                 index2 = pf->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i;
1297                         }
1298                 }
1299                 else {
1300                         /* fall back to old cache file format */
1301                         use_old = 1;
1302                         totpoint2 = pid->totpoint(pid->calldata);
1303                 }
1304         }
1305
1306         /* don't read old cache if allready simulated past cached frame */
1307         if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe)
1308                 error = 1;
1309         if(cfra1 && cfra1==cfra2)
1310                 error = 1;
1311
1312         if(!error) 
1313         {
1314                 if(pf && pid->read_stream) {
1315                         if(totpoint != pid->totpoint(pid->calldata))
1316                                 error = 1;
1317                         else
1318                         {
1319                                 // we have stream writing here
1320                                 pid->read_stream(pf, pid->calldata);
1321                         }
1322                 }
1323         }
1324
1325         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata));
1326
1327         if(!error) 
1328         {       
1329                 for(i=0; i<totpoint; i++) {
1330                         /* read old cache file format */
1331                         if(use_old) {
1332                                 if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize))
1333                                         pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1);
1334                                 else if(pid->read_elem)
1335                                         { error = 1; break; }
1336                         }
1337                         else {
1338                                 if(pid->read_elem && (pm || ptcache_file_read_data(pf)))
1339                                         pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL);
1340                                 else if(pid->read_elem)
1341                                         { error = 1; break; }
1342                         }
1343
1344                         if(pm) {
1345                                 BKE_ptcache_mem_incr_pointers(pm);
1346                                 index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
1347                         }
1348                 }
1349         }
1350
1351         if(!error) 
1352         {
1353                 if(pf2 && pid->read_stream) {
1354                         if(totpoint2 != pid->totpoint(pid->calldata))
1355                                 error = 1;
1356                         else
1357                         {
1358                                 // we have stream writing here
1359                                 pid->read_stream(pf2, pid->calldata);
1360                         }
1361                 }
1362         }
1363
1364         totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata));
1365
1366         if(!error) 
1367         {
1368                 for(i=0; i<totpoint2; i++) {
1369                         /* read old cache file format */
1370                         if(use_old) {
1371                                 if(pid->read_elem && ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) {
1372                                         if(!pf && pf2)
1373                                                 pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2);
1374                                         else if(pid->interpolate_elem)
1375                                                 pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2);
1376                                         else
1377                                         { error = 1; break; }
1378                                 }
1379                                 else if(pid->read_elem)
1380                                         { error = 1; break; }
1381                         }
1382                         else {
1383                                 if(pid->read_elem && (pm2 || ptcache_file_read_data(pf2))) {
1384                                         if((!pf && pf2) || (!pm && pm2))
1385                                                 pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL);
1386                                         else if(pid->interpolate_elem)
1387                                                 pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL);
1388                                         else
1389                                         { error = 1; break; }
1390                                 }
1391                                 else if(pid->read_elem)
1392                                         { error = 1; break; }
1393                         }
1394
1395                         if(pm2) {
1396                                 BKE_ptcache_mem_incr_pointers(pm2);
1397                                 index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
1398                         }
1399                 }
1400         }
1401
1402         if(pm || pf)
1403                 ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT;
1404         else if(pm2 || pf2) {
1405                 ret = PTCACHE_READ_OLD;
1406                 pid->cache->simframe = old_frame;
1407         }
1408
1409         if(pf) {
1410                 ptcache_file_close(pf);
1411                 pf = NULL;
1412         }
1413
1414         if(pf2) {
1415                 ptcache_file_close(pf2);
1416                 pf = NULL;
1417         }
1418
1419         if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
1420                 cfrai = (int)cfra;
1421                 /* clear invalid cache frames so that better stuff can be simulated */
1422                 if(pid->cache->flag & PTCACHE_OUTDATED) {
1423                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
1424                 }
1425                 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
1426                         if(cfra <= pid->cache->last_exact)
1427                                 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1428
1429                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact));
1430                 }
1431         }
1432
1433         return (error ? 0 : ret);
1434 }
1435 /* TODO for later */
1436 //static void ptcache_make_index_array(PTCacheMem *pm, int totpoint)
1437 //{
1438 //      int i, *index;
1439 //
1440 //      if(pm->index_array) {
1441 //              MEM_freeN(pm->index_array);
1442 //              pm->index_array = NULL;
1443 //      }
1444 //
1445 //      if(!pm->data[BPHYS_DATA_INDEX])
1446 //              return;
1447 //
1448 //      pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array");
1449 //      index = pm->data[BPHYS_DATA_INDEX];
1450 //
1451 //      for(i=0; i<pm->totpoint; i++, index++)
1452 //              pm->index_array[*index] = i;
1453 //}
1454 /* writes cache to disk or memory */
1455 int BKE_ptcache_write_cache(PTCacheID *pid, int cfra)
1456 {
1457         PointCache *cache = pid->cache;
1458         PTCacheFile *pf= NULL;
1459         int i;
1460         int totpoint = pid->totpoint(pid->calldata);
1461         int add = 0, overwrite = 0;
1462
1463         if(totpoint == 0 || cfra < 0
1464                 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
1465                 return 0;
1466
1467         if(cache->flag & PTCACHE_DISK_CACHE) {
1468                 int efra = cache->endframe;
1469
1470                 if(cfra==0)
1471                         add = 1;
1472                 /* allways start from scratch on the first frame */
1473                 else if(cfra == cache->startframe) {
1474                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1475                         cache->flag &= ~PTCACHE_REDO_NEEDED;
1476                         add = 1;
1477                 }
1478                 else {
1479                         int ofra;
1480                         /* find last cached frame */
1481                         while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
1482                                 efra--;
1483
1484                         /* find second last cached frame */
1485                         ofra = efra-1;
1486                         while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
1487                                 ofra--;
1488
1489                         if(efra >= cache->startframe && cfra > efra) {
1490                                 if(ofra >= cache->startframe && efra - ofra < cache->step)
1491                                         overwrite = 1;
1492                                 else
1493                                         add = 1;
1494                         }
1495                 }
1496
1497                 if(add || overwrite) {
1498                         if(overwrite)
1499                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
1500
1501                         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
1502                         if(!pf)
1503                                 return 0;
1504
1505                         pf->type = pid->type;
1506                         pf->totpoint = cfra ? totpoint : pid->totwrite(pid->calldata);
1507                         pf->data_types = cfra ? pid->data_types : pid->info_types;
1508
1509                         if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
1510                                 ptcache_file_close(pf);
1511                                 return 0;
1512                         }
1513
1514                         ptcache_file_init_pointers(pf);
1515
1516                         if(pf && pid->write_stream) {
1517                                 // we have stream writing here
1518                                 pid->write_stream(pf, pid->calldata);
1519                         }
1520                         else
1521                                 for(i=0; i<totpoint; i++) {
1522                                         if(pid->write_elem && pid->write_elem(i, pid->calldata, pf->cur))
1523                                                 if(!ptcache_file_write_data(pf)) {
1524                                                         ptcache_file_close(pf);
1525                                                         return 0;
1526                                                 }
1527                                 }
1528                 }
1529         }
1530         else {
1531                 PTCacheMem *pm;
1532                 PTCacheMem *pm2;
1533
1534                 pm2 = cache->mem_cache.first;
1535                 
1536                 /* don't write info file in memory */
1537                 if(cfra==0)
1538                         return 1;
1539                 /* allways start from scratch on the first frame */
1540                 if(cfra == cache->startframe) {
1541                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1542                         cache->flag &= ~PTCACHE_REDO_NEEDED;
1543                         add = 1;
1544                 }
1545                 else if (cache->mem_cache.last) {
1546                         pm2 = cache->mem_cache.last;
1547
1548                         if(pm2 && cfra > pm2->frame) {
1549                                 if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
1550                                         overwrite = 1;
1551                                 else
1552                                         add = 1;
1553                         }
1554                 }
1555                 else
1556                         add = 1;
1557
1558                 if(add || overwrite) {
1559                         if(overwrite)
1560                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame);
1561
1562                         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1563
1564                         pm->totpoint = pid->totwrite(pid->calldata);
1565                         pm->data_types = cfra ? pid->data_types : pid->info_types;
1566
1567                         ptcache_alloc_data(pm);
1568                         BKE_ptcache_mem_init_pointers(pm);
1569
1570                         for(i=0; i<totpoint; i++) {
1571                                 if(pid->write_elem && pid->write_elem(i, pid->calldata, pm->cur))
1572                                         BKE_ptcache_mem_incr_pointers(pm);
1573                         }
1574                         //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
1575
1576                         pm->frame = cfra;
1577                         BLI_addtail(&cache->mem_cache, pm);
1578                 }
1579         }
1580
1581         if(add || overwrite) {
1582                 if(cfra - cache->last_exact == 1
1583                         || cfra == cache->startframe) {
1584                         cache->last_exact = cfra;
1585                         cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1586                 }
1587                 else
1588                         cache->flag |= PTCACHE_FRAMES_SKIPPED;
1589         }
1590         
1591         if(pf)
1592                 ptcache_file_close(pf);
1593
1594         BKE_ptcache_update_info(pid);
1595
1596         return 1;
1597 }
1598 /* youll need to close yourself after!
1599  * mode - PTCACHE_CLEAR_ALL, 
1600
1601 */
1602 /* Clears & resets */
1603 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
1604 {
1605         int len; /* store the length of the string */
1606
1607         /* mode is same as fopen's modes */
1608         DIR *dir; 
1609         struct dirent *de;
1610         char path[MAX_PTCACHE_PATH];
1611         char filename[MAX_PTCACHE_FILE];
1612         char path_full[MAX_PTCACHE_FILE];
1613         char ext[MAX_PTCACHE_PATH];
1614
1615         if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
1616                 return;
1617
1618         /* don't allow clearing for linked objects */
1619         if(pid->ob->id.lib)
1620                 return;
1621
1622         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
1623         
1624         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
1625         switch (mode) {
1626         case PTCACHE_CLEAR_ALL:
1627         case PTCACHE_CLEAR_BEFORE:      
1628         case PTCACHE_CLEAR_AFTER:
1629                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1630                         ptcache_path(pid, path);
1631                         
1632                         len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
1633                         
1634                         dir = opendir(path);
1635                         if (dir==NULL)
1636                                 return;
1637
1638                         snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
1639                         
1640                         while ((de = readdir(dir)) != NULL) {
1641                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
1642                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
1643                                                 if (mode == PTCACHE_CLEAR_ALL) {
1644                                                         pid->cache->last_exact = 0;
1645                                                         BLI_join_dirfile(path_full, path, de->d_name);
1646                                                         BLI_delete(path_full, 0, 0);
1647                                                 } else {
1648                                                         /* read the number of the file */
1649                                                         int frame, len2 = (int)strlen(de->d_name);
1650                                                         char num[7];
1651
1652                                                         if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
1653                                                                 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
1654                                                                 frame = atoi(num);
1655                                                                 
1656                                                                 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || 
1657                                                                 (mode==PTCACHE_CLEAR_AFTER && frame > cfra)     ) {
1658                                                                         
1659                                                                         BLI_join_dirfile(path_full, path, de->d_name);
1660                                                                         BLI_delete(path_full, 0, 0);
1661                                                                 }
1662                                                         }
1663                                                 }
1664                                         }
1665                                 }
1666                         }
1667                         closedir(dir);
1668                 }
1669                 else {
1670                         PTCacheMem *pm= pid->cache->mem_cache.first;
1671                         PTCacheMem *link= NULL;
1672
1673                         pm= pid->cache->mem_cache.first;
1674
1675                         if(mode == PTCACHE_CLEAR_ALL) {
1676                                 pid->cache->last_exact = 0;
1677                                 for(; pm; pm=pm->next)
1678                                         ptcache_free_data(pm->data);
1679                                 BLI_freelistN(&pid->cache->mem_cache);
1680                         } else {
1681                                 while(pm) {
1682                                         if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra)     || 
1683                                         (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
1684                                                 link = pm;
1685                                                 pm = pm->next;
1686                                                 ptcache_free_data(link->data);
1687                                                 BLI_freelinkN(&pid->cache->mem_cache, link);
1688                                         }
1689                                         else
1690                                                 pm = pm->next;
1691                                 }
1692                         }
1693                 }
1694                 break;
1695                 
1696         case PTCACHE_CLEAR_FRAME:
1697                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1698                         if(BKE_ptcache_id_exist(pid, cfra)) {
1699                                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
1700                                 BLI_delete(filename, 0, 0);
1701                         }
1702                 }
1703                 else {
1704                         PTCacheMem *pm = pid->cache->mem_cache.first;
1705
1706                         for(; pm; pm=pm->next) {
1707                                 if(pm->frame == cfra) {
1708                                         ptcache_free_data(pm->data);
1709                                         BLI_freelinkN(&pid->cache->mem_cache, pm);
1710                                         break;
1711                                 }
1712                         }
1713                 }
1714                 break;
1715         }
1716
1717         BKE_ptcache_update_info(pid);
1718 }
1719
1720 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
1721 {
1722         if(!pid->cache)
1723                 return 0;
1724         
1725         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1726                 char filename[MAX_PTCACHE_FILE];
1727                 
1728                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
1729
1730                 return BLI_exists(filename);
1731         }
1732         else {
1733                 PTCacheMem *pm = pid->cache->mem_cache.first;
1734
1735                 for(; pm; pm=pm->next) {
1736                         if(pm->frame==cfra)
1737                                 return 1;
1738                 }
1739                 return 0;
1740         }
1741 }
1742
1743 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
1744 {
1745         Object *ob;
1746         PointCache *cache;
1747         float offset, time, nexttime;
1748
1749         /* TODO: this has to be sorter out once bsystem_time gets redone, */
1750         /*       now caches can handle interpolating etc. too - jahka */
1751
1752         /* time handling for point cache:
1753          * - simulation time is scaled by result of bsystem_time
1754          * - for offsetting time only time offset is taken into account, since
1755          *   that's always the same and can't be animated. a timeoffset which
1756          *   varies over time is not simpe to support.
1757          * - field and motion blur offsets are currently ignored, proper solution
1758          *   is probably to interpolate results from two frames for that ..
1759          */
1760
1761         ob= pid->ob;
1762         cache= pid->cache;
1763
1764         if(timescale) {
1765                 time= bsystem_time(scene, ob, cfra, 0.0f);
1766                 nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f);
1767
1768                 *timescale= MAX2(nexttime - time, 0.0f);
1769         }
1770
1771         if(startframe && endframe) {
1772                 *startframe= cache->startframe;
1773                 *endframe= cache->endframe;
1774
1775                 // XXX ipoflag is depreceated - old animation system stuff
1776                 if (/*(ob->ipoflag & OB_OFFS_PARENT) &&*/ (ob->partype & PARSLOW)==0) {
1777                         offset= give_timeoffset(ob);
1778
1779                         *startframe += (int)(offset+0.5f);
1780                         *endframe += (int)(offset+0.5f);
1781                 }
1782         }
1783 }
1784
1785 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
1786 {
1787         PointCache *cache;
1788         int reset, clear, after;
1789
1790         if(!pid->cache)
1791                 return 0;
1792
1793         cache= pid->cache;
1794         reset= 0;
1795         clear= 0;
1796         after= 0;
1797
1798         if(mode == PTCACHE_RESET_DEPSGRAPH) {
1799                 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
1800                         if(cache->flag & PTCACHE_QUICK_CACHE)
1801                                 clear= 1;
1802
1803                         after= 1;
1804                 }
1805
1806                 cache->flag |= PTCACHE_OUTDATED;
1807         }
1808         else if(mode == PTCACHE_RESET_BAKED) {
1809                 if(!BKE_ptcache_get_continue_physics()) {
1810                         reset= 1;
1811                         clear= 1;
1812                 }
1813                 else
1814                         cache->flag |= PTCACHE_OUTDATED;
1815         }
1816         else if(mode == PTCACHE_RESET_OUTDATED) {
1817                 reset = 1;
1818
1819                 if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
1820                         clear= 1;
1821                         cache->flag &= ~PTCACHE_OUTDATED;
1822                 }
1823         }
1824
1825         if(reset) {
1826                 cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
1827                 cache->simframe= 0;
1828                 cache->last_exact= 0;
1829
1830                 if(pid->type == PTCACHE_TYPE_CLOTH)
1831                         cloth_free_modifier(pid->ob, pid->calldata);
1832                 else if(pid->type == PTCACHE_TYPE_SOFTBODY)
1833                         sbFreeSimulation(pid->calldata);
1834                 else if(pid->type == PTCACHE_TYPE_PARTICLES)
1835                         psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
1836                 else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
1837                         smokeModifier_reset(pid->calldata);
1838                 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
1839                         smokeModifier_reset_turbulence(pid->calldata);
1840         }
1841         if(clear)
1842                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1843         else if(after)
1844                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
1845
1846         return (reset || clear || after);
1847 }
1848
1849 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
1850 {
1851         PTCacheID pid;
1852         ParticleSystem *psys;
1853         ModifierData *md;
1854         int reset, skip;
1855
1856         reset= 0;
1857         skip= 0;
1858
1859         if(ob->soft) {
1860                 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
1861                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1862         }
1863
1864         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1865                 /* Baked cloth hair has to be checked first, because we don't want to reset */
1866                 /* particles or cloth in that case -jahka */
1867                 if(psys->clmd) {
1868                         BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
1869                         if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
1870                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1871                         else
1872                                 skip = 1;
1873                 }
1874                 else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
1875                         skip = 1;
1876
1877                 if(skip == 0 && psys->part) {
1878                         BKE_ptcache_id_from_particles(&pid, ob, psys);
1879                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1880                 }
1881         }
1882
1883         for(md=ob->modifiers.first; md; md=md->next) {
1884                 if(md->type == eModifierType_Cloth) {
1885                         BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
1886                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1887                 }
1888                 if(md->type == eModifierType_Smoke) {
1889                         SmokeModifierData *smd = (SmokeModifierData *)md;
1890                         if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
1891                         {
1892                                 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md);
1893                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1894
1895                                 BKE_ptcache_id_from_smoke_turbulence(&pid, ob, (SmokeModifierData*)md);
1896                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1897                         }
1898                 }
1899         }
1900
1901         return reset;
1902 }
1903
1904 /* Use this when quitting blender, with unsaved files */
1905 void BKE_ptcache_remove(void)
1906 {
1907         char path[MAX_PTCACHE_PATH];
1908         char path_full[MAX_PTCACHE_PATH];
1909         int rmdir = 1;
1910         
1911         ptcache_path(NULL, path);
1912
1913         if (BLI_exist(path)) {
1914                 /* The pointcache dir exists? - remove all pointcache */
1915
1916                 DIR *dir; 
1917                 struct dirent *de;
1918
1919                 dir = opendir(path);
1920                 if (dir==NULL)
1921                         return;
1922                 
1923                 while ((de = readdir(dir)) != NULL) {
1924                         if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
1925                                 /* do nothing */
1926                         } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
1927                                 BLI_join_dirfile(path_full, path, de->d_name);
1928                                 BLI_delete(path_full, 0, 0);
1929                         } else {
1930                                 rmdir = 0; /* unknown file, dont remove the dir */
1931                         }
1932                 }
1933
1934                 closedir(dir);
1935         } else { 
1936                 rmdir = 0; /* path dosnt exist  */
1937         }
1938         
1939         if (rmdir) {
1940                 BLI_delete(path, 1, 0);
1941         }
1942 }
1943
1944 /* Continuous Interaction */
1945
1946 static int CONTINUE_PHYSICS = 0;
1947
1948 void BKE_ptcache_set_continue_physics(Scene *scene, int enable)
1949 {
1950         Object *ob;
1951
1952         if(CONTINUE_PHYSICS != enable) {
1953                 CONTINUE_PHYSICS = enable;
1954
1955                 if(CONTINUE_PHYSICS == 0) {
1956                         for(ob=G.main->object.first; ob; ob=ob->id.next)
1957                                 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
1958                                         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1959                 }
1960         }
1961 }
1962
1963 int BKE_ptcache_get_continue_physics()
1964 {
1965         return CONTINUE_PHYSICS;
1966 }
1967
1968 /* Point Cache handling */
1969
1970 PointCache *BKE_ptcache_add(ListBase *ptcaches)
1971 {
1972         PointCache *cache;
1973
1974         cache= MEM_callocN(sizeof(PointCache), "PointCache");
1975         cache->startframe= 1;
1976         cache->endframe= 250;
1977         cache->step= 10;
1978         cache->index = -1;
1979
1980         BLI_addtail(ptcaches, cache);
1981
1982         return cache;
1983 }
1984
1985 void BKE_ptcache_free_mem(ListBase *mem_cache)
1986 {
1987         PTCacheMem *pm = mem_cache->first;
1988
1989         if(pm) {
1990                 for(; pm; pm=pm->next) {
1991                         ptcache_free_data(pm->data);
1992                         if(pm->index_array)
1993                                 MEM_freeN(pm->index_array);
1994                 }
1995
1996                 BLI_freelistN(mem_cache);
1997         }
1998 }
1999 void BKE_ptcache_free(PointCache *cache)
2000 {
2001         BKE_ptcache_free_mem(&cache->mem_cache);
2002         if(cache->edit && cache->free_edit)
2003                 cache->free_edit(cache->edit);
2004         MEM_freeN(cache);
2005 }
2006 void BKE_ptcache_free_list(ListBase *ptcaches)
2007 {
2008         PointCache *cache = ptcaches->first;
2009
2010         while(cache) {
2011                 BLI_remlink(ptcaches, cache);
2012                 BKE_ptcache_free(cache);
2013                 cache = ptcaches->first;
2014         }
2015 }
2016
2017 static PointCache *ptcache_copy(PointCache *cache)
2018 {
2019         PointCache *ncache;
2020
2021         ncache= MEM_dupallocN(cache);
2022
2023         /* hmm, should these be copied over instead? */
2024         ncache->mem_cache.first = NULL;
2025         ncache->mem_cache.last = NULL;
2026
2027         ncache->flag= 0;
2028         ncache->simframe= 0;
2029
2030         return ncache;
2031 }
2032 /* returns first point cache */
2033 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old)
2034 {
2035         PointCache *cache = ptcaches_old->first;
2036
2037         ptcaches_new->first = ptcaches_new->last = NULL;
2038
2039         for(; cache; cache=cache->next)
2040                 BLI_addtail(ptcaches_new, ptcache_copy(cache));
2041
2042         return ptcaches_new->first;
2043 }
2044
2045
2046 /* Baking */
2047 static int count_quick_cache(Scene *scene, int *quick_step)
2048 {
2049         Base *base = scene->base.first;
2050         PTCacheID *pid;
2051         ListBase pidlist;
2052         int autocache_count= 0;
2053
2054         for(base = scene->base.first; base; base = base->next) {
2055                 if(base->object) {
2056                         BKE_ptcache_ids_from_object(&pidlist, base->object);
2057
2058                         for(pid=pidlist.first; pid; pid=pid->next) {
2059                                 if((pid->cache->flag & PTCACHE_BAKED)
2060                                         || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
2061                                         continue;
2062
2063                                 if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
2064                                         if(!autocache_count)
2065                                                 *quick_step = pid->cache->step;
2066                                         else
2067                                                 *quick_step = MIN2(*quick_step, pid->cache->step);
2068
2069                                         autocache_count++;
2070                                 }
2071                         }
2072
2073                         BLI_freelistN(&pidlist);
2074                 }
2075         }
2076
2077         return autocache_count;
2078 }
2079 void BKE_ptcache_quick_cache_all(Scene *scene)
2080 {
2081         PTCacheBaker baker;
2082
2083         baker.bake=0;
2084         baker.break_data=NULL;
2085         baker.break_test=NULL;
2086         baker.pid=NULL;
2087         baker.progressbar=NULL;
2088         baker.progresscontext=NULL;
2089         baker.render=0;
2090         baker.anim_init = 0;
2091         baker.scene=scene;
2092
2093         if(count_quick_cache(scene, &baker.quick_step))
2094                 BKE_ptcache_make_cache(&baker);
2095 }
2096
2097 /* if bake is not given run simulations to current frame */
2098 void BKE_ptcache_make_cache(PTCacheBaker* baker)
2099 {
2100         Scene *scene = baker->scene;
2101         Base *base;
2102         ListBase pidlist;
2103         PTCacheID *pid = baker->pid;
2104         PointCache *cache = NULL;
2105         float frameleno = scene->r.framelen;
2106         int cfrao = CFRA;
2107         int startframe = MAXFRAME;
2108         int endframe = baker->anim_init ? scene->r.sfra : CFRA;
2109         int bake = baker->bake;
2110         int render = baker->render;
2111         int step = baker->quick_step;
2112
2113         G.afbreek = 0;
2114
2115         /* set caches to baking mode and figure out start frame */
2116         if(pid) {
2117                 /* cache/bake a single object */
2118                 cache = pid->cache;
2119                 if((cache->flag & PTCACHE_BAKED)==0) {
2120                         if(pid->type==PTCACHE_TYPE_PARTICLES)
2121                                 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
2122                         else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
2123                                 /* get all pids from the object and search for smoke low res */
2124                                 ListBase pidlist2;
2125                                 PTCacheID *pid2;
2126                                 BKE_ptcache_ids_from_object(&pidlist2, pid->ob);
2127                                 for(pid2=pidlist2.first; pid2; pid2=pid2->next) {
2128                                         if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) 
2129                                         {
2130                                                 if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) {
2131                                                         if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED)
2132                                                                 BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0);
2133                                                         if(bake) {
2134                                                                 pid2->cache->flag |= PTCACHE_BAKING;
2135                                                                 pid2->cache->flag &= ~PTCACHE_BAKED;
2136                                                         }
2137                                                 }
2138                                         }
2139                                 }
2140                         }
2141
2142                         if(bake || cache->flag & PTCACHE_REDO_NEEDED)
2143                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2144
2145                         startframe = MAX2(cache->last_exact, cache->startframe);
2146
2147                         if(bake) {
2148                                 endframe = cache->endframe;
2149                                 cache->flag |= PTCACHE_BAKING;
2150                         }
2151                         else {
2152                                 endframe = MIN2(endframe, cache->endframe);
2153                         }
2154
2155                         cache->flag &= ~PTCACHE_BAKED;
2156                 }
2157         }
2158         else for(base=scene->base.first; base; base= base->next) {
2159                 /* cache/bake everything in the scene */
2160                 BKE_ptcache_ids_from_object(&pidlist, base->object);
2161
2162                 for(pid=pidlist.first; pid; pid=pid->next) {
2163                         cache = pid->cache;
2164                         if((cache->flag & PTCACHE_BAKED)==0) {
2165                                 if(pid->type==PTCACHE_TYPE_PARTICLES) {
2166                                         ParticleSystem *psys = (ParticleSystem*)pid->calldata;
2167                                         /* skip hair & keyed particles */
2168                                         if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
2169                                                 continue;
2170
2171                                         psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
2172                                 }
2173
2174                                 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
2175                                         && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
2176                                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2177
2178                                 startframe = MIN2(startframe, cache->startframe);
2179
2180                                 if(bake || render) {
2181                                         cache->flag |= PTCACHE_BAKING;
2182
2183                                         if(bake)
2184                                                 endframe = MAX2(endframe, cache->endframe);
2185                                 }
2186
2187                                 cache->flag &= ~PTCACHE_BAKED;
2188
2189                         }
2190                 }
2191                 BLI_freelistN(&pidlist);
2192         }
2193
2194         CFRA= startframe;
2195         scene->r.framelen = 1.0;
2196
2197         for(; CFRA <= endframe; CFRA+=step) {
2198                 int prog;
2199
2200                 if(bake)
2201                         prog = (int)(100.0f * (float)(CFRA - startframe)/(float)(endframe-startframe));
2202                 else
2203                         prog = CFRA;
2204
2205                 /* NOTE: baking should not redraw whole ui as this slows things down */
2206                 if(baker->progressbar)
2207                         baker->progressbar(baker->progresscontext, prog);
2208                 
2209                 scene_update_for_newframe(scene, scene->lay);
2210
2211                 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
2212                 if(baker->break_test && baker->break_test(baker->break_data))
2213                         break;
2214         }
2215
2216         /* clear baking flag */
2217         if(pid) {
2218                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
2219                 cache->flag |= PTCACHE_SIMULATION_VALID;
2220                 if(bake) {
2221                         cache->flag |= PTCACHE_BAKED;
2222                         /* write info file */
2223                         if(cache->flag & PTCACHE_DISK_CACHE)
2224                                 BKE_ptcache_write_cache(pid, 0);
2225                 }
2226         }
2227         else for(base=scene->base.first; base; base= base->next) {
2228                 BKE_ptcache_ids_from_object(&pidlist, base->object);
2229
2230                 for(pid=pidlist.first; pid; pid=pid->next) {
2231                         /* skip hair particles */
2232                         if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
2233                                 continue;
2234                 
2235                         cache = pid->cache;
2236
2237                         if(step > 1)
2238                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
2239                         else
2240                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
2241
2242                         cache->flag |= PTCACHE_SIMULATION_VALID;
2243
2244                         if(bake) {
2245                                 cache->flag |= PTCACHE_BAKED;
2246                                 if(cache->flag & PTCACHE_DISK_CACHE)
2247                                         BKE_ptcache_write_cache(pid, 0);
2248                         }
2249                 }
2250                 BLI_freelistN(&pidlist);
2251         }
2252
2253         scene->r.framelen = frameleno;
2254         CFRA = cfrao;
2255
2256         if(bake) /* already on cfra unless baking */
2257                 scene_update_for_newframe(scene, scene->lay);
2258
2259         /* TODO: call redraw all windows somehow */
2260 }
2261 /* Helpers */
2262 void BKE_ptcache_disk_to_mem(PTCacheID *pid)
2263 {
2264         PointCache *cache = pid->cache;
2265         PTCacheFile *pf;
2266         PTCacheMem *pm;
2267
2268         int cfra, sfra = cache->startframe, efra = cache->endframe;
2269         int i;
2270
2271         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2272
2273         for(cfra=sfra; cfra <= efra; cfra++) {
2274                 pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
2275
2276                 if(pf) {
2277                         if(!ptcache_file_read_header_begin(pf)) {
2278                                 printf("Can't yet convert old cache format\n");
2279                                 cache->flag |= PTCACHE_DISK_CACHE;
2280                                 ptcache_file_close(pf);
2281                                 return;
2282                         }
2283
2284                         if(pf->type != pid->type || !pid->read_header(pf)) {
2285                                 cache->flag |= PTCACHE_DISK_CACHE;
2286                                 ptcache_file_close(pf);
2287                                 return;
2288                         }
2289                         
2290                         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2291
2292                         pm->totpoint = pf->totpoint;
2293                         pm->data_types = pf->data_types;
2294                         pm->frame = cfra;
2295
2296                         ptcache_alloc_data(pm);
2297                         BKE_ptcache_mem_init_pointers(pm);
2298                         ptcache_file_init_pointers(pf);
2299
2300                         for(i=0; i<pm->totpoint; i++) {
2301                                 if(!ptcache_file_read_data(pf)) {
2302                                         printf("Error reading from disk cache\n");
2303                                         
2304                                         cache->flag |= PTCACHE_DISK_CACHE;
2305                                         
2306                                         ptcache_free_data(pm->data);
2307                                         MEM_freeN(pm);
2308                                         ptcache_file_close(pf);
2309
2310                                         return;
2311                                 }
2312                                 ptcache_copy_data(pf->cur, pm->cur);
2313                                 BKE_ptcache_mem_incr_pointers(pm);
2314                         }
2315
2316                         //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
2317
2318                         BLI_addtail(&pid->cache->mem_cache, pm);
2319
2320                         ptcache_file_close(pf);
2321                 }
2322         }
2323
2324 }
2325 void BKE_ptcache_mem_to_disk(PTCacheID *pid)
2326 {
2327         PointCache *cache = pid->cache;
2328         PTCacheFile *pf;
2329         PTCacheMem *pm;
2330         int i;
2331
2332         pm = cache->mem_cache.first;
2333
2334         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2335
2336         for(; pm; pm=pm->next) {
2337                 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
2338
2339                 if(pf) {
2340                         pf->data_types = pm->data_types;
2341                         pf->totpoint = pm->totpoint;
2342                         pf->type = pid->type;
2343
2344                         BKE_ptcache_mem_init_pointers(pm);
2345                         ptcache_file_init_pointers(pf);
2346
2347                         if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
2348                                 printf("Error writing to disk cache\n");
2349                                 cache->flag &= ~PTCACHE_DISK_CACHE;
2350
2351                                 ptcache_file_close(pf);
2352                                 return;
2353                         }
2354
2355                         for(i=0; i<pm->totpoint; i++) {
2356                                 ptcache_copy_data(pm->cur, pf->cur);
2357                                 if(!ptcache_file_write_data(pf)) {
2358                                         printf("Error writing to disk cache\n");
2359                                         cache->flag &= ~PTCACHE_DISK_CACHE;
2360
2361                                         ptcache_file_close(pf);
2362                                         return;
2363                                 }
2364                                 BKE_ptcache_mem_incr_pointers(pm);
2365                         }
2366
2367                         ptcache_file_close(pf);
2368
2369                         /* write info file */
2370                         if(cache->flag & PTCACHE_BAKED)
2371                                 BKE_ptcache_write_cache(pid, 0);
2372                 }
2373                 else
2374                         printf("Error creating disk cache file\n");
2375         }
2376 }
2377 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
2378 {
2379         PointCache *cache = pid->cache;
2380         int last_exact = cache->last_exact;
2381
2382         if (!G.relbase_valid){
2383                 cache->flag &= ~PTCACHE_DISK_CACHE;
2384                 printf("File must be saved before using disk cache!\n");
2385                 return;
2386         }
2387
2388         if(cache->flag & PTCACHE_DISK_CACHE)
2389                 BKE_ptcache_mem_to_disk(pid);
2390         else
2391                 BKE_ptcache_disk_to_mem(pid);
2392
2393         cache->flag ^= PTCACHE_DISK_CACHE;
2394         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2395         cache->flag ^= PTCACHE_DISK_CACHE;
2396         
2397         cache->last_exact = last_exact;
2398
2399         BKE_ptcache_update_info(pid);
2400 }
2401
2402 void BKE_ptcache_load_external(PTCacheID *pid)
2403 {
2404         /*todo*/
2405         PointCache *cache = pid->cache;
2406         int len; /* store the length of the string */
2407         int info = 0;
2408
2409         /* mode is same as fopen's modes */
2410         DIR *dir; 
2411         struct dirent *de;
2412         char path[MAX_PTCACHE_PATH];
2413         char filename[MAX_PTCACHE_FILE];
2414         char ext[MAX_PTCACHE_PATH];
2415
2416         if(!cache)
2417                 return;
2418
2419         cache->startframe = MAXFRAME;
2420         cache->endframe = -1;
2421         cache->totpoint = 0;
2422
2423         ptcache_path(pid, path);
2424         
2425         len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */
2426         
2427         dir = opendir(path);
2428         if (dir==NULL)
2429                 return;
2430
2431         if(cache->index >= 0)
2432                 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
2433         else
2434                 strcpy(ext, PTCACHE_EXT);
2435         
2436         while ((de = readdir(dir)) != NULL) {
2437                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2438                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2439                                 /* read the number of the file */
2440                                 int frame, len2 = (int)strlen(de->d_name);
2441                                 char num[7];
2442
2443                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2444                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2445                                         frame = atoi(num);
2446
2447                                         if(frame) {
2448                                                 cache->startframe = MIN2(cache->startframe, frame);
2449                                                 cache->endframe = MAX2(cache->endframe, frame);
2450                                         }
2451                                         else
2452                                                 info = 1;
2453                                 }
2454                         }
2455                 }
2456         }
2457         closedir(dir);
2458
2459         if(cache->startframe != MAXFRAME) {
2460                 PTCacheFile *pf;
2461
2462                 /* read totpoint from info file (frame 0) */
2463                 if(info) {
2464                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
2465
2466                         if(pf) {
2467                                 if(ptcache_file_read_header_begin(pf)) {
2468                                         if(pf->type == pid->type && pid->read_header(pf)) {
2469                                                 cache->totpoint = pf->totpoint;
2470                                                 cache->flag |= PTCACHE_READ_INFO;
2471                                         }
2472                                         else {
2473                                                 cache->totpoint = 0;
2474                                         }
2475                                 }
2476                                 ptcache_file_close(pf);
2477                         }
2478                 }
2479                 /* or from any old format cache file */
2480                 else {
2481                         float old_data[14];
2482                         int elemsize = ptcache_pid_old_elemsize(pid);
2483                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
2484
2485                         if(pf) {
2486                                 while(ptcache_file_read(pf, old_data, 1, elemsize))
2487                                         cache->totpoint++;
2488                                 
2489                                 ptcache_file_close(pf);
2490                         }
2491                 }
2492         }
2493
2494         cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
2495
2496         BKE_ptcache_update_info(pid);
2497 }
2498
2499 void BKE_ptcache_update_info(PTCacheID *pid)
2500 {
2501         PointCache *cache = pid->cache;
2502         int totframes = 0;
2503         char mem_info[64];
2504
2505         if(cache->flag & PTCACHE_EXTERNAL) {
2506                 int cfra = cache->startframe;
2507
2508                 for(; cfra<=cache->endframe; cfra++) {
2509                         if(BKE_ptcache_id_exist(pid, cfra))
2510                                 totframes++;
2511                 }
2512
2513                 if(totframes && cache->totpoint)
2514                         sprintf(cache->info, "%i points found!", cache->totpoint);
2515                 else
2516                         sprintf(cache->info, "No valid data to read!");
2517                 return;
2518         }
2519
2520         if(cache->flag & PTCACHE_DISK_CACHE) {
2521                 int cfra = cache->startframe;
2522
2523                 for(; cfra<=cache->endframe; cfra++) {
2524                         if(BKE_ptcache_id_exist(pid, cfra))
2525                                 totframes++;
2526                 }
2527
2528                 sprintf(mem_info, "%i frames on disk", totframes);
2529         }
2530         else {
2531                 PTCacheMem *pm = cache->mem_cache.first;                
2532                 float framesize = 0.0f, bytes = 0.0f;
2533                 int mb;
2534
2535                 if(pm)
2536                         framesize = (float)ptcache_pid_old_elemsize(pid) * (float)pm->totpoint;
2537                 
2538                 for(; pm; pm=pm->next)
2539                         totframes++;
2540
2541                 bytes = totframes * framesize;
2542
2543                 mb = (bytes > 1024.0f * 1024.0f);
2544
2545                 sprintf(mem_info, "%i frames in memory (%.1f %s)",
2546                         totframes,
2547                         bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
2548                         mb ? "Mb" : "kb");
2549         }
2550
2551         if(cache->flag & PTCACHE_OUTDATED) {
2552                 sprintf(cache->info, "%s, cache is outdated!", mem_info);
2553         }
2554         else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
2555                 sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
2556         }
2557         else
2558                 sprintf(cache->info, "%s.", mem_info);
2559 }