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