649c26242ce53c8fb30f73fc1b1c60f1e3eaef62
[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
43 #include "BLI_blenlib.h"
44
45 #include "BKE_cloth.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_global.h"
48 #include "BKE_library.h"
49 #include "BKE_main.h"
50 #include "BKE_modifier.h"
51 #include "BKE_object.h"
52 #include "BKE_particle.h"
53 #include "BKE_pointcache.h"
54 #include "BKE_scene.h"
55 #include "BKE_softbody.h"
56 #include "BKE_utildefines.h"
57
58 #include "BLI_blenlib.h"
59
60 /* needed for directory lookup */
61 #ifndef WIN32
62   #include <dirent.h>
63 #else
64   #include "BLI_winstuff.h"
65 #endif
66
67 /* untitled blend's need getpid for a unique name */
68 #ifdef WIN32
69 #include <process.h>
70 #else
71 #include <unistd.h>
72 #endif
73
74 #ifdef _WIN32
75 #ifndef snprintf
76 #define snprintf _snprintf
77 #endif
78 #endif
79
80 static void ptcache_data_to(void **data, int type, int index, void *to);
81 static void ptcache_data_from(void **data, int type, void *from);
82
83 /* Common functions */
84 static int ptcache_read_basic_header(PTCacheFile *pf)
85 {
86         int error=0;
87
88         /* Custom functions should read these basic elements too! */
89         if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp))
90                 error = 1;
91         
92         if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp))
93                 error = 1;
94
95         return !error;
96 }
97 static int ptcache_write_basic_header(PTCacheFile *pf)
98 {
99         /* Custom functions should write these basic elements too! */
100         if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp))
101                 return 0;
102         
103         if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp))
104                 return 0;
105
106         return 1;
107 }
108 /* Softbody functions */
109 static int ptcache_write_softbody(int index, void *soft_v, void **data)
110 {
111         SoftBody *soft= soft_v;
112         BodyPoint *bp = soft->bpoint + index;
113
114         ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos);
115         ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec);
116
117         return 1;
118 }
119 static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data)
120 {
121         SoftBody *soft= soft_v;
122         BodyPoint *bp = soft->bpoint + index;
123
124         if(old_data) {
125                 memcpy(bp->pos, data, 3 * sizeof(float));
126                 memcpy(bp->vec, data + 3, 3 * sizeof(float));
127         }
128         else {
129                 ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos);
130                 ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
131         }
132 }
133 static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
134 {
135         SoftBody *soft= soft_v;
136         BodyPoint *bp = soft->bpoint + index;
137         ParticleKey keys[4];
138         float dfra;
139
140         if(cfra1 == cfra2)
141                 return;
142
143         VECCOPY(keys[1].co, bp->pos);
144         VECCOPY(keys[1].vel, bp->vec);
145
146         if(old_data) {
147                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
148                 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
149         }
150         else
151                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
152
153         dfra = cfra2 - cfra1;
154
155         VecMulf(keys[1].vel, dfra);
156         VecMulf(keys[2].vel, dfra);
157
158         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
159
160         VecMulf(keys->vel, 1.0f / dfra);
161
162         VECCOPY(bp->pos, keys->co);
163         VECCOPY(bp->vec, keys->vel);
164 }
165 static int ptcache_totpoint_softbody(void *soft_v)
166 {
167         SoftBody *soft= soft_v;
168         return soft->totpoint;
169 }
170 /* Particle functions */
171 static int ptcache_write_particle(int index, void *psys_v, void **data)
172 {
173         ParticleSystem *psys= psys_v;
174         ParticleData *pa = psys->particles + index;
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(pa->boid)
193                 ptcache_data_from(data, BPHYS_DATA_TIMES, &pa->boid);
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
210         if(cfra > pa->state.time)
211                 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
212
213         if(old_data){
214                 /* old format cache */
215                 memcpy(&pa->state, old_data, sizeof(ParticleKey));
216                 return;
217         }
218
219         BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
220
221         if(data[BPHYS_DATA_SIZE])
222                 ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size);
223         
224         if(data[BPHYS_DATA_TIMES]) {
225                 float times[3];
226                 ptcache_data_to(data, BPHYS_DATA_TIMES, 0, &times);
227                 pa->time = times[0];
228                 pa->dietime = times[1];
229                 pa->lifetime = times[2];
230         }
231
232         if(pa->boid)
233                 ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &pa->boid);
234
235         /* determine velocity from previous location */
236         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
237                 if(cfra > pa->prev_state.time) {
238                         VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co);
239                         VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
240                 }
241                 else {
242                         VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co);
243                         VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
244                 }
245         }
246
247         /* determine rotation from velocity */
248         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
249                 vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot);
250         }
251 }
252 static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
253 {
254         ParticleSystem *psys= psys_v;
255         ParticleData *pa = psys->particles + index;
256         ParticleKey keys[4];
257         float dfra;
258
259         cfra = MIN2(cfra, pa->dietime);
260         cfra1 = MIN2(cfra1, pa->dietime);
261         cfra2 = MIN2(cfra2, pa->dietime);
262
263         if(cfra1 == cfra2)
264                 return;
265
266         memcpy(keys+1, &pa->state, sizeof(ParticleKey));
267         if(old_data)
268                 memcpy(keys+2, old_data, sizeof(ParticleKey));
269         else
270                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
271
272         dfra = cfra2 - cfra1;
273
274         VecMulf(keys[1].vel, dfra / frs_sec);
275         VecMulf(keys[2].vel, dfra / frs_sec);
276
277         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
278         QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
279
280         VecMulf(pa->state.vel, frs_sec / dfra);
281
282         pa->state.time = cfra;
283 }
284
285 static int ptcache_totpoint_particle(void *psys_v)
286 {
287         ParticleSystem *psys = psys_v;
288         return psys->totpart;
289 }
290 static int ptcache_totwrite_particle(void *psys_v)
291 {
292         ParticleSystem *psys = psys_v;
293         int totwrite = 0;
294
295         /* TODO for later */
296         //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0) {
297         //      ParticleData *pa= psys->particles;
298         //      int p, step = psys->pointcache->step;
299
300         //      for(p=0; p<psys->totpart; p++,pa++)
301         //              totwrite += (pa->time - step > pa->state.time || pa->dietime + step > pa->state.time);
302         //}
303         //else
304                 totwrite= psys->totpart;
305
306         return totwrite;
307 }
308 /* Cloth functions */
309 static int ptcache_write_cloth(int index, void *cloth_v, void **data)
310 {
311         ClothModifierData *clmd= cloth_v;
312         Cloth *cloth= clmd->clothObject;
313         ClothVertex *vert = cloth->verts + index;
314
315         ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x);
316         ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v);
317         ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst);
318
319         return 1;
320 }
321 static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data)
322 {
323         ClothModifierData *clmd= cloth_v;
324         Cloth *cloth= clmd->clothObject;
325         ClothVertex *vert = cloth->verts + index;
326         
327         if(old_data) {
328                 memcpy(vert->x, data, 3 * sizeof(float));
329                 memcpy(vert->xconst, data + 3, 3 * sizeof(float));
330                 memcpy(vert->v, data + 6, 3 * sizeof(float));
331         }
332         else {
333                 ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x);
334                 ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v);
335                 ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst);
336         }
337 }
338 static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
339 {
340         ClothModifierData *clmd= cloth_v;
341         Cloth *cloth= clmd->clothObject;
342         ClothVertex *vert = cloth->verts + index;
343         ParticleKey keys[4];
344         float dfra;
345
346         if(cfra1 == cfra2)
347                 return;
348
349         VECCOPY(keys[1].co, vert->x);
350         VECCOPY(keys[1].vel, vert->v);
351
352         if(old_data) {
353                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
354                 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
355         }
356         else
357                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
358
359         dfra = cfra2 - cfra1;
360
361         VecMulf(keys[1].vel, dfra);
362         VecMulf(keys[2].vel, dfra);
363
364         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
365
366         VecMulf(keys->vel, 1.0f / dfra);
367
368         VECCOPY(vert->x, keys->co);
369         VECCOPY(vert->v, keys->vel);
370
371         /* should vert->xconst be interpolated somehow too? - jahka */
372 }
373
374 static int ptcache_totpoint_cloth(void *cloth_v)
375 {
376         ClothModifierData *clmd= cloth_v;
377         return clmd->clothObject->numverts;
378 }
379 /* Creating ID's */
380 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
381 {
382         ParticleSystemModifierData *psmd;
383         ModifierData *md;
384         int a;
385
386         memset(pid, 0, sizeof(PTCacheID));
387
388         pid->ob= ob;
389         pid->calldata= sb;
390         pid->type= PTCACHE_TYPE_SOFTBODY;
391         pid->cache= sb->pointcache;
392         pid->cache_ptr= &sb->pointcache;
393         pid->ptcaches= &sb->ptcaches;
394         pid->totpoint= pid->totwrite= ptcache_totpoint_softbody;
395
396         pid->write_elem= ptcache_write_softbody;
397         pid->read_elem= ptcache_read_softbody;
398         pid->interpolate_elem= ptcache_interpolate_softbody;
399
400         pid->write_header= ptcache_write_basic_header;
401         pid->read_header= ptcache_read_basic_header;
402
403         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
404         pid->info_types= 0;
405
406         if(sb->particles) {
407                 psmd= psys_get_modifier(ob, sb->particles);
408                 pid->stack_index= modifiers_indexInObject(ob, (ModifierData*)psmd);
409         }
410         else {
411                 for(a=0, md=ob->modifiers.first; md; md=md->next, a++) {
412                         if(md->type == eModifierType_Softbody) {
413                                 pid->stack_index = a;
414                                 break;
415                         }
416                 }
417         }
418 }
419
420 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
421 {
422         ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
423
424         memset(pid, 0, sizeof(PTCacheID));
425
426         pid->ob= ob;
427         pid->calldata= psys;
428         pid->type= PTCACHE_TYPE_PARTICLES;
429         pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)psmd);
430         pid->cache= psys->pointcache;
431         pid->cache_ptr= &psys->pointcache;
432         pid->ptcaches= &psys->ptcaches;
433
434         pid->write_elem= ptcache_write_particle;
435         pid->read_elem= ptcache_read_particle;
436         pid->interpolate_elem= ptcache_interpolate_particle;
437
438         pid->totpoint= ptcache_totpoint_particle;
439         pid->totwrite= ptcache_totwrite_particle;
440
441         pid->write_header= ptcache_write_basic_header;
442         pid->read_header= ptcache_read_basic_header;
443
444         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
445
446         if(psys->part)
447         {
448                 /* TODO for later */
449                 //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0)
450                 //      pid->data_types|= (1<<BPHYS_DATA_INDEX);
451
452                 if(psys->part->phystype == PART_PHYS_BOIDS)
453                         pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
454
455                 if(psys->part->rotmode || psys->part->avemode)
456                         pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
457
458                 if(psys->part->flag & PART_ROT_DYN)
459                         pid->data_types|= (1<<BPHYS_DATA_ROTATION);
460         }
461
462         pid->info_types= (1<<BPHYS_DATA_TIMES);
463 }
464
465 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
466 {
467         memset(pid, 0, sizeof(PTCacheID));
468
469         pid->ob= ob;
470         pid->calldata= clmd;
471         pid->type= PTCACHE_TYPE_CLOTH;
472         pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)clmd);
473         pid->cache= clmd->point_cache;
474         pid->cache_ptr= &clmd->point_cache;
475         pid->ptcaches= &clmd->ptcaches;
476         pid->totpoint= pid->totwrite= ptcache_totpoint_cloth;
477
478         pid->write_elem= ptcache_write_cloth;
479         pid->read_elem= ptcache_read_cloth;
480         pid->interpolate_elem= ptcache_interpolate_cloth;
481
482         pid->write_header= ptcache_write_basic_header;
483         pid->read_header= ptcache_read_basic_header;
484
485         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
486         pid->info_types= 0;
487 }
488
489 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
490 {
491         PTCacheID *pid;
492         ParticleSystem *psys;
493         ModifierData *md;
494
495         lb->first= lb->last= NULL;
496
497         if(ob->soft) {
498                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
499                 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
500                 BLI_addtail(lb, pid);
501         }
502
503         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
504                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
505                 BKE_ptcache_id_from_particles(pid, ob, psys);
506                 BLI_addtail(lb, pid);
507
508                 if(psys->soft) {
509                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
510                         BKE_ptcache_id_from_softbody(pid, ob, psys->soft);
511                         BLI_addtail(lb, pid);
512                 }
513         }
514
515         for(md=ob->modifiers.first; md; md=md->next) {
516                 if(md->type == eModifierType_Cloth) {
517                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
518                         BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
519                         BLI_addtail(lb, pid);
520                 }
521         }
522 }
523
524
525 /* File handling */
526
527 /*      Takes an Object ID and returns a unique name
528         - id: object id
529         - cfra: frame for the cache, can be negative
530         - stack_index: index in the modifier stack. we can have cache for more then one stack_index
531 */
532
533 #define MAX_PTCACHE_PATH FILE_MAX
534 #define MAX_PTCACHE_FILE ((FILE_MAXDIR+FILE_MAXFILE)*2)
535
536 static int ptcache_path(PTCacheID *pid, char *filename)
537 {
538         Library *lib;
539         int i;
540
541         lib= (pid)? pid->ob->id.lib: NULL;
542
543         if(pid->cache->flag & PTCACHE_EXTERNAL) {
544                 strcpy(filename, pid->cache->path);
545                 return BLI_add_slash(filename); /* new strlen() */
546         }
547         else if (G.relbase_valid || lib) {
548                 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */
549                 char *blendfilename;
550
551                 blendfilename= (lib)? lib->filename: G.sce;
552
553                 BLI_split_dirfile_basic(blendfilename, NULL, file);
554                 i = strlen(file);
555                 
556                 /* remove .blend */
557                 if (i > 6)
558                         file[i-6] = '\0';
559                 
560                 snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
561                 BLI_convertstringcode(filename, blendfilename);
562                 return BLI_add_slash(filename); /* new strlen() */
563         }
564         
565         /* use the temp path. this is weak but better then not using point cache at all */
566         /* btempdir is assumed to exist and ALWAYS has a trailing slash */
567         snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", btempdir, abs(getpid()));
568         
569         return BLI_add_slash(filename); /* new strlen() */
570 }
571
572 static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
573 {
574         int len=0;
575         char *idname;
576         char *newname;
577         filename[0] = '\0';
578         newname = filename;
579         
580         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
581         
582         /* start with temp dir */
583         if (do_path) {
584                 len = ptcache_path(pid, filename);
585                 newname += len;
586         }
587         if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
588                 idname = (pid->ob->id.name+2);
589                 /* convert chars to hex so they are always a valid filename */
590                 while('\0' != *idname) {
591                         snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
592                         newname+=2;
593                         len += 2;
594                 }
595         }
596         else {
597                 int temp = strlen(pid->cache->name); 
598                 strcpy(newname, pid->cache->name); 
599                 newname+=temp;
600                 len += temp;
601         }
602
603         if (do_ext) {
604                 if(pid->cache->flag & PTCACHE_EXTERNAL) {
605                         if(pid->cache->index >= 0)
606                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
607                         else
608                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
609                 }
610                 else {
611                         snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
612                 }
613                 len += 16;
614         }
615         
616         return len; /* make sure the above string is always 16 chars */
617 }
618
619 /* youll need to close yourself after! */
620 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
621 {
622         PTCacheFile *pf;
623         FILE *fp = NULL;
624         char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
625
626         /* don't allow writing for linked objects */
627         if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
628                 return NULL;
629
630         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
631         
632         BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
633
634         if (mode==PTCACHE_FILE_READ) {
635                 if (!BLI_exists(filename)) {
636                         return NULL;
637                 }
638                 fp = fopen(filename, "rb");
639         } else if (mode==PTCACHE_FILE_WRITE) {
640                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
641                 fp = fopen(filename, "wb");
642         }
643
644         if (!fp)
645                 return NULL;
646         
647         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
648         pf->fp= fp;
649         
650         return pf;
651 }
652
653 static void ptcache_file_close(PTCacheFile *pf)
654 {
655         fclose(pf->fp);
656         MEM_freeN(pf);
657 }
658
659 static int ptcache_file_read(PTCacheFile *pf, void *f, int tot, int size)
660 {
661         return (fread(f, size, tot, pf->fp) == tot);
662 }
663 static int ptcache_file_write(PTCacheFile *pf, void *f, int tot, int size)
664 {
665         return (fwrite(f, size, tot, pf->fp) == tot);
666 }
667 static int ptcache_file_read_data(PTCacheFile *pf)
668 {
669         int i;
670
671         for(i=0; i<BPHYS_TOT_DATA; i++) {
672                 if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
673                         return 0;
674         }
675         
676         return 1;
677 }
678 static int ptcache_file_write_data(PTCacheFile *pf)
679 {               
680         int i;
681
682         for(i=0; i<BPHYS_TOT_DATA; i++) {
683                 if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
684                         return 0;
685         }
686         
687         return 1;
688 }
689 static int ptcache_file_read_header_begin(PTCacheFile *pf)
690 {
691         int error=0;
692         char bphysics[8];
693         
694         pf->data_types = 0;
695         
696         if(fread(bphysics, sizeof(char), 8, pf->fp) != 8)
697                 error = 1;
698         
699         if(!error && strncmp(bphysics, "BPHYSICS", 8))
700                 error = 1;
701
702         if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp))
703                 error = 1;
704         
705         /* if there was an error set file as it was */
706         if(error)
707                 fseek(pf->fp, 0, SEEK_SET);
708
709         return !error;
710 }
711
712
713 static int ptcache_file_write_header_begin(PTCacheFile *pf)
714 {
715         char *bphysics = "BPHYSICS";
716         
717         if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
718                 return 0;
719
720         if(!fwrite(&pf->type, sizeof(int), 1, pf->fp))
721                 return 0;
722         
723         return 1;
724 }
725
726
727 /* Data pointer handling */
728 int BKE_ptcache_data_size(int data_type)
729 {
730         switch(data_type) {
731                 case BPHYS_DATA_INDEX:
732                         return sizeof(int);
733                 case BPHYS_DATA_LOCATION:
734                 case BPHYS_DATA_VELOCITY:
735                 case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */
736                 case BPHYS_DATA_TIMES:
737                         return 3 * sizeof(float);
738                 case BPHYS_DATA_ROTATION:
739                         return 4 * sizeof(float);
740                 case BPHYS_DATA_SIZE:
741                         return sizeof(float);
742                 case BPHYS_DATA_BOIDS:
743                         return sizeof(BoidData);
744                 default:
745                         return 0;
746         }
747 }
748 static void ptcache_data_to(void **data, int type, int index, void *to)
749 {
750         if(data[type]) {
751                 if(index)
752                         memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type));
753                 else
754                         memcpy(to, data[type], BKE_ptcache_data_size(type));
755         }
756 }
757
758 static void ptcache_data_from(void **data, int type, void *from)
759 {
760         if(data[type])
761                 memcpy(data[type], from, BKE_ptcache_data_size(type));
762 }
763
764 static void ptcache_file_init_pointers(PTCacheFile *pf)
765 {
766         int data_types = pf->data_types;
767
768         pf->cur[BPHYS_DATA_INDEX] =             data_types & (1<<BPHYS_DATA_INDEX) ?            &pf->data.index : NULL;
769         pf->cur[BPHYS_DATA_LOCATION] =  data_types & (1<<BPHYS_DATA_LOCATION) ?         &pf->data.loc   : NULL;
770         pf->cur[BPHYS_DATA_VELOCITY] =  data_types & (1<<BPHYS_DATA_VELOCITY) ?         &pf->data.vel   : NULL;
771         pf->cur[BPHYS_DATA_ROTATION] =  data_types & (1<<BPHYS_DATA_ROTATION) ?         &pf->data.rot   : NULL;
772         pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ?        &pf->data.ave   : NULL;
773         pf->cur[BPHYS_DATA_SIZE] =              data_types & (1<<BPHYS_DATA_SIZE)       ?               &pf->data.size  : NULL;
774         pf->cur[BPHYS_DATA_TIMES] =             data_types & (1<<BPHYS_DATA_TIMES) ?            &pf->data.times : NULL;
775         pf->cur[BPHYS_DATA_BOIDS] =             data_types & (1<<BPHYS_DATA_BOIDS) ?            &pf->data.boids : NULL;
776 }
777
778 static void ptcache_mem_init_pointers(PTCacheMem *pm)
779 {
780         int data_types = pm->data_types;
781         int i;
782
783         for(i=0; i<BPHYS_TOT_DATA; i++)
784                 pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL;
785 }
786
787 static void ptcache_mem_incr_pointers(PTCacheMem *pm)
788 {
789         int i;
790
791         for(i=0; i<BPHYS_TOT_DATA; i++) {
792                 if(pm->cur[i])
793                         pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i);
794         }
795 }
796 static void ptcache_alloc_data(PTCacheMem *pm)
797 {
798         int data_types = pm->data_types;
799         int totpoint = pm->totpoint;
800         int i;
801
802         for(i=0; i<BPHYS_TOT_DATA; i++) {
803                 if(data_types & (1<<i))
804                         pm->data[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data");
805         }
806 }
807 static void ptcache_free_data(void *data[])
808 {
809         int i;
810
811         for(i=0; i<BPHYS_TOT_DATA; i++) {
812                 if(data[i])
813                         MEM_freeN(data[i]);
814         }
815 }
816 static void ptcache_copy_data(void *from[], void *to[])
817 {
818         int i;
819         for(i=0; i<BPHYS_TOT_DATA; i++) {
820                 if(from[i])
821                         memcpy(to[i], from[i], BKE_ptcache_data_size(i));
822         }
823 }
824
825
826
827 static int ptcache_pid_old_elemsize(PTCacheID *pid)
828 {
829         if(pid->type==PTCACHE_TYPE_SOFTBODY)
830                 return 6 * sizeof(float);
831         else if(pid->type==PTCACHE_TYPE_PARTICLES)
832                 return sizeof(ParticleKey);
833         else if(pid->type==PTCACHE_TYPE_CLOTH)
834                 return 9 * sizeof(float);
835
836         return 0;
837 }
838
839 /* reads cache from disk or memory */
840 /* possible to get old or interpolated result */
841 int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec)
842 {
843         PTCacheFile *pf=NULL, *pf2=NULL;
844         PTCacheMem *pm=NULL, *pm2=NULL;
845         float old_data1[14], old_data2[14];
846         int cfrai = (int)cfra;
847         int old_elemsize = ptcache_pid_old_elemsize(pid);
848         int i, incr = old_elemsize / sizeof(float);
849
850         int cfra1 = 0, cfra2 = 0;
851         int totpoint = 0, totpoint2 = 0;
852         int *index = &i, *index2 = &i;
853         int use_old = 0, old_frame;
854
855         int ret = 0, error = 0;
856
857         /* nothing to read to */
858         if(pid->totpoint(pid->calldata) == 0)
859                 return 0;
860
861         if(pid->cache->flag & PTCACHE_READ_INFO) {
862                 pid->cache->flag &= ~PTCACHE_READ_INFO;
863                 BKE_ptcache_read_cache(pid, 0, frs_sec);
864         }
865
866
867         /* first check if we have the actual frame cached */
868         if(cfra == (float)cfrai) {
869                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
870                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
871                 }
872                 else {
873                         pm = pid->cache->mem_cache.first;
874
875                         for(; pm; pm=pm->next) {
876                                 if(pm->frame == cfrai)
877                                         break;
878                         }
879                 }
880         }
881
882         /* no exact cache frame found so try to find cached frames around cfra */
883         if(!pm && !pf) {
884                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
885                         pf=NULL;
886                         while(cfrai > pid->cache->startframe && !pf) {
887                                 cfrai--;
888                                 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
889                                 cfra1 = cfrai;
890                         }
891
892                         old_frame = cfrai;
893
894                         cfrai = (int)cfra;
895                         while(cfrai < pid->cache->endframe && !pf2) {
896                                 cfrai++;
897                                 pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
898                                 cfra2 = cfrai;
899                         }
900
901                         if(pf && !pf2) {
902                                 pf2 = pf;
903                                 pf = NULL;
904                         }
905                 }
906                 else if(pid->cache->mem_cache.first){
907                         pm = pid->cache->mem_cache.first;
908
909                         while(pm->next && pm->next->frame < cfra)
910                                 pm= pm->next;
911
912                         if(pm) {
913                                 old_frame = pm->frame;
914                                 cfra1 = pm->frame;
915                         }
916
917                         pm2 = pid->cache->mem_cache.last;
918
919                         if(pm2 && pm2->frame < cfra)
920                                 pm2 = NULL;
921                         else {
922                                 while(pm2->prev && pm2->prev->frame > cfra)
923                                         pm2= pm2->prev;
924
925                                 if(pm2)
926                                         cfra2 = pm2->frame;
927                         }
928
929                         if(pm && !pm2) {
930                                 pm2 = pm;
931                                 pm = NULL;
932                         }
933                 }
934         }
935
936         if(!pm && !pm2 && !pf && !pf2)
937                 return 0;
938
939         if(pm) {
940                 ptcache_mem_init_pointers(pm);
941                 totpoint = pm->totpoint;
942                 index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
943         }
944         if(pm2) {
945                 ptcache_mem_init_pointers(pm2);
946                 totpoint2 = pm2->totpoint;
947                 index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
948         }
949         if(pf) {
950                 if(ptcache_file_read_header_begin(pf)) {
951                         if(pf->type != pid->type) {
952                                 /* todo report error */
953                                 ptcache_file_close(pf);
954                                 pf = NULL;
955                         }
956                         else if(pid->read_header(pf)) {
957                                 ptcache_file_init_pointers(pf);
958                                 totpoint = pf->totpoint;
959                                 index = pf->data_types & BPHYS_DATA_INDEX ? &pf->data.index : &i;
960                         }
961                 }
962                 else {
963                         /* fall back to old cache file format */
964                         use_old = 1;
965                         totpoint = pid->totpoint(pid->calldata);
966                 }
967         }
968         if(pf2) {
969                 if(ptcache_file_read_header_begin(pf2)) {
970                         if(pf2->type != pid->type) {
971                                 /* todo report error */
972                                 ptcache_file_close(pf2);
973                                 pf2 = NULL;
974                         }
975                         else if(pid->read_header(pf2)) {
976                                 ptcache_file_init_pointers(pf2);
977                                 totpoint2 = pf2->totpoint;
978                                 index2 = pf->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i;
979                         }
980                 }
981                 else {
982                         /* fall back to old cache file format */
983                         use_old = 1;
984                         totpoint2 = pid->totpoint(pid->calldata);
985                 }
986         }
987
988         /* don't read old cache if allready simulated past cached frame */
989         if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe)
990                 error = 1;
991         if(cfra1 && cfra1==cfra2)
992                 error = 1;
993
994         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata));
995         totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata));
996
997         if(!error) for(i=0; i<totpoint; i++) {
998                 /* read old cache file format */
999                 if(use_old) {
1000                         if(ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize))
1001                                 pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1);
1002                         else
1003                                 { error = 1; break; }
1004                 }
1005                 else {
1006                         if(pm || ptcache_file_read_data(pf))
1007                                 pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL);
1008                         else
1009                                 { error = 1; break; }
1010                 }
1011
1012                 if(pm) {
1013                         ptcache_mem_incr_pointers(pm);
1014                         index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
1015                 }
1016         }
1017
1018         if(!error) for(i=0; i<totpoint2; i++) {
1019                 /* read old cache file format */
1020                 if(use_old) {
1021                         if(ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) {
1022                                 if(!pf && pf2)
1023                                         pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2);
1024                                 else
1025                                         pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2);
1026                         }
1027                         else
1028                                 { error = 1; break; }
1029                 }
1030                 else {
1031                         if(pm2 || ptcache_file_read_data(pf2)) {
1032                                 if((!pf && pf2) || (!pm && pm2))
1033                                         pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL);
1034                                 else
1035                                         pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL);
1036                         }
1037                         else
1038                                 { error = 1; break; }
1039                 }
1040
1041                 if(pm2) {
1042                         ptcache_mem_incr_pointers(pm2);
1043                         index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
1044                 }
1045         }
1046
1047         if(pm || pf)
1048                 ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT;
1049         else if(pm2 || pf2) {
1050                 ret = PTCACHE_READ_OLD;
1051                 pid->cache->simframe = old_frame;
1052         }
1053
1054         if(pf) {
1055                 ptcache_file_close(pf);
1056                 pf = NULL;
1057         }
1058
1059         if(pf2) {
1060                 ptcache_file_close(pf2);
1061                 pf = NULL;
1062         }
1063
1064         if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
1065                 cfrai = (int)cfra;
1066                 /* clear invalid cache frames so that better stuff can be simulated */
1067                 if(pid->cache->flag & PTCACHE_OUTDATED) {
1068                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
1069                 }
1070                 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
1071                         if(cfra <= pid->cache->last_exact)
1072                                 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1073
1074                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact));
1075                 }
1076         }
1077
1078         return (error ? 0 : ret);
1079 }
1080 /* TODO for later */
1081 //static void ptcache_make_index_array(PTCacheMem *pm, int totpoint)
1082 //{
1083 //      int i, *index;
1084 //
1085 //      if(pm->index_array) {
1086 //              MEM_freeN(pm->index_array);
1087 //              pm->index_array = NULL;
1088 //      }
1089 //
1090 //      if(!pm->data[BPHYS_DATA_INDEX])
1091 //              return;
1092 //
1093 //      pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array");
1094 //      index = pm->data[BPHYS_DATA_INDEX];
1095 //
1096 //      for(i=0; i<pm->totpoint; i++, index++)
1097 //              pm->index_array[*index] = i;
1098 //}
1099 /* writes cache to disk or memory */
1100 int BKE_ptcache_write_cache(PTCacheID *pid, int cfra)
1101 {
1102         PointCache *cache = pid->cache;
1103         PTCacheFile *pf= NULL;
1104         int elemsize = ptcache_pid_old_elemsize(pid);
1105         int i, incr = elemsize / sizeof(float);
1106         int totpoint = pid->totpoint(pid->calldata);
1107         int add = 0, overwrite = 0;
1108
1109         if(totpoint == 0 || cfra < 0
1110                 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
1111                 return 0;
1112
1113         if(cache->flag & PTCACHE_DISK_CACHE) {
1114                 int efra = cache->endframe;
1115
1116                 if(cfra==0)
1117                         add = 1;
1118                 /* allways start from scratch on the first frame */
1119                 else if(cfra == cache->startframe) {
1120                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1121                         cache->flag &= ~PTCACHE_REDO_NEEDED;
1122                         add = 1;
1123                 }
1124                 else {
1125                         int ofra;
1126                         /* find last cached frame */
1127                         while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
1128                                 efra--;
1129
1130                         /* find second last cached frame */
1131                         ofra = efra-1;
1132                         while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
1133                                 ofra--;
1134
1135                         if(efra >= cache->startframe && cfra > efra) {
1136                                 if(ofra >= cache->startframe && efra - ofra < cache->step)
1137                                         overwrite = 1;
1138                                 else
1139                                         add = 1;
1140                         }
1141                 }
1142
1143                 if(add || overwrite) {
1144                         if(overwrite)
1145                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
1146
1147                         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
1148                         if(!pf)
1149                                 return 0;
1150
1151                         pf->type = pid->type;
1152                         pf->totpoint = cfra ? totpoint : pid->totwrite(pid->calldata);
1153                         pf->data_types = cfra ? pid->data_types : pid->info_types;
1154
1155                         if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
1156                                 ptcache_file_close(pf);
1157                                 return 0;
1158                         }
1159
1160                         ptcache_file_init_pointers(pf);
1161
1162                         for(i=0; i<totpoint; i++) {
1163                                 if(pid->write_elem(i, pid->calldata, pf->cur))
1164                                         if(!ptcache_file_write_data(pf)) {
1165                                                 ptcache_file_close(pf);
1166                                                 return 0;
1167                                         }
1168                         }
1169                 }
1170         }
1171         else {
1172                 PTCacheMem *pm;
1173                 PTCacheMem *pm2;
1174
1175                 pm2 = cache->mem_cache.first;
1176                 
1177                 /* don't write info file in memory */
1178                 if(cfra==0)
1179                         return 1;
1180                 /* allways start from scratch on the first frame */
1181                 if(cfra == cache->startframe) {
1182                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1183                         cache->flag &= ~PTCACHE_REDO_NEEDED;
1184                         add = 1;
1185                 }
1186                 else if (cache->mem_cache.last) {
1187                         pm2 = cache->mem_cache.last;
1188
1189                         if(pm2 && cfra > pm2->frame) {
1190                                 if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
1191                                         overwrite = 1;
1192                                 else
1193                                         add = 1;
1194                         }
1195                 }
1196                 else
1197                         add = 1;
1198
1199                 if(add || overwrite) {
1200                         if(overwrite)
1201                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame);
1202
1203                         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1204
1205                         pm->totpoint = pid->totwrite(pid->calldata);
1206                         pm->data_types = cfra ? pid->data_types : pid->info_types;
1207
1208                         ptcache_alloc_data(pm);
1209                         ptcache_mem_init_pointers(pm);
1210
1211                         for(i=0; i<totpoint; i++) {
1212                                 if(pid->write_elem(i, pid->calldata, pm->cur))
1213                                         ptcache_mem_incr_pointers(pm);
1214                         }
1215                         //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
1216
1217                         pm->frame = cfra;
1218                         BLI_addtail(&cache->mem_cache, pm);
1219                 }
1220         }
1221
1222         if(add || overwrite) {
1223                 if(cfra - cache->last_exact == 1
1224                         || cfra == cache->startframe) {
1225                         cache->last_exact = cfra;
1226                         cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1227                 }
1228                 else
1229                         cache->flag |= PTCACHE_FRAMES_SKIPPED;
1230         }
1231         
1232         if(pf)
1233                 ptcache_file_close(pf);
1234
1235         BKE_ptcache_update_info(pid);
1236
1237         return 1;
1238 }
1239 /* youll need to close yourself after!
1240  * mode - PTCACHE_CLEAR_ALL, 
1241
1242 */
1243 /* Clears & resets */
1244 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
1245 {
1246         int len; /* store the length of the string */
1247
1248         /* mode is same as fopen's modes */
1249         DIR *dir; 
1250         struct dirent *de;
1251         char path[MAX_PTCACHE_PATH];
1252         char filename[MAX_PTCACHE_FILE];
1253         char path_full[MAX_PTCACHE_FILE];
1254         char ext[MAX_PTCACHE_PATH];
1255
1256         if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
1257                 return;
1258
1259         /* don't allow clearing for linked objects */
1260         if(pid->ob->id.lib)
1261                 return;
1262
1263         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
1264         
1265         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
1266         switch (mode) {
1267         case PTCACHE_CLEAR_ALL:
1268         case PTCACHE_CLEAR_BEFORE:      
1269         case PTCACHE_CLEAR_AFTER:
1270                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1271                         ptcache_path(pid, path);
1272                         
1273                         len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
1274                         
1275                         dir = opendir(path);
1276                         if (dir==NULL)
1277                                 return;
1278
1279                         snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
1280                         
1281                         while ((de = readdir(dir)) != NULL) {
1282                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
1283                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
1284                                                 if (mode == PTCACHE_CLEAR_ALL) {
1285                                                         pid->cache->last_exact = 0;
1286                                                         BLI_join_dirfile(path_full, path, de->d_name);
1287                                                         BLI_delete(path_full, 0, 0);
1288                                                 } else {
1289                                                         /* read the number of the file */
1290                                                         int frame, len2 = strlen(de->d_name);
1291                                                         char num[7];
1292
1293                                                         if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
1294                                                                 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
1295                                                                 frame = atoi(num);
1296                                                                 
1297                                                                 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || 
1298                                                                 (mode==PTCACHE_CLEAR_AFTER && frame > cfra)     ) {
1299                                                                         
1300                                                                         BLI_join_dirfile(path_full, path, de->d_name);
1301                                                                         BLI_delete(path_full, 0, 0);
1302                                                                 }
1303                                                         }
1304                                                 }
1305                                         }
1306                                 }
1307                         }
1308                         closedir(dir);
1309                 }
1310                 else {
1311                         PTCacheMem *pm= pid->cache->mem_cache.first;
1312                         PTCacheMem *link= NULL;
1313
1314                         if(mode == PTCACHE_CLEAR_ALL) {
1315                                 pid->cache->last_exact = 0;
1316                                 for(; pm; pm=pm->next)
1317                                         ptcache_free_data(pm->data);
1318                                 BLI_freelistN(&pid->cache->mem_cache);
1319                         } else {
1320                                 while(pm) {
1321                                         if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra)     || 
1322                                         (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
1323                                                 link = pm;
1324                                                 pm = pm->next;
1325                                                 ptcache_free_data(link->data);
1326                                                 BLI_freelinkN(&pid->cache->mem_cache, link);
1327                                         }
1328                                         else
1329                                                 pm = pm->next;
1330                                 }
1331                         }
1332                 }
1333                 break;
1334                 
1335         case PTCACHE_CLEAR_FRAME:
1336                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1337                         if(BKE_ptcache_id_exist(pid, cfra)) {
1338                                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
1339                                 BLI_delete(filename, 0, 0);
1340                         }
1341                 }
1342                 else {
1343                         PTCacheMem *pm = pid->cache->mem_cache.first;
1344
1345                         for(; pm; pm=pm->next) {
1346                                 if(pm->frame == cfra) {
1347                                         ptcache_free_data(pm->data);
1348                                         BLI_freelinkN(&pid->cache->mem_cache, pm);
1349                                         break;
1350                                 }
1351                         }
1352                 }
1353                 break;
1354         }
1355
1356         BKE_ptcache_update_info(pid);
1357 }
1358
1359 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
1360 {
1361         if(!pid->cache)
1362                 return 0;
1363         
1364         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1365                 char filename[MAX_PTCACHE_FILE];
1366                 
1367                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
1368
1369                 return BLI_exists(filename);
1370         }
1371         else {
1372                 PTCacheMem *pm = pid->cache->mem_cache.first;
1373
1374                 for(; pm; pm=pm->next) {
1375                         if(pm->frame==cfra)
1376                                 return 1;
1377                 }
1378                 return 0;
1379         }
1380 }
1381
1382 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
1383 {
1384         Object *ob;
1385         PointCache *cache;
1386         float offset, time, nexttime;
1387
1388         /* TODO: this has to be sorter out once bsystem_time gets redone, */
1389         /*       now caches can handle interpolating etc. too - jahka */
1390
1391         /* time handling for point cache:
1392          * - simulation time is scaled by result of bsystem_time
1393          * - for offsetting time only time offset is taken into account, since
1394          *   that's always the same and can't be animated. a timeoffset which
1395          *   varies over time is not simpe to support.
1396          * - field and motion blur offsets are currently ignored, proper solution
1397          *   is probably to interpolate results from two frames for that ..
1398          */
1399
1400         ob= pid->ob;
1401         cache= pid->cache;
1402
1403         if(timescale) {
1404                 time= bsystem_time(scene, ob, cfra, 0.0f);
1405                 nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f);
1406
1407                 *timescale= MAX2(nexttime - time, 0.0f);
1408         }
1409
1410         if(startframe && endframe) {
1411                 *startframe= cache->startframe;
1412                 *endframe= cache->endframe;
1413
1414                 // XXX ipoflag is depreceated - old animation system stuff
1415                 if (/*(ob->ipoflag & OB_OFFS_PARENT) &&*/ (ob->partype & PARSLOW)==0) {
1416                         offset= give_timeoffset(ob);
1417
1418                         *startframe += (int)(offset+0.5f);
1419                         *endframe += (int)(offset+0.5f);
1420                 }
1421         }
1422 }
1423
1424 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
1425 {
1426         PointCache *cache;
1427         int reset, clear, after;
1428
1429         if(!pid->cache)
1430                 return 0;
1431
1432         cache= pid->cache;
1433         reset= 0;
1434         clear= 0;
1435         after= 0;
1436
1437         if(mode == PTCACHE_RESET_DEPSGRAPH) {
1438                 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
1439                         if(cache->flag & PTCACHE_QUICK_CACHE)
1440                                 clear= 1;
1441
1442                         after= 1;
1443                 }
1444
1445                 cache->flag |= PTCACHE_OUTDATED;
1446         }
1447         else if(mode == PTCACHE_RESET_BAKED) {
1448                 if(!BKE_ptcache_get_continue_physics()) {
1449                         reset= 1;
1450                         clear= 1;
1451                 }
1452                 else
1453                         cache->flag |= PTCACHE_OUTDATED;
1454         }
1455         else if(mode == PTCACHE_RESET_OUTDATED) {
1456                 reset = 1;
1457
1458                 if(cache->flag & PTCACHE_OUTDATED)
1459                         if(!(cache->flag & PTCACHE_BAKED))
1460                                 clear= 1;
1461         }
1462
1463         if(reset) {
1464                 cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
1465                 cache->simframe= 0;
1466                 cache->last_exact= 0;
1467
1468                 if(pid->type == PTCACHE_TYPE_CLOTH)
1469                         cloth_free_modifier(pid->ob, pid->calldata);
1470                 else if(pid->type == PTCACHE_TYPE_SOFTBODY)
1471                         sbFreeSimulation(pid->calldata);
1472                 else if(pid->type == PTCACHE_TYPE_PARTICLES)
1473                         psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
1474         }
1475         if(clear)
1476                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1477         else if(after)
1478                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
1479
1480         return (reset || clear || after);
1481 }
1482
1483 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
1484 {
1485         PTCacheID pid;
1486         ParticleSystem *psys;
1487         ModifierData *md;
1488         int reset, skip;
1489
1490         reset= 0;
1491         skip= 0;
1492
1493         if(ob->soft) {
1494                 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
1495                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1496         }
1497
1498         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1499                 /* Baked softbody hair has to be checked first, because we don't want to reset */
1500                 /* particles or softbody in that case -jahka */
1501                 if(psys->soft) {
1502                         BKE_ptcache_id_from_softbody(&pid, ob, psys->soft);
1503                         if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
1504                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1505                         else
1506                                 skip = 1;
1507                 }
1508                 else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
1509                         skip = 1;
1510
1511                 if(skip == 0) {
1512                         BKE_ptcache_id_from_particles(&pid, ob, psys);
1513                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1514                 }
1515         }
1516
1517         for(md=ob->modifiers.first; md; md=md->next) {
1518                 if(md->type == eModifierType_Cloth) {
1519                         BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
1520                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1521                 }
1522         }
1523
1524         return reset;
1525 }
1526
1527 /* Use this when quitting blender, with unsaved files */
1528 void BKE_ptcache_remove(void)
1529 {
1530         char path[MAX_PTCACHE_PATH];
1531         char path_full[MAX_PTCACHE_PATH];
1532         int rmdir = 1;
1533         
1534         ptcache_path(NULL, path);
1535
1536         if (BLI_exist(path)) {
1537                 /* The pointcache dir exists? - remove all pointcache */
1538
1539                 DIR *dir; 
1540                 struct dirent *de;
1541
1542                 dir = opendir(path);
1543                 if (dir==NULL)
1544                         return;
1545                 
1546                 while ((de = readdir(dir)) != NULL) {
1547                         if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
1548                                 /* do nothing */
1549                         } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
1550                                 BLI_join_dirfile(path_full, path, de->d_name);
1551                                 BLI_delete(path_full, 0, 0);
1552                         } else {
1553                                 rmdir = 0; /* unknown file, dont remove the dir */
1554                         }
1555                 }
1556
1557                 closedir(dir);
1558         } else { 
1559                 rmdir = 0; /* path dosnt exist  */
1560         }
1561         
1562         if (rmdir) {
1563                 BLI_delete(path, 1, 0);
1564         }
1565 }
1566
1567 /* Continuous Interaction */
1568
1569 static int CONTINUE_PHYSICS = 0;
1570
1571 void BKE_ptcache_set_continue_physics(Scene *scene, int enable)
1572 {
1573         Object *ob;
1574
1575         if(CONTINUE_PHYSICS != enable) {
1576                 CONTINUE_PHYSICS = enable;
1577
1578                 if(CONTINUE_PHYSICS == 0) {
1579                         for(ob=G.main->object.first; ob; ob=ob->id.next)
1580                                 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
1581                                         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
1582                 }
1583         }
1584 }
1585
1586 int BKE_ptcache_get_continue_physics()
1587 {
1588         return CONTINUE_PHYSICS;
1589 }
1590
1591 /* Point Cache handling */
1592
1593 PointCache *BKE_ptcache_add(ListBase *ptcaches)
1594 {
1595         PointCache *cache;
1596
1597         cache= MEM_callocN(sizeof(PointCache), "PointCache");
1598         cache->startframe= 1;
1599         cache->endframe= 250;
1600         cache->step= 10;
1601
1602         BLI_addtail(ptcaches, cache);
1603
1604         return cache;
1605 }
1606
1607 void BKE_ptache_free_mem(PointCache *cache)
1608 {
1609         PTCacheMem *pm = cache->mem_cache.first;
1610
1611         if(pm) {
1612                 for(; pm; pm=pm->next) {
1613                         ptcache_free_data(pm->data);
1614                         if(pm->index_array)
1615                                 MEM_freeN(pm->index_array);
1616                 }
1617
1618                 BLI_freelistN(&cache->mem_cache);
1619         }
1620 }
1621 void BKE_ptcache_free(PointCache *cache)
1622 {
1623         BKE_ptache_free_mem(cache);
1624         MEM_freeN(cache);
1625 }
1626 void BKE_ptcache_free_list(ListBase *ptcaches)
1627 {
1628         PointCache *cache = ptcaches->first;
1629
1630         for(; cache; cache=cache->next)
1631                 BKE_ptache_free_mem(cache);
1632
1633         BLI_freelistN(ptcaches);
1634 }
1635
1636 PointCache *BKE_ptcache_copy(PointCache *cache)
1637 {
1638         PointCache *ncache;
1639
1640         ncache= MEM_dupallocN(cache);
1641
1642         /* hmm, should these be copied over instead? */
1643         ncache->mem_cache.first = NULL;
1644         ncache->mem_cache.last = NULL;
1645
1646         ncache->flag= 0;
1647         ncache->simframe= 0;
1648
1649         return ncache;
1650 }
1651
1652
1653
1654 /* Baking */
1655 static int count_quick_cache(Scene *scene, int *quick_step)
1656 {
1657         Base *base = scene->base.first;
1658         PTCacheID *pid;
1659         ListBase pidlist;
1660         int autocache_count= 0;
1661
1662         for(base = scene->base.first; base; base = base->next) {
1663                 if(base->object) {
1664                         BKE_ptcache_ids_from_object(&pidlist, base->object);
1665
1666                         for(pid=pidlist.first; pid; pid=pid->next) {
1667                                 if((pid->cache->flag & PTCACHE_BAKED)
1668                                         || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
1669                                         continue;
1670
1671                                 if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
1672                                         if(!autocache_count)
1673                                                 *quick_step = pid->cache->step;
1674                                         else
1675                                                 *quick_step = MIN2(*quick_step, pid->cache->step);
1676
1677                                         autocache_count++;
1678                                 }
1679                         }
1680
1681                         BLI_freelistN(&pidlist);
1682                 }
1683         }
1684
1685         return autocache_count;
1686 }
1687 void BKE_ptcache_quick_cache_all(Scene *scene)
1688 {
1689         PTCacheBaker baker;
1690
1691         baker.bake=0;
1692         baker.break_data=NULL;
1693         baker.break_test=NULL;
1694         baker.pid=NULL;
1695         baker.progressbar=NULL;
1696         baker.progresscontext=NULL;
1697         baker.render=0;
1698         baker.anim_init = 0;
1699         baker.scene=scene;
1700
1701         if(count_quick_cache(scene, &baker.quick_step))
1702                 BKE_ptcache_make_cache(&baker);
1703 }
1704
1705 /* if bake is not given run simulations to current frame */
1706 void BKE_ptcache_make_cache(PTCacheBaker* baker)
1707 {
1708         Scene *scene = baker->scene;
1709         Base *base;
1710         ListBase pidlist;
1711         PTCacheID *pid = baker->pid;
1712         PointCache *cache;
1713         float frameleno = scene->r.framelen;
1714         int cfrao = CFRA;
1715         int startframe = MAXFRAME;
1716         int endframe = baker->anim_init ? scene->r.sfra : CFRA;
1717         int bake = baker->bake;
1718         int render = baker->render;
1719         int step = baker->quick_step;
1720
1721         G.afbreek = 0;
1722
1723         /* set caches to baking mode and figure out start frame */
1724         if(pid) {
1725                 /* cache/bake a single object */
1726                 cache = pid->cache;
1727                 if((cache->flag & PTCACHE_BAKED)==0) {
1728                         if(pid->type==PTCACHE_TYPE_PARTICLES)
1729                                 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
1730
1731                         if(bake || cache->flag & PTCACHE_REDO_NEEDED)
1732                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1733
1734                         startframe = MAX2(cache->last_exact, cache->startframe);
1735
1736                         if(bake) {
1737                                 endframe = cache->endframe;
1738                                 cache->flag |= PTCACHE_BAKING;
1739                         }
1740                         else {
1741                                 endframe = MIN2(endframe, cache->endframe);
1742                         }
1743
1744                         cache->flag &= ~PTCACHE_BAKED;
1745                 }
1746         }
1747         else for(base=scene->base.first; base; base= base->next) {
1748                 /* cache/bake everything in the scene */
1749                 BKE_ptcache_ids_from_object(&pidlist, base->object);
1750
1751                 for(pid=pidlist.first; pid; pid=pid->next) {
1752                         cache = pid->cache;
1753                         if((cache->flag & PTCACHE_BAKED)==0) {
1754                                 if(pid->type==PTCACHE_TYPE_PARTICLES) {
1755                                         ParticleSystem *psys = (ParticleSystem*)pid->calldata;
1756                                         /* skip hair & keyed particles */
1757                                         if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
1758                                                 continue;
1759
1760                                         psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
1761                                 }
1762
1763                                 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
1764                                         && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
1765                                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1766
1767                                 startframe = MIN2(startframe, cache->startframe);
1768
1769                                 if(bake || render) {
1770                                         cache->flag |= PTCACHE_BAKING;
1771
1772                                         if(bake)
1773                                                 endframe = MAX2(endframe, cache->endframe);
1774                                 }
1775
1776                                 cache->flag &= ~PTCACHE_BAKED;
1777
1778                         }
1779                 }
1780                 BLI_freelistN(&pidlist);
1781         }
1782
1783         CFRA= startframe;
1784         scene->r.framelen = 1.0;
1785
1786         for(; CFRA <= endframe; CFRA+=step) {
1787                 int prog;
1788
1789                 if(bake)
1790                         prog = (int)(100.0f * (float)(CFRA - startframe)/(float)(endframe-startframe));
1791                 else
1792                         prog = CFRA;
1793
1794                 /* NOTE: baking should not redraw whole ui as this slows things down */
1795                 if(baker->progressbar)
1796                         baker->progressbar(baker->progresscontext, prog);
1797                 
1798                 scene_update_for_newframe(scene, scene->lay);
1799
1800                 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
1801                 if(baker->break_test && baker->break_test(baker->break_data))
1802                         break;
1803         }
1804
1805         /* clear baking flag */
1806         if(pid) {
1807                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
1808                 cache->flag |= PTCACHE_SIMULATION_VALID;
1809                 if(bake) {
1810                         cache->flag |= PTCACHE_BAKED;
1811                         /* write info file */
1812                         if(cache->flag & PTCACHE_DISK_CACHE)
1813                                 BKE_ptcache_write_cache(pid, 0);
1814                 }
1815         }
1816         else for(base=scene->base.first; base; base= base->next) {
1817                 BKE_ptcache_ids_from_object(&pidlist, base->object);
1818
1819                 for(pid=pidlist.first; pid; pid=pid->next) {
1820                         /* skip hair particles */
1821                         if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
1822                                 continue;
1823                 
1824                         cache = pid->cache;
1825
1826                         if(step > 1)
1827                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
1828                         else
1829                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
1830
1831                         cache->flag |= PTCACHE_SIMULATION_VALID;
1832
1833                         if(bake) {
1834                                 cache->flag |= PTCACHE_BAKED;
1835                                 if(cache->flag & PTCACHE_DISK_CACHE)
1836                                         BKE_ptcache_write_cache(pid, 0);
1837                         }
1838                 }
1839                 BLI_freelistN(&pidlist);
1840         }
1841
1842         scene->r.framelen = frameleno;
1843         CFRA = cfrao;
1844
1845         if(bake) /* already on cfra unless baking */
1846                 scene_update_for_newframe(scene, scene->lay);
1847
1848         /* TODO: call redraw all windows somehow */
1849 }
1850 /* Helpers */
1851 void BKE_ptcache_disk_to_mem(PTCacheID *pid)
1852 {
1853         PointCache *cache = pid->cache;
1854         PTCacheFile *pf;
1855         PTCacheMem *pm;
1856
1857         int cfra, sfra = cache->startframe, efra = cache->endframe;
1858         int i;
1859
1860         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1861
1862         for(cfra=sfra; cfra <= efra; cfra++) {
1863                 pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1864
1865                 if(pf) {
1866                         if(!ptcache_file_read_header_begin(pf)) {
1867                                 printf("Can't yet convert old cache format\n");
1868                                 cache->flag |= PTCACHE_DISK_CACHE;
1869                                 ptcache_file_close(pf);
1870                                 return;
1871                         }
1872
1873                         if(pf->type != pid->type || !pid->read_header(pf)) {
1874                                 cache->flag |= PTCACHE_DISK_CACHE;
1875                                 ptcache_file_close(pf);
1876                                 return;
1877                         }
1878                         
1879                         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1880
1881                         pm->totpoint = pf->totpoint;
1882                         pm->data_types = pf->data_types;
1883                         pm->frame = cfra;
1884
1885                         ptcache_alloc_data(pm);
1886                         ptcache_mem_init_pointers(pm);
1887                         ptcache_file_init_pointers(pf);
1888
1889                         for(i=0; i<pm->totpoint; i++) {
1890                                 if(!ptcache_file_read_data(pf)) {
1891                                         printf("Error reading from disk cache\n");
1892                                         
1893                                         cache->flag |= PTCACHE_DISK_CACHE;
1894                                         
1895                                         ptcache_free_data(pm->data);
1896                                         MEM_freeN(pm);
1897                                         ptcache_file_close(pf);
1898
1899                                         return;
1900                                 }
1901                                 ptcache_copy_data(pf->cur, pm->cur);
1902                                 ptcache_mem_incr_pointers(pm);
1903                         }
1904
1905                         //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
1906
1907                         BLI_addtail(&pid->cache->mem_cache, pm);
1908
1909                         ptcache_file_close(pf);
1910                 }
1911         }
1912
1913 }
1914 void BKE_ptcache_mem_to_disk(PTCacheID *pid)
1915 {
1916         PointCache *cache = pid->cache;
1917         PTCacheFile *pf;
1918         PTCacheMem *pm;
1919         int i;
1920
1921         pm = cache->mem_cache.first;
1922
1923         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1924
1925         for(; pm; pm=pm->next) {
1926                 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
1927
1928                 if(pf) {
1929                         pf->data_types = pm->data_types;
1930                         pf->totpoint = pm->totpoint;
1931                         pf->type = pid->type;
1932
1933                         ptcache_mem_init_pointers(pm);
1934                         ptcache_file_init_pointers(pf);
1935
1936                         if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
1937                                 printf("Error writing to disk cache\n");
1938                                 cache->flag &= ~PTCACHE_DISK_CACHE;
1939
1940                                 ptcache_file_close(pf);
1941                                 return;
1942                         }
1943
1944                         for(i=0; i<pm->totpoint; i++) {
1945                                 ptcache_copy_data(pm->cur, pf->cur);
1946                                 if(!ptcache_file_write_data(pf)) {
1947                                         printf("Error writing to disk cache\n");
1948                                         cache->flag &= ~PTCACHE_DISK_CACHE;
1949
1950                                         ptcache_file_close(pf);
1951                                         return;
1952                                 }
1953                                 ptcache_mem_incr_pointers(pm);
1954                         }
1955
1956                         ptcache_file_close(pf);
1957
1958                         /* write info file */
1959                         if(cache->flag & PTCACHE_BAKED)
1960                                 BKE_ptcache_write_cache(pid, 0);
1961                 }
1962                 else
1963                         printf("Error creating disk cache file\n");
1964         }
1965 }
1966 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
1967 {
1968         PointCache *cache = pid->cache;
1969         int last_exact = cache->last_exact;
1970
1971         if (!G.relbase_valid){
1972                 cache->flag &= ~PTCACHE_DISK_CACHE;
1973                 printf("File must be saved before using disk cache!\n");
1974                 return;
1975         }
1976
1977         if(cache->flag & PTCACHE_DISK_CACHE)
1978                 BKE_ptcache_mem_to_disk(pid);
1979         else
1980                 BKE_ptcache_disk_to_mem(pid);
1981
1982         cache->flag ^= PTCACHE_DISK_CACHE;
1983         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1984         cache->flag ^= PTCACHE_DISK_CACHE;
1985         
1986         cache->last_exact = last_exact;
1987
1988         BKE_ptcache_update_info(pid);
1989 }
1990
1991 void BKE_ptcache_load_external(PTCacheID *pid)
1992 {
1993         /*todo*/
1994         PointCache *cache = pid->cache;
1995         int len; /* store the length of the string */
1996         int info = 0;
1997
1998         /* mode is same as fopen's modes */
1999         DIR *dir; 
2000         struct dirent *de;
2001         char path[MAX_PTCACHE_PATH];
2002         char filename[MAX_PTCACHE_FILE];
2003         char ext[MAX_PTCACHE_PATH];
2004
2005         if(!cache)
2006                 return;
2007
2008         cache->startframe = MAXFRAME;
2009         cache->endframe = -1;
2010         cache->totpoint = 0;
2011
2012         ptcache_path(pid, path);
2013         
2014         len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */
2015         
2016         dir = opendir(path);
2017         if (dir==NULL)
2018                 return;
2019
2020         if(cache->index >= 0)
2021                 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
2022         else
2023                 strcpy(ext, PTCACHE_EXT);
2024         
2025         while ((de = readdir(dir)) != NULL) {
2026                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2027                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2028                                 /* read the number of the file */
2029                                 int frame, len2 = strlen(de->d_name);
2030                                 char num[7];
2031
2032                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2033                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2034                                         frame = atoi(num);
2035
2036                                         if(frame) {
2037                                                 cache->startframe = MIN2(cache->startframe, frame);
2038                                                 cache->endframe = MAX2(cache->endframe, frame);
2039                                         }
2040                                         else
2041                                                 info = 1;
2042                                 }
2043                         }
2044                 }
2045         }
2046         closedir(dir);
2047
2048         if(cache->startframe != MAXFRAME) {
2049                 PTCacheFile *pf;
2050
2051                 /* read totpoint from info file (frame 0) */
2052                 if(info) {
2053                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
2054
2055                         if(pf) {
2056                                 if(ptcache_file_read_header_begin(pf)) {
2057                                         if(pf->type == pid->type && pid->read_header(pf)) {
2058                                                 cache->totpoint = pf->totpoint;
2059                                                 cache->flag |= PTCACHE_READ_INFO;
2060                                         }
2061                                         else {
2062                                                 cache->totpoint = 0;
2063                                         }
2064                                 }
2065                                 ptcache_file_close(pf);
2066                         }
2067                 }
2068                 /* or from any old format cache file */
2069                 else {
2070                         float old_data[14];
2071                         int elemsize = ptcache_pid_old_elemsize(pid);
2072                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
2073
2074                         if(pf) {
2075                                 while(ptcache_file_read(pf, old_data, 1, elemsize))
2076                                         cache->totpoint++;
2077                                 
2078                                 ptcache_file_close(pf);
2079                         }
2080                 }
2081         }
2082
2083         cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
2084
2085         BKE_ptcache_update_info(pid);
2086 }
2087
2088 void BKE_ptcache_update_info(PTCacheID *pid)
2089 {
2090         PointCache *cache = pid->cache;
2091         int totframes = 0;
2092         char mem_info[64];
2093
2094         if(cache->flag & PTCACHE_EXTERNAL) {
2095                 int cfra = cache->startframe;
2096
2097                 for(; cfra<=cache->endframe; cfra++) {
2098                         if(BKE_ptcache_id_exist(pid, cfra))
2099                                 totframes++;
2100                 }
2101
2102                 if(totframes && cache->totpoint)
2103                         sprintf(cache->info, "%i points found!", cache->totpoint);
2104                 else
2105                         sprintf(cache->info, "No valid data to read!");
2106                 return;
2107         }
2108
2109         if(cache->flag & PTCACHE_DISK_CACHE) {
2110                 int cfra = cache->startframe;
2111
2112                 for(; cfra<=cache->endframe; cfra++) {
2113                         if(BKE_ptcache_id_exist(pid, cfra))
2114                                 totframes++;
2115                 }
2116
2117                 sprintf(mem_info, "%i frames on disk", totframes);
2118         }
2119         else {
2120                 PTCacheMem *pm = cache->mem_cache.first;                
2121                 float framesize = 0.0f, bytes = 0.0f;
2122                 int mb;
2123
2124                 if(pm)
2125                         framesize = (float)ptcache_pid_old_elemsize(pid) * (float)pm->totpoint;
2126                 
2127                 for(; pm; pm=pm->next)
2128                         totframes++;
2129
2130                 bytes = totframes * framesize;
2131
2132                 mb = (bytes > 1024.0f * 1024.0f);
2133
2134                 sprintf(mem_info, "%i frames in memory (%.1f %s)",
2135                         totframes,
2136                         bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
2137                         mb ? "Mb" : "kb");
2138         }
2139
2140         if(cache->flag & PTCACHE_OUTDATED) {
2141                 sprintf(cache->info, "%s, cache is outdated!", mem_info);
2142         }
2143         else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
2144                 sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
2145         }
2146         else
2147                 sprintf(cache->info, "%s.", mem_info);
2148 }