svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r22130:22205
[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 /* Creating ID's */
81
82 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
83 {
84         ParticleSystemModifierData *psmd;
85         ModifierData *md;
86         int a;
87
88         memset(pid, 0, sizeof(PTCacheID));
89
90         pid->ob= ob;
91         pid->data= sb;
92         pid->type= PTCACHE_TYPE_SOFTBODY;
93         pid->cache= sb->pointcache;
94
95         if(sb->particles) {
96                 psmd= psys_get_modifier(ob, sb->particles);
97                 pid->stack_index= modifiers_indexInObject(ob, (ModifierData*)psmd);
98         }
99         else {
100                 for(a=0, md=ob->modifiers.first; md; md=md->next, a++) {
101                         if(md->type == eModifierType_Softbody) {
102                                 pid->stack_index = a;
103                                 break;
104                         }
105                 }
106         }
107 }
108
109 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
110 {
111         ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
112
113         memset(pid, 0, sizeof(PTCacheID));
114
115         pid->ob= ob;
116         pid->data= psys;
117         pid->type= PTCACHE_TYPE_PARTICLES;
118         pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)psmd);
119         pid->cache= psys->pointcache;
120 }
121
122 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
123 {
124         memset(pid, 0, sizeof(PTCacheID));
125
126         pid->ob= ob;
127         pid->data= clmd;
128         pid->type= PTCACHE_TYPE_CLOTH;
129         pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)clmd);
130         pid->cache= clmd->point_cache;
131 }
132
133 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
134 {
135         PTCacheID *pid;
136         ParticleSystem *psys;
137         ModifierData *md;
138
139         lb->first= lb->last= NULL;
140
141         if(ob->soft) {
142                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
143                 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
144                 BLI_addtail(lb, pid);
145         }
146
147         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
148                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
149                 BKE_ptcache_id_from_particles(pid, ob, psys);
150                 BLI_addtail(lb, pid);
151
152                 if(psys->soft) {
153                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
154                         BKE_ptcache_id_from_softbody(pid, ob, psys->soft);
155                         BLI_addtail(lb, pid);
156                 }
157         }
158
159         for(md=ob->modifiers.first; md; md=md->next) {
160                 if(md->type == eModifierType_Cloth) {
161                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
162                         BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
163                         BLI_addtail(lb, pid);
164                 }
165         }
166 }
167
168 /*      Takes an Object ID and returns a unique name
169         - id: object id
170         - cfra: frame for the cache, can be negative
171         - stack_index: index in the modifier stack. we can have cache for more then one stack_index
172 */
173
174 #define MAX_PTCACHE_PATH FILE_MAX
175 #define MAX_PTCACHE_FILE ((FILE_MAXDIR+FILE_MAXFILE)*2)
176
177 static int ptcache_path(PTCacheID *pid, char *filename)
178 {
179         Library *lib;
180         int i;
181
182         lib= (pid)? pid->ob->id.lib: NULL;
183
184         if(pid->cache->flag & PTCACHE_EXTERNAL) {
185                 strcpy(filename, pid->cache->path);
186                 return BLI_add_slash(filename); /* new strlen() */
187         }
188         else if (G.relbase_valid || lib) {
189                 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */
190                 char *blendfilename;
191
192                 blendfilename= (lib)? lib->filename: G.sce;
193
194                 BLI_split_dirfile_basic(blendfilename, NULL, file);
195                 i = strlen(file);
196                 
197                 /* remove .blend */
198                 if (i > 6)
199                         file[i-6] = '\0';
200                 
201                 snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
202                 BLI_convertstringcode(filename, blendfilename);
203                 return BLI_add_slash(filename); /* new strlen() */
204         }
205         
206         /* use the temp path. this is weak but better then not using point cache at all */
207         /* btempdir is assumed to exist and ALWAYS has a trailing slash */
208         snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", btempdir, abs(getpid()));
209         
210         return BLI_add_slash(filename); /* new strlen() */
211 }
212
213 static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
214 {
215         int len=0;
216         char *idname;
217         char *newname;
218         filename[0] = '\0';
219         newname = filename;
220         
221         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
222         
223         /* start with temp dir */
224         if (do_path) {
225                 len = ptcache_path(pid, filename);
226                 newname += len;
227         }
228         if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
229                 idname = (pid->ob->id.name+2);
230                 /* convert chars to hex so they are always a valid filename */
231                 while('\0' != *idname) {
232                         snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
233                         newname+=2;
234                         len += 2;
235                 }
236         }
237         else {
238                 int temp = strlen(pid->cache->name); 
239                 strcpy(newname, pid->cache->name); 
240                 newname+=temp;
241                 len += temp;
242         }
243
244         if (do_ext) {
245                 if(pid->cache->flag & PTCACHE_EXTERNAL) {
246                         if(pid->cache->index >= 0)
247                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
248                         else
249                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
250                 }
251                 else {
252                         snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
253                 }
254                 len += 16;
255         }
256         
257         return len; /* make sure the above string is always 16 chars */
258 }
259
260 /* youll need to close yourself after! */
261 PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra)
262 {
263         PTCacheFile *pf;
264         FILE *fp = NULL;
265         char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
266
267         /* don't allow writing for linked objects */
268         if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
269                 return NULL;
270
271         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
272         
273         BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
274
275         if (mode==PTCACHE_FILE_READ) {
276                 if (!BLI_exists(filename)) {
277                         return NULL;
278                 }
279                 fp = fopen(filename, "rb");
280         } else if (mode==PTCACHE_FILE_WRITE) {
281                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
282                 fp = fopen(filename, "wb");
283         }
284
285         if (!fp)
286                 return NULL;
287         
288         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
289         pf->fp= fp;
290         
291         return pf;
292 }
293
294 void BKE_ptcache_file_close(PTCacheFile *pf)
295 {
296         fclose(pf->fp);
297         MEM_freeN(pf);
298 }
299
300 int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot)
301 {
302         return (fread(f, sizeof(float), tot, pf->fp) == tot);
303 }
304
305 int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot)
306 {
307         return (fwrite(f, sizeof(float), tot, pf->fp) == tot);
308 }
309
310 static int ptcache_pid_elemsize(PTCacheID *pid)
311 {
312         if(pid->type==PTCACHE_TYPE_SOFTBODY)
313                 return 6 * sizeof(float);
314         else if(pid->type==PTCACHE_TYPE_PARTICLES)
315                 return sizeof(ParticleKey);
316         else if(pid->type==PTCACHE_TYPE_CLOTH)
317                 return 9 * sizeof(float);
318
319         return 0;
320 }
321 static int ptcache_pid_totelem(PTCacheID *pid)
322 {
323         if(pid->type==PTCACHE_TYPE_SOFTBODY) {
324                 SoftBody *soft = pid->data;
325                 return soft->totpoint;
326         }
327         else if(pid->type==PTCACHE_TYPE_PARTICLES) {
328                 ParticleSystem *psys = pid->data;
329                 return psys->totpart;
330         }
331         else if(pid->type==PTCACHE_TYPE_CLOTH) {
332                 ClothModifierData *clmd = pid->data;
333                 return clmd->clothObject->numverts;
334         }
335
336         return 0;
337 }
338
339 void BKE_ptcache_update_info(PTCacheID *pid)
340 {
341         PointCache *cache = pid->cache;
342         int totframes = 0;
343         char mem_info[64];
344
345         if(cache->flag & PTCACHE_EXTERNAL) {
346                 int cfra = cache->startframe;
347
348                 for(; cfra<=cache->endframe; cfra++) {
349                         if(BKE_ptcache_id_exist(pid, cfra))
350                                 totframes++;
351                 }
352
353                 if(totframes)
354                         sprintf(cache->info, "%i points read for %i frames", cache->totpoint, totframes);
355                 else
356                         sprintf(cache->info, "No valid data to read!");
357                 return;
358         }
359
360         if(cache->flag & PTCACHE_DISK_CACHE) {
361                 int cfra = cache->startframe;
362
363                 for(; cfra<=cache->endframe; cfra++) {
364                         if(BKE_ptcache_id_exist(pid, cfra))
365                                 totframes++;
366                 }
367
368                 sprintf(mem_info, "%i frames on disk", totframes);
369         }
370         else {
371                 PTCacheMem *pm = cache->mem_cache.first;                
372                 float framesize = 0.0f, bytes = 0.0f;
373                 int mb;
374
375                 if(pm)
376                         framesize = (float)ptcache_pid_elemsize(pid) * (float)pm->totpoint;
377                 
378                 for(; pm; pm=pm->next)
379                         totframes++;
380
381                 bytes = totframes * framesize;
382
383                 mb = (bytes > 1024.0f * 1024.0f);
384
385                 sprintf(mem_info, "%i frames in memory (%.1f %s)",
386                         totframes,
387                         bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
388                         mb ? "Mb" : "kb");
389         }
390
391         if(cache->flag & PTCACHE_OUTDATED) {
392                 sprintf(cache->info, "%s, cache is outdated!", mem_info);
393         }
394         else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
395                 sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
396         }
397         else
398                 sprintf(cache->info, "%s.", mem_info);
399 }
400 /* reads cache from disk or memory */
401 /* possible to get old or interpolated result */
402 int BKE_ptcache_read_cache(PTCacheReader *reader)
403 {
404         PTCacheID *pid = reader->pid;
405         PTCacheFile *pf=NULL, *pf2=NULL;
406         PTCacheMem *pm=NULL, *pm2=NULL;
407         int totelem = reader->totelem;
408         float cfra = reader->cfra;
409         int cfrai = (int)cfra;
410         int elemsize = ptcache_pid_elemsize(pid);
411         int i, incr = elemsize / sizeof(float);
412         float frs_sec = reader->scene->r.frs_sec;
413         int cfra1=0, cfra2;
414         int ret = 0;
415
416         if(totelem == 0)
417                 return 0;
418
419
420         /* first check if we have the actual frame cached */
421         if(cfra == (float)cfrai) {
422                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
423                         pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
424                 }
425                 else {
426                         pm = pid->cache->mem_cache.first;
427
428                         for(; pm; pm=pm->next) {
429                                 if(pm->frame == cfrai)
430                                         break;
431                         }
432                 }
433         }
434
435         /* if found, use exact frame */
436         if(pf || pm) {
437                 float *data;
438
439                 if(pm)
440                         data = pm->data;
441                 else
442                         data = MEM_callocN(elemsize, "pointcache read data");
443
444                 for(i=0; i<totelem; i++) {
445                         if(pf) {
446                                 if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
447                                         BKE_ptcache_file_close(pf);
448                                         MEM_freeN(data);
449                                         return 0;
450                                 }
451
452                                 reader->set_elem(i, reader->calldata, data);
453                         }
454                         else {
455                                 reader->set_elem(i, reader->calldata, data);
456                                 data += incr;
457                         }
458                 }
459
460                 if(pf) {
461                         BKE_ptcache_file_close(pf);
462                         pf = NULL;
463                         MEM_freeN(data);
464                 }
465
466                 ret = PTCACHE_READ_EXACT;
467         }
468
469         if(ret)
470                 ;
471         /* no exact cache frame found so try to find cached frames around cfra */
472         else if(pid->cache->flag & PTCACHE_DISK_CACHE) {
473                 pf=NULL;
474                 while(cfrai > pid->cache->startframe && !pf) {
475                         cfrai--;
476                         pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
477                         cfra1 = cfrai;
478                 }
479
480                 if(reader->old_frame)
481                         *(reader->old_frame) = cfrai;
482
483                 cfrai = (int)cfra;
484                 while(cfrai < pid->cache->endframe && !pf2) {
485                         cfrai++;
486                         pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
487                         cfra2 = cfrai;
488                 }
489         }
490         else if(pid->cache->mem_cache.first){
491                 pm = pid->cache->mem_cache.first;
492
493                 while(pm->next && pm->next->frame < cfra)
494                         pm= pm->next;
495
496                 if(pm) {
497                         if(reader->old_frame)
498                                 *(reader->old_frame) = pm->frame;
499                         cfra1 = pm->frame;
500                 }
501
502                 pm2 = pid->cache->mem_cache.last;
503
504                 if(pm2 && pm2->frame < cfra)
505                         pm2 = NULL;
506                 else {
507                         while(pm2->prev && pm2->prev->frame > cfra)
508                                 pm2= pm2->prev;
509
510                         if(pm2)
511                                 cfra2 = pm2->frame;
512                 }
513         }
514
515         if(ret)
516                 ;
517         else if((pf && pf2) || (pm && pm2)) {
518                 /* interpolate from nearest frames if cache isn't outdated */
519                 float *data1, *data2;
520
521                 if(pm) {
522                         data1 = pm->data;
523                         data2 = pm2->data;
524                 }
525                 else {
526                         data1 = MEM_callocN(elemsize, "pointcache read data1");
527                         data2 = MEM_callocN(elemsize, "pointcache read data2");
528                 }
529
530                 for(i=0; i<totelem; i++) {
531                         if(pf && pf2) {
532                                 if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
533                                         BKE_ptcache_file_close(pf);
534                                         BKE_ptcache_file_close(pf2);
535                                         MEM_freeN(data1);
536                                         MEM_freeN(data2);
537                                         return 0;
538                                 }
539                                 if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
540                                         BKE_ptcache_file_close(pf);
541                                         BKE_ptcache_file_close(pf2);
542                                         MEM_freeN(data1);
543                                         MEM_freeN(data2);
544                                         return 0;
545                                 }
546                                 reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
547                         }
548                         else {
549                                 reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
550                                 data1 += incr;
551                                 data2 += incr;
552                         }
553                 }
554
555                 if(pf) {
556                         BKE_ptcache_file_close(pf);
557                         pf = NULL;
558                         BKE_ptcache_file_close(pf2);
559                         pf2 = NULL;
560                         MEM_freeN(data1);
561                         MEM_freeN(data2);
562                 }
563
564                 ret = PTCACHE_READ_INTERPOLATED;
565         }
566         else if(pf || pm) {
567                 /* use last valid cache frame */
568                 float *data;
569
570                 /* don't read cache if allready simulated past cached frame */
571                 if(cfra1 && cfra1 <= pid->cache->simframe) {
572                         if(pf)
573                                 BKE_ptcache_file_close(pf);
574                         if(pf2)
575                                 BKE_ptcache_file_close(pf2);
576
577                         return 0;
578                 }
579
580                 if(pm)
581                         data = pm->data;
582                 else
583                         data = MEM_callocN(elemsize, "pointcache read data");
584
585                 for(i=0; i<totelem; i++) {
586                         if(pf) {
587                                 if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
588                                         BKE_ptcache_file_close(pf);
589                                         if(pf2)
590                                                 BKE_ptcache_file_close(pf2);
591                                         return 0;
592                                 }
593                                 reader->set_elem(i, reader->calldata, data);
594                         }
595                         else {
596                                 reader->set_elem(i, reader->calldata, data);
597                                 data += incr;
598                         }
599                 }
600
601                 if(pf) {
602                         BKE_ptcache_file_close(pf);
603                         pf = NULL;
604                         MEM_freeN(data);
605                 }
606                 if(pf2) {
607                         BKE_ptcache_file_close(pf2);
608                         pf = NULL;
609                 }
610
611                 ret = PTCACHE_READ_OLD;
612         }
613
614         if(pf)
615                 BKE_ptcache_file_close(pf);
616         if(pf2)
617                 BKE_ptcache_file_close(pf2);
618
619         if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
620                 /* clear invalid cache frames so that better stuff can be simulated */
621                 if(pid->cache->flag & PTCACHE_OUTDATED) {
622                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
623                 }
624                 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
625                         if(cfra <= pid->cache->last_exact)
626                                 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
627
628                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact));
629                 }
630         }
631
632         return ret;
633 }
634 /* writes cache to disk or memory */
635 int BKE_ptcache_write_cache(PTCacheWriter *writer)
636 {
637         PointCache *cache = writer->pid->cache;
638         PTCacheFile *pf= NULL;
639         int elemsize = ptcache_pid_elemsize(writer->pid);
640         int i, incr = elemsize / sizeof(float);
641         int add = 0, overwrite = 0;
642         float temp[14];
643
644         if(writer->totelem == 0 || writer->cfra <= 0)
645                 return 0;
646
647         if(cache->flag & PTCACHE_DISK_CACHE) {
648                 int cfra = cache->endframe;
649
650                 /* allways start from scratch on the first frame */
651                 if(writer->cfra == cache->startframe) {
652                         BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
653                         cache->flag &= ~PTCACHE_REDO_NEEDED;
654                         add = 1;
655                 }
656                 else {
657                         int ocfra;
658                         /* find last cached frame */
659                         while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
660                                 cfra--;
661
662                         /* find second last cached frame */
663                         ocfra = cfra-1;
664                         while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
665                                 ocfra--;
666
667                         if(cfra >= cache->startframe && writer->cfra > cfra) {
668                                 if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
669                                         overwrite = 1;
670                                 else
671                                         add = 1;
672                         }
673                 }
674
675                 if(add || overwrite) {
676                         if(overwrite)
677                                 BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, cfra);
678
679                         pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
680                         if(!pf)
681                                 return 0;
682
683                         for(i=0; i<writer->totelem; i++) {
684                                 writer->set_elem(i, writer->calldata, temp);
685                                 BKE_ptcache_file_write_floats(pf, temp, incr);
686                         }
687                 }
688         }
689         else {
690                 PTCacheMem *pm;
691                 PTCacheMem *pm2;
692                 float *pmdata;
693
694                 pm2 = cache->mem_cache.first;
695                 
696                 /* allways start from scratch on the first frame */
697                 if(writer->cfra == cache->startframe) {
698                         BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
699                         cache->flag &= ~PTCACHE_REDO_NEEDED;
700                         add = 1;
701                 }
702                 else {
703                         pm2 = cache->mem_cache.last;
704
705                         if(pm2 && writer->cfra > pm2->frame) {
706                                 if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
707                                         overwrite = 1;
708                                 else
709                                         add = 1;
710                         }
711                 }
712
713                 if(overwrite) {
714                         pm = cache->mem_cache.last;
715                         pmdata = pm->data;
716
717                         for(i=0; i<writer->totelem; i++, pmdata+=incr) {
718                                 writer->set_elem(i, writer->calldata, temp);
719                                 memcpy(pmdata, temp, elemsize);
720                         }
721
722                         pm->frame = writer->cfra;
723                 }
724                 else if(add) {
725                         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
726                         pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
727                         pmdata = pm->data;
728
729                         for(i=0; i<writer->totelem; i++, pmdata+=incr) {
730                                 writer->set_elem(i, writer->calldata, temp);
731                                 memcpy(pmdata, temp, elemsize);
732                         }
733
734                         pm->frame = writer->cfra;
735                         pm->totpoint = writer->totelem;
736
737                         BLI_addtail(&cache->mem_cache, pm);
738                 }
739         }
740
741         if(add || overwrite) {
742                 if(writer->cfra - cache->last_exact == 1
743                         || writer->cfra == cache->startframe) {
744                         cache->last_exact = writer->cfra;
745                         cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
746                 }
747                 else
748                         cache->flag |= PTCACHE_FRAMES_SKIPPED;
749         }
750         
751         if(pf)
752                 BKE_ptcache_file_close(pf);
753
754         BKE_ptcache_update_info(writer->pid);
755
756         return 1;
757 }
758 /* youll need to close yourself after!
759  * mode - PTCACHE_CLEAR_ALL, 
760
761 */
762
763 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
764 {
765         int len; /* store the length of the string */
766
767         /* mode is same as fopen's modes */
768         DIR *dir; 
769         struct dirent *de;
770         char path[MAX_PTCACHE_PATH];
771         char filename[MAX_PTCACHE_FILE];
772         char path_full[MAX_PTCACHE_FILE];
773         char ext[MAX_PTCACHE_PATH];
774
775         if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
776                 return;
777
778         /* don't allow clearing for linked objects */
779         if(pid->ob->id.lib)
780                 return;
781
782         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
783         
784         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
785         switch (mode) {
786         case PTCACHE_CLEAR_ALL:
787         case PTCACHE_CLEAR_BEFORE:      
788         case PTCACHE_CLEAR_AFTER:
789                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
790                         ptcache_path(pid, path);
791                         
792                         len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
793                         
794                         dir = opendir(path);
795                         if (dir==NULL)
796                                 return;
797
798                         snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
799                         
800                         while ((de = readdir(dir)) != NULL) {
801                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
802                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
803                                                 if (mode == PTCACHE_CLEAR_ALL) {
804                                                         pid->cache->last_exact = 0;
805                                                         BLI_join_dirfile(path_full, path, de->d_name);
806                                                         BLI_delete(path_full, 0, 0);
807                                                 } else {
808                                                         /* read the number of the file */
809                                                         int frame, len2 = strlen(de->d_name);
810                                                         char num[7];
811
812                                                         if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
813                                                                 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
814                                                                 frame = atoi(num);
815                                                                 
816                                                                 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || 
817                                                                 (mode==PTCACHE_CLEAR_AFTER && frame > cfra)     ) {
818                                                                         
819                                                                         BLI_join_dirfile(path_full, path, de->d_name);
820                                                                         BLI_delete(path_full, 0, 0);
821                                                                 }
822                                                         }
823                                                 }
824                                         }
825                                 }
826                         }
827                         closedir(dir);
828                 }
829                 else {
830                         PTCacheMem *pm= pid->cache->mem_cache.first;
831                         PTCacheMem *link= NULL;
832
833                         if(mode == PTCACHE_CLEAR_ALL) {
834                                 pid->cache->last_exact = 0;
835                                 for(; pm; pm=pm->next)
836                                         MEM_freeN(pm->data);
837                                 BLI_freelistN(&pid->cache->mem_cache);
838                         } else {
839                                 while(pm) {
840                                         if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra)     || 
841                                         (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
842                                                 link = pm;
843                                                 pm = pm->next;
844                                                 MEM_freeN(link->data);
845                                                 BLI_freelinkN(&pid->cache->mem_cache, link);
846                                         }
847                                         else
848                                                 pm = pm->next;
849                                 }
850                         }
851                 }
852                 break;
853                 
854         case PTCACHE_CLEAR_FRAME:
855                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
856                         if(BKE_ptcache_id_exist(pid, cfra)) {
857                                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
858                                 BLI_delete(filename, 0, 0);
859                         }
860                 }
861                 else {
862                         PTCacheMem *pm = pid->cache->mem_cache.first;
863
864                         for(; pm; pm=pm->next) {
865                                 if(pm->frame == cfra) {
866                                         MEM_freeN(pm->data);
867                                         BLI_freelinkN(&pid->cache->mem_cache, pm);
868                                         break;
869                                 }
870                         }
871                 }
872                 break;
873         }
874
875         BKE_ptcache_update_info(pid);
876 }
877
878 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
879 {
880         if(!pid->cache)
881                 return 0;
882         
883         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
884                 char filename[MAX_PTCACHE_FILE];
885                 
886                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
887
888                 return BLI_exists(filename);
889         }
890         else {
891                 PTCacheMem *pm = pid->cache->mem_cache.first;
892
893                 for(; pm; pm=pm->next) {
894                         if(pm->frame==cfra)
895                                 return 1;
896                 }
897                 return 0;
898         }
899 }
900
901 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
902 {
903         Object *ob;
904         PointCache *cache;
905         float offset, time, nexttime;
906
907         /* TODO: this has to be sorter out once bsystem_time gets redone, */
908         /*       now caches can handle interpolating etc. too - jahka */
909
910         /* time handling for point cache:
911          * - simulation time is scaled by result of bsystem_time
912          * - for offsetting time only time offset is taken into account, since
913          *   that's always the same and can't be animated. a timeoffset which
914          *   varies over time is not simpe to support.
915          * - field and motion blur offsets are currently ignored, proper solution
916          *   is probably to interpolate results from two frames for that ..
917          */
918
919         ob= pid->ob;
920         cache= pid->cache;
921
922         if(timescale) {
923                 time= bsystem_time(scene, ob, cfra, 0.0f);
924                 nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f);
925
926                 *timescale= MAX2(nexttime - time, 0.0f);
927         }
928
929         if(startframe && endframe) {
930                 *startframe= cache->startframe;
931                 *endframe= cache->endframe;
932
933                 // XXX ipoflag is depreceated - old animation system stuff
934                 if (/*(ob->ipoflag & OB_OFFS_PARENT) &&*/ (ob->partype & PARSLOW)==0) {
935                         offset= give_timeoffset(ob);
936
937                         *startframe += (int)(offset+0.5f);
938                         *endframe += (int)(offset+0.5f);
939                 }
940         }
941 }
942
943 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
944 {
945         PointCache *cache;
946         int reset, clear, after;
947
948         if(!pid->cache)
949                 return 0;
950
951         cache= pid->cache;
952         reset= 0;
953         clear= 0;
954         after= 0;
955
956         if(mode == PTCACHE_RESET_DEPSGRAPH) {
957                 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
958                         if(cache->flag & PTCACHE_QUICK_CACHE)
959                                 clear= 1;
960
961                         after= 1;
962                 }
963
964                 cache->flag |= PTCACHE_OUTDATED;
965         }
966         else if(mode == PTCACHE_RESET_BAKED) {
967                 if(!BKE_ptcache_get_continue_physics()) {
968                         reset= 1;
969                         clear= 1;
970                 }
971                 else
972                         cache->flag |= PTCACHE_OUTDATED;
973         }
974         else if(mode == PTCACHE_RESET_OUTDATED) {
975                 reset = 1;
976
977                 if(cache->flag & PTCACHE_OUTDATED)
978                         if(!(cache->flag & PTCACHE_BAKED))
979                                 clear= 1;
980         }
981
982         if(reset) {
983                 cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
984                 cache->simframe= 0;
985                 cache->last_exact= 0;
986
987                 if(pid->type == PTCACHE_TYPE_CLOTH)
988                         cloth_free_modifier(pid->ob, pid->data);
989                 else if(pid->type == PTCACHE_TYPE_SOFTBODY)
990                         sbFreeSimulation(pid->data);
991                 else if(pid->type == PTCACHE_TYPE_PARTICLES)
992                         psys_reset(pid->data, PSYS_RESET_DEPSGRAPH);
993         }
994         if(clear)
995                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
996         else if(after)
997                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
998
999         return (reset || clear || after);
1000 }
1001
1002 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
1003 {
1004         PTCacheID pid;
1005         ParticleSystem *psys;
1006         ModifierData *md;
1007         int reset, skip;
1008
1009         reset= 0;
1010         skip= 0;
1011
1012         if(ob->soft) {
1013                 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
1014                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1015         }
1016
1017         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1018                 /* Baked softbody hair has to be checked first, because we don't want to reset */
1019                 /* particles or softbody in that case -jahka */
1020                 if(psys->soft) {
1021                         BKE_ptcache_id_from_softbody(&pid, ob, psys->soft);
1022                         if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
1023                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1024                         else
1025                                 skip = 1;
1026                 }
1027                 else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
1028                         skip = 1;
1029
1030                 if(skip == 0) {
1031                         BKE_ptcache_id_from_particles(&pid, ob, psys);
1032                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1033                 }
1034         }
1035
1036         for(md=ob->modifiers.first; md; md=md->next) {
1037                 if(md->type == eModifierType_Cloth) {
1038                         BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
1039                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1040                 }
1041         }
1042
1043         return reset;
1044 }
1045
1046 /* Use this when quitting blender, with unsaved files */
1047 void BKE_ptcache_remove(void)
1048 {
1049         char path[MAX_PTCACHE_PATH];
1050         char path_full[MAX_PTCACHE_PATH];
1051         int rmdir = 1;
1052         
1053         ptcache_path(NULL, path);
1054
1055         if (BLI_exist(path)) {
1056                 /* The pointcache dir exists? - remove all pointcache */
1057
1058                 DIR *dir; 
1059                 struct dirent *de;
1060
1061                 dir = opendir(path);
1062                 if (dir==NULL)
1063                         return;
1064                 
1065                 while ((de = readdir(dir)) != NULL) {
1066                         if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
1067                                 /* do nothing */
1068                         } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
1069                                 BLI_join_dirfile(path_full, path, de->d_name);
1070                                 BLI_delete(path_full, 0, 0);
1071                         } else {
1072                                 rmdir = 0; /* unknown file, dont remove the dir */
1073                         }
1074                 }
1075
1076                 closedir(dir);
1077         } else { 
1078                 rmdir = 0; /* path dosnt exist  */
1079         }
1080         
1081         if (rmdir) {
1082                 BLI_delete(path, 1, 0);
1083         }
1084 }
1085
1086 /* Continuous Interaction */
1087
1088 static int CONTINUE_PHYSICS = 0;
1089
1090 void BKE_ptcache_set_continue_physics(Scene *scene, int enable)
1091 {
1092         Object *ob;
1093
1094         if(CONTINUE_PHYSICS != enable) {
1095                 CONTINUE_PHYSICS = enable;
1096
1097                 if(CONTINUE_PHYSICS == 0) {
1098                         for(ob=G.main->object.first; ob; ob=ob->id.next)
1099                                 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
1100                                         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
1101                 }
1102         }
1103 }
1104
1105 int BKE_ptcache_get_continue_physics()
1106 {
1107         return CONTINUE_PHYSICS;
1108 }
1109
1110 /* Point Cache */
1111
1112 PointCache *BKE_ptcache_add()
1113 {
1114         PointCache *cache;
1115
1116         cache= MEM_callocN(sizeof(PointCache), "PointCache");
1117         cache->startframe= 1;
1118         cache->endframe= 250;
1119         cache->step= 10;
1120
1121         return cache;
1122 }
1123
1124 void BKE_ptcache_free(PointCache *cache)
1125 {
1126         PTCacheMem *pm = cache->mem_cache.first;
1127         if(pm) {
1128                 for(; pm; pm=pm->next)
1129                         MEM_freeN(pm->data);
1130
1131                 BLI_freelistN(&cache->mem_cache);
1132         }
1133
1134         MEM_freeN(cache);
1135 }
1136
1137 PointCache *BKE_ptcache_copy(PointCache *cache)
1138 {
1139         PointCache *ncache;
1140
1141         ncache= MEM_dupallocN(cache);
1142
1143         /* hmm, should these be copied over instead? */
1144         ncache->mem_cache.first = NULL;
1145         ncache->mem_cache.last = NULL;
1146
1147         ncache->flag= 0;
1148         ncache->simframe= 0;
1149
1150         return ncache;
1151 }
1152
1153
1154
1155 /* Baking */
1156 static int count_quick_cache(Scene *scene, int *quick_step)
1157 {
1158         Base *base = scene->base.first;
1159         PTCacheID *pid;
1160         ListBase pidlist;
1161         int autocache_count= 0;
1162
1163         for(base = scene->base.first; base; base = base->next) {
1164                 if(base->object) {
1165                         BKE_ptcache_ids_from_object(&pidlist, base->object);
1166
1167                         for(pid=pidlist.first; pid; pid=pid->next) {
1168                                 if((pid->cache->flag & PTCACHE_BAKED)
1169                                         || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
1170                                         continue;
1171
1172                                 if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
1173                                         if(!autocache_count)
1174                                                 *quick_step = pid->cache->step;
1175                                         else
1176                                                 *quick_step = MIN2(*quick_step, pid->cache->step);
1177
1178                                         autocache_count++;
1179                                 }
1180                         }
1181
1182                         BLI_freelistN(&pidlist);
1183                 }
1184         }
1185
1186         return autocache_count;
1187 }
1188 void BKE_ptcache_quick_cache_all(Scene *scene)
1189 {
1190         PTCacheBaker baker;
1191
1192         baker.bake=0;
1193         baker.break_data=NULL;
1194         baker.break_test=NULL;
1195         baker.pid=NULL;
1196         baker.progressbar=NULL;
1197         baker.progresscontext=NULL;
1198         baker.render=0;
1199         baker.anim_init = 0;
1200         baker.scene=scene;
1201
1202         if(count_quick_cache(scene, &baker.quick_step))
1203                 BKE_ptcache_make_cache(&baker);
1204 }
1205
1206 /* if bake is not given run simulations to current frame */
1207 void BKE_ptcache_make_cache(PTCacheBaker* baker)
1208 {
1209         Scene *scene = baker->scene;
1210         Base *base;
1211         ListBase pidlist;
1212         PTCacheID *pid = baker->pid;
1213         PointCache *cache;
1214         float frameleno = scene->r.framelen;
1215         int cfrao = CFRA;
1216         int startframe = MAXFRAME;
1217         int endframe = baker->anim_init ? scene->r.sfra : CFRA;
1218         int bake = baker->bake;
1219         int render = baker->render;
1220         int step = baker->quick_step;
1221
1222         G.afbreek = 0;
1223
1224         /* set caches to baking mode and figure out start frame */
1225         if(pid) {
1226                 /* cache/bake a single object */
1227                 cache = pid->cache;
1228                 if((cache->flag & PTCACHE_BAKED)==0) {
1229                         if(pid->type==PTCACHE_TYPE_PARTICLES)
1230                                 psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
1231
1232                         if(bake || cache->flag & PTCACHE_REDO_NEEDED)
1233                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1234
1235                         startframe = MAX2(cache->last_exact, cache->startframe);
1236
1237                         if(bake) {
1238                                 endframe = cache->endframe;
1239                                 cache->flag |= PTCACHE_BAKING;
1240                         }
1241                         else {
1242                                 endframe = MIN2(endframe, cache->endframe);
1243                         }
1244
1245                         cache->flag &= ~PTCACHE_BAKED;
1246                 }
1247         }
1248         else for(base=scene->base.first; base; base= base->next) {
1249                 /* cache/bake everything in the scene */
1250                 BKE_ptcache_ids_from_object(&pidlist, base->object);
1251
1252                 for(pid=pidlist.first; pid; pid=pid->next) {
1253                         cache = pid->cache;
1254                         if((cache->flag & PTCACHE_BAKED)==0) {
1255                                 if(pid->type==PTCACHE_TYPE_PARTICLES) {
1256                                         ParticleSystem *psys = (ParticleSystem*)pid->data;
1257                                         /* skip hair & keyed particles */
1258                                         if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
1259                                                 continue;
1260
1261                                         psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
1262                                 }
1263
1264                                 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
1265                                         && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
1266                                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1267
1268                                 startframe = MIN2(startframe, cache->startframe);
1269
1270                                 if(bake || render) {
1271                                         cache->flag |= PTCACHE_BAKING;
1272
1273                                         if(bake)
1274                                                 endframe = MAX2(endframe, cache->endframe);
1275                                 }
1276
1277                                 cache->flag &= ~PTCACHE_BAKED;
1278
1279                         }
1280                 }
1281                 BLI_freelistN(&pidlist);
1282         }
1283
1284         CFRA= startframe;
1285         scene->r.framelen = 1.0;
1286
1287         for(; CFRA <= endframe; CFRA+=step) {
1288                 float prog;
1289
1290                 if(bake)
1291                         prog = (int)(100.0 * (float)(CFRA - startframe)/(float)(endframe-startframe));
1292                 else
1293                         prog = CFRA;
1294
1295                 /* NOTE: baking should not redraw whole ui as this slows things down */
1296                 if(baker->progressbar)
1297                         baker->progressbar(baker->progresscontext, prog);
1298                 
1299                 scene_update_for_newframe(scene, scene->lay);
1300
1301                 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
1302                 if(baker->break_test && baker->break_test(baker->break_data))
1303                         break;
1304         }
1305
1306         /* clear baking flag */
1307         if(pid) {
1308                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
1309                 cache->flag |= PTCACHE_SIMULATION_VALID;
1310                 if(bake)
1311                         cache->flag |= PTCACHE_BAKED;
1312         }
1313         else for(base=scene->base.first; base; base= base->next) {
1314                 BKE_ptcache_ids_from_object(&pidlist, base->object);
1315
1316                 for(pid=pidlist.first; pid; pid=pid->next) {
1317                         /* skip hair particles */
1318                         if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->data)->part->type == PART_HAIR)
1319                                 continue;
1320                 
1321                         cache = pid->cache;
1322
1323                         if(step > 1)
1324                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
1325                         else
1326                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
1327
1328                         cache->flag |= PTCACHE_SIMULATION_VALID;
1329
1330                         if(bake)
1331                                 cache->flag |= PTCACHE_BAKED;
1332                 }
1333                 BLI_freelistN(&pidlist);
1334         }
1335
1336         scene->r.framelen = frameleno;
1337         CFRA = cfrao;
1338
1339         if(bake) /* already on cfra unless baking */
1340                 scene_update_for_newframe(scene, scene->lay);
1341
1342         /* TODO: call redraw all windows somehow */
1343 }
1344
1345 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
1346         PointCache *cache = pid->cache;
1347         PTCacheFile *pf;
1348         PTCacheMem *pm;
1349         int totelem=0;
1350         int float_count=0;
1351         int tot;
1352         int last_exact = cache->last_exact;
1353
1354         if (!G.relbase_valid){
1355                 cache->flag &= ~PTCACHE_DISK_CACHE;
1356                 printf("File must be saved before using disk cache!\n");
1357                 return;
1358         }
1359
1360         totelem = ptcache_pid_totelem(pid);
1361         float_count = ptcache_pid_elemsize(pid) / sizeof(float);
1362
1363         if(totelem==0 || float_count==0)
1364                 return;
1365
1366         tot = totelem*float_count;
1367
1368         /* MEM -> DISK */
1369         if(cache->flag & PTCACHE_DISK_CACHE) {
1370                 pm = cache->mem_cache.first;
1371
1372                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1373
1374                 for(; pm; pm=pm->next) {
1375                         pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
1376
1377                         if(pf) {
1378                                 if(fwrite(pm->data, sizeof(float), tot, pf->fp) != tot) {
1379                                         printf("Error writing to disk cache\n");
1380                                         
1381                                         cache->flag &= ~PTCACHE_DISK_CACHE;
1382
1383                                         BKE_ptcache_file_close(pf);
1384                                         return;
1385                                 }
1386                                 BKE_ptcache_file_close(pf);
1387                         }
1388                         else
1389                                 printf("Error creating disk cache file\n");
1390                 }
1391
1392                 cache->flag &= ~PTCACHE_DISK_CACHE;
1393                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1394                 cache->flag |= PTCACHE_DISK_CACHE;
1395         }
1396         /* DISK -> MEM */
1397         else {
1398                 int cfra;
1399                 int sfra = cache->startframe;
1400                 int efra = cache->endframe;
1401
1402                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1403
1404                 for(cfra=sfra; cfra <= efra; cfra++) {
1405                         pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1406
1407                         if(pf) {
1408                                 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1409                                 pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache mem data");
1410
1411                                 if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) {
1412                                         printf("Error reading from disk cache\n");
1413
1414                                         cache->flag |= PTCACHE_DISK_CACHE;
1415
1416                                         MEM_freeN(pm->data);
1417                                         MEM_freeN(pm);
1418                                         BKE_ptcache_file_close(pf);
1419                                         return;
1420                                 }
1421
1422                                 pm->frame = cfra;
1423                                 pm->totpoint = totelem;
1424
1425                                 BLI_addtail(&pid->cache->mem_cache, pm);
1426
1427                                 BKE_ptcache_file_close(pf);
1428                         }
1429                 }
1430
1431                 cache->flag |= PTCACHE_DISK_CACHE;
1432                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1433                 cache->flag &= ~PTCACHE_DISK_CACHE;
1434         }
1435         
1436         cache->last_exact = last_exact;
1437
1438         BKE_ptcache_update_info(pid);
1439 }
1440
1441 void BKE_ptcache_load_external(PTCacheID *pid)
1442 {
1443         PointCache *cache = pid->cache;
1444         int len; /* store the length of the string */
1445
1446         /* mode is same as fopen's modes */
1447         DIR *dir; 
1448         struct dirent *de;
1449         char path[MAX_PTCACHE_PATH];
1450         char filename[MAX_PTCACHE_FILE];
1451         char path_full[MAX_PTCACHE_FILE];
1452         char ext[MAX_PTCACHE_PATH];
1453
1454         if(!cache)
1455                 return;
1456
1457         cache->startframe = MAXFRAME;
1458         cache->endframe = -1;
1459         cache->totpoint = 0;
1460
1461         ptcache_path(pid, path);
1462         
1463         len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */
1464         
1465         dir = opendir(path);
1466         if (dir==NULL)
1467                 return;
1468
1469         if(cache->index >= 0)
1470                 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
1471         else
1472                 strcpy(ext, PTCACHE_EXT);
1473         
1474         while ((de = readdir(dir)) != NULL) {
1475                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
1476                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
1477                                 /* read the number of the file */
1478                                 int frame, len2 = strlen(de->d_name);
1479                                 char num[7];
1480
1481                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
1482                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
1483                                         frame = atoi(num);
1484
1485                                         cache->startframe = MIN2(cache->startframe, frame);
1486                                         cache->endframe = MAX2(cache->endframe, frame);
1487                                 }
1488                         }
1489                 }
1490         }
1491         closedir(dir);
1492
1493         if(cache->startframe != MAXFRAME) {
1494                 PTCacheFile *pf;
1495                 int elemsize = ptcache_pid_elemsize(pid);
1496                 int     incr = elemsize / sizeof(float);
1497                 float *data = NULL;
1498                 pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
1499
1500                 if(pf) {
1501                         data = MEM_callocN(elemsize, "pointcache read data");
1502                         while(BKE_ptcache_file_read_floats(pf, data, incr))
1503                                 cache->totpoint++;
1504                         
1505                         BKE_ptcache_file_close(pf);
1506                         MEM_freeN(data);
1507                 }
1508         }
1509
1510         cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
1511
1512         BKE_ptcache_update_info(pid);
1513 }