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