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