Merge with trunk r39928
[blender-staging.git] / source / blender / blenkernel / intern / pointcache.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Campbell Barton <ideasman42@gmail.com>
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/pointcache.c
29  *  \ingroup bke
30  */
31
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_ID.h"
42 #include "DNA_cloth_types.h"
43 #include "DNA_dynamicpaint_types.h"
44 #include "DNA_modifier_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_object_force.h"
47 #include "DNA_particle_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_smoke_types.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_threads.h"
53 #include "BLI_math.h"
54 #include "BLI_utildefines.h"
55
56 #include "PIL_time.h"
57
58 #include "WM_api.h"
59
60 #include "BKE_anim.h"
61 #include "BKE_blender.h"
62 #include "BKE_cloth.h"
63 #include "BKE_depsgraph.h"
64 #include "BKE_dynamicpaint.h"
65 #include "BKE_global.h"
66 #include "BKE_library.h"
67 #include "BKE_main.h"
68 #include "BKE_object.h"
69 #include "BKE_particle.h"
70 #include "BKE_pointcache.h"
71 #include "BKE_scene.h"
72 #include "BKE_smoke.h"
73 #include "BKE_softbody.h"
74 #include "BKE_utildefines.h"
75
76 #include "BIK_api.h"
77
78 /* both in intern */
79 #include "smoke_API.h"
80
81 #ifdef WITH_LZO
82 #include "minilzo.h"
83 #else
84 /* used for non-lzo cases */
85 #define LZO_OUT_LEN(size)     ((size) + (size) / 16 + 64 + 3)
86 #endif
87
88 #ifdef WITH_LZMA
89 #include "LzmaLib.h"
90 #endif
91
92 /* needed for directory lookup */
93 /* untitled blend's need getpid for a unique name */
94 #ifndef WIN32
95   #include <dirent.h>
96 #include <unistd.h>
97 #else
98 #include <process.h>
99   #include "BLI_winstuff.h"
100 #endif
101
102 #define PTCACHE_DATA_FROM(data, type, from)             if(data[type]) { memcpy(data[type], from, ptcache_data_size[type]); }
103 #define PTCACHE_DATA_TO(data, type, index, to)  if(data[type]) { memcpy(to, (char*)data[type] + (index ? index * ptcache_data_size[type] : 0), ptcache_data_size[type]); }
104
105 /* could be made into a pointcache option */
106 #define DURIAN_POINTCACHE_LIB_OK 1
107
108 static int ptcache_data_size[] = {      
109                 sizeof(unsigned int), // BPHYS_DATA_INDEX
110                 3 * sizeof(float), // BPHYS_DATA_LOCATION
111                 3 * sizeof(float), // BPHYS_DATA_VELOCITY
112                 4 * sizeof(float), // BPHYS_DATA_ROTATION
113                 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST
114                 sizeof(float), // BPHYS_DATA_SIZE
115                 3 * sizeof(float), // BPHYS_DATA_TIMES
116                 sizeof(BoidData) // case BPHYS_DATA_BOIDS
117 };
118
119 static int ptcache_extra_datasize[] = {
120         0,
121         sizeof(ParticleSpring)
122 };
123
124 /* forward declerations */
125 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len);
126 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode);
127 static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
128 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
129
130 /* Common functions */
131 static int ptcache_basic_header_read(PTCacheFile *pf)
132 {
133         int error=0;
134
135         /* Custom functions should read these basic elements too! */
136         if(!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
137                 error = 1;
138         
139         if(!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
140                 error = 1;
141
142         return !error;
143 }
144 static int ptcache_basic_header_write(PTCacheFile *pf)
145 {
146         /* Custom functions should write these basic elements too! */
147         if(!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
148                 return 0;
149         
150         if(!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
151                 return 0;
152
153         return 1;
154 }
155 /* Softbody functions */
156 static int  ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
157 {
158         SoftBody *soft= soft_v;
159         BodyPoint *bp = soft->bpoint + index;
160
161         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos);
162         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec);
163
164         return 1;
165 }
166 static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data)
167 {
168         SoftBody *soft= soft_v;
169         BodyPoint *bp = soft->bpoint + index;
170
171         if(old_data) {
172                 memcpy(bp->pos, data, 3 * sizeof(float));
173                 memcpy(bp->vec, data + 3, 3 * sizeof(float));
174         }
175         else {
176                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos);
177                 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
178         }
179 }
180 static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
181 {
182         SoftBody *soft= soft_v;
183         BodyPoint *bp = soft->bpoint + index;
184         ParticleKey keys[4];
185         float dfra;
186
187         if(cfra1 == cfra2)
188                 return;
189
190         VECCOPY(keys[1].co, bp->pos);
191         VECCOPY(keys[1].vel, bp->vec);
192
193         if(old_data) {
194                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
195                 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
196         }
197         else
198                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
199
200         dfra = cfra2 - cfra1;
201
202         mul_v3_fl(keys[1].vel, dfra);
203         mul_v3_fl(keys[2].vel, dfra);
204
205         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
206
207         mul_v3_fl(keys->vel, 1.0f / dfra);
208
209         VECCOPY(bp->pos, keys->co);
210         VECCOPY(bp->vec, keys->vel);
211 }
212 static int  ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
213 {
214         SoftBody *soft= soft_v;
215         return soft->totpoint;
216 }
217 /* Particle functions */
218 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
219 {
220         PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
221         PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
222         
223         /* no rotation info, so make something nice up */
224         if(data[BPHYS_DATA_ROTATION]==NULL) {
225                 vec_to_quat( key->rot, key->vel, OB_NEGX, OB_POSZ);
226         }
227         else {
228                 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
229         }
230
231         PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
232         key->time = time;
233 }
234 static int  ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
235 {
236         ParticleSystem *psys= psys_v;
237         ParticleData *pa = psys->particles + index;
238         BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
239         float times[3];
240         int step = psys->pointcache->step;
241
242         /* No need to store unborn or died particles outside cache step bounds */
243         if(data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step))
244                 return 0;
245
246         times[0]= pa->time;
247         times[1]= pa->dietime;
248         times[2]= pa->lifetime;
249
250         PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
251         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
252         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
253         PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
254         PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
255         PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
256         PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
257
258         if(boid)
259                 PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
260
261         /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */
262         return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
263 }
264 static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data)
265 {
266         ParticleSystem *psys= psys_v;
267         ParticleData *pa;
268         BoidParticle *boid;
269         float timestep = 0.04f*psys->part->timetweak;
270
271         if(index >= psys->totpart)
272                 return;
273
274         pa = psys->particles + index;
275         boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
276
277         if(cfra > pa->state.time)
278                 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
279
280         if(old_data){
281                 /* old format cache */
282                 memcpy(&pa->state, old_data, sizeof(ParticleKey));
283                 return;
284         }
285
286         BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
287
288         /* set frames cached before birth to birth time */
289         if(cfra < pa->time)
290                 pa->state.time = pa->time;
291         else if(cfra > pa->dietime)
292                 pa->state.time = pa->dietime;
293
294         if(data[BPHYS_DATA_SIZE])
295                 PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
296         
297         if(data[BPHYS_DATA_TIMES]) {
298                 float times[3];
299                 PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, &times);
300                 pa->time = times[0];
301                 pa->dietime = times[1];
302                 pa->lifetime = times[2];
303         }
304
305         if(boid)
306                 PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
307
308         /* determine velocity from previous location */
309         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
310                 if(cfra > pa->prev_state.time) {
311                         sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
312                         mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep);
313                 }
314                 else {
315                         sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
316                         mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep);
317                 }
318         }
319
320         /* determine rotation from velocity */
321         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
322                 vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ);
323         }
324 }
325 static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
326 {
327         ParticleSystem *psys= psys_v;
328         ParticleData *pa;
329         ParticleKey keys[4];
330         float dfra, timestep = 0.04f*psys->part->timetweak;
331
332         if(index >= psys->totpart)
333                 return;
334
335         pa = psys->particles + index;
336
337         /* particle wasn't read from first cache so can't interpolate */
338         if((int)cfra1 < pa->time - psys->pointcache->step || (int)cfra1 > pa->dietime + psys->pointcache->step)
339                 return;
340
341         cfra = MIN2(cfra, pa->dietime);
342         cfra1 = MIN2(cfra1, pa->dietime);
343         cfra2 = MIN2(cfra2, pa->dietime);
344
345         if(cfra1 == cfra2)
346                 return;
347
348         memcpy(keys+1, &pa->state, sizeof(ParticleKey));
349         if(old_data)
350                 memcpy(keys+2, old_data, sizeof(ParticleKey));
351         else
352                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
353
354         /* determine velocity from previous location */
355         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
356                 if(keys[1].time > keys[2].time) {
357                         sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
358                         mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep);
359                 }
360                 else {
361                         sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
362                         mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep);
363                 }
364         }
365
366         /* determine rotation from velocity */
367         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
368                 vec_to_quat( keys[2].rot,keys[2].vel, OB_NEGX, OB_POSZ);
369         }
370
371         if(cfra > pa->time)
372                 cfra1 = MAX2(cfra1, pa->time);
373
374         dfra = cfra2 - cfra1;
375
376         mul_v3_fl(keys[1].vel, dfra * timestep);
377         mul_v3_fl(keys[2].vel, dfra * timestep);
378
379         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
380         interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
381
382         mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep));
383
384         pa->state.time = cfra;
385 }
386
387 static int  ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
388 {
389         ParticleSystem *psys = psys_v;
390         return psys->totpart;
391 }
392 static int  ptcache_particle_totwrite(void *psys_v, int cfra)
393 {
394         ParticleSystem *psys = psys_v;
395         ParticleData *pa= psys->particles;
396         int p, step = psys->pointcache->step;
397         int totwrite = 0;
398
399         if(cfra == 0)
400                 return psys->totpart;
401
402         for(p=0; p<psys->totpart; p++,pa++)
403                 totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step);
404
405         return totwrite;
406 }
407
408 static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
409 {
410         ParticleSystem *psys = psys_v;
411         PTCacheExtra *extra = NULL;
412
413         if(psys->part->phystype == PART_PHYS_FLUID &&
414                 psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS &&
415                 psys->tot_fluidsprings && psys->fluid_springs) {
416
417                 extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data");
418
419                 extra->type = BPHYS_EXTRA_FLUID_SPRINGS;
420                 extra->totdata = psys->tot_fluidsprings;
421
422                 extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data");
423                 memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]);
424
425                 BLI_addtail(&pm->extradata, extra);
426         }
427 }
428
429 static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
430 {
431         ParticleSystem *psys = psys_v;
432         PTCacheExtra *extra = pm->extradata.first;
433
434         for(; extra; extra=extra->next) {
435                 switch(extra->type) {
436                         case BPHYS_EXTRA_FLUID_SPRINGS:
437                         {
438                                 if(psys->fluid_springs)
439                                         MEM_freeN(psys->fluid_springs);
440
441                                 psys->fluid_springs = MEM_dupallocN(extra->data);
442                                 psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata;
443                                 break;
444                         }
445                 }
446         }
447 }
448
449 /* Cloth functions */
450 static int  ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
451 {
452         ClothModifierData *clmd= cloth_v;
453         Cloth *cloth= clmd->clothObject;
454         ClothVertex *vert = cloth->verts + index;
455
456         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x);
457         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v);
458         PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst);
459
460         return 1;
461 }
462 static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data)
463 {
464         ClothModifierData *clmd= cloth_v;
465         Cloth *cloth= clmd->clothObject;
466         ClothVertex *vert = cloth->verts + index;
467         
468         if(old_data) {
469                 memcpy(vert->x, data, 3 * sizeof(float));
470                 memcpy(vert->xconst, data + 3, 3 * sizeof(float));
471                 memcpy(vert->v, data + 6, 3 * sizeof(float));
472         }
473         else {
474                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x);
475                 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v);
476                 PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst);
477         }
478 }
479 static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
480 {
481         ClothModifierData *clmd= cloth_v;
482         Cloth *cloth= clmd->clothObject;
483         ClothVertex *vert = cloth->verts + index;
484         ParticleKey keys[4];
485         float dfra;
486
487         if(cfra1 == cfra2)
488                 return;
489
490         VECCOPY(keys[1].co, vert->x);
491         VECCOPY(keys[1].vel, vert->v);
492
493         if(old_data) {
494                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
495                 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
496         }
497         else
498                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
499
500         dfra = cfra2 - cfra1;
501
502         mul_v3_fl(keys[1].vel, dfra);
503         mul_v3_fl(keys[2].vel, dfra);
504
505         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
506
507         mul_v3_fl(keys->vel, 1.0f / dfra);
508
509         VECCOPY(vert->x, keys->co);
510         VECCOPY(vert->v, keys->vel);
511
512         /* should vert->xconst be interpolated somehow too? - jahka */
513 }
514
515 static int  ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
516 {
517         ClothModifierData *clmd= cloth_v;
518         return clmd->clothObject ? clmd->clothObject->numverts : 0;
519 }
520
521 #ifdef WITH_SMOKE
522 /* Smoke functions */
523 static int  ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
524 {
525         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
526         SmokeDomainSettings *sds = smd->domain;
527         
528         if(sds->fluid) {
529                 return sds->res[0]*sds->res[1]*sds->res[2];
530         }
531         else
532                 return 0;
533 }
534 static int  ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
535 {       
536         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
537         SmokeDomainSettings *sds = smd->domain;
538         int ret = 0;
539         
540         if(sds->fluid) {
541                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
542                 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
543                 unsigned char *obstacles;
544                 unsigned int in_len = sizeof(float)*(unsigned int)res;
545                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
546                 //int mode = res >= 1000000 ? 2 : 1;
547                 int mode=1;             // light
548                 if (sds->cache_comp == SM_CACHE_HEAVY) mode=2;  // heavy
549
550                 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
551
552                 ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
553                 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode);
554                 ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode); 
555                 ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode);
556                 ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode);
557                 ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode);
558                 ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode);
559                 ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode);
560                 ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode);
561                 ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode);
562                 ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode);
563                 ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
564                 ptcache_file_write(pf, &dt, 1, sizeof(float));
565                 ptcache_file_write(pf, &dx, 1, sizeof(float));
566
567                 MEM_freeN(out);
568                 
569                 ret = 1;
570         }
571
572         if(sds->wt) {
573                 int res_big_array[3];
574                 int res_big;
575                 int res = sds->res[0]*sds->res[1]*sds->res[2];
576                 float *dens, *densold, *tcu, *tcv, *tcw;
577                 unsigned int in_len = sizeof(float)*(unsigned int)res;
578                 unsigned int in_len_big;
579                 unsigned char *out;
580                 int mode;
581
582                 smoke_turbulence_get_res(sds->wt, res_big_array);
583                 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
584                 //mode =  res_big >= 1000000 ? 2 : 1;
585                 mode = 1;       // light
586                 if (sds->cache_high_comp == SM_CACHE_HEAVY) mode=2;     // heavy
587
588                 in_len_big = sizeof(float) * (unsigned int)res_big;
589
590                 smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
591
592                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
593                 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode);
594                 ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode);     
595                 MEM_freeN(out);
596
597                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
598                 ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode);
599                 ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode);
600                 ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode);
601                 MEM_freeN(out);
602                 
603                 ret = 1;
604         }
605
606         return ret;
607 }
608 static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
609 {
610         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
611         SmokeDomainSettings *sds = smd->domain;
612         
613         if(sds->fluid) {
614                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
615                 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
616                 unsigned char *obstacles;
617                 unsigned int out_len = (unsigned int)res * sizeof(float);
618                 
619                 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
620
621                 ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
622                 ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
623                 ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len);
624                 ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
625                 ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
626                 ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
627                 ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
628                 ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
629                 ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len);
630                 ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len);
631                 ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len);
632                 ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
633                 ptcache_file_read(pf, &dt, 1, sizeof(float));
634                 ptcache_file_read(pf, &dx, 1, sizeof(float));
635
636                 if(pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
637                         int res = sds->res[0]*sds->res[1]*sds->res[2];
638                         int res_big, res_big_array[3];
639                         float *dens, *densold, *tcu, *tcv, *tcw;
640                         unsigned int out_len = sizeof(float)*(unsigned int)res;
641                         unsigned int out_len_big;
642
643                         smoke_turbulence_get_res(sds->wt, res_big_array);
644                         res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
645                         out_len_big = sizeof(float) * (unsigned int)res_big;
646
647                         smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
648
649                         ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
650                         ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big);
651
652                         ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
653                         ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
654                         ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
655                 }
656         }
657
658         return 1;
659 }
660 #else // WITH_SMOKE
661 static int  ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; };
662 static void ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) {}
663 static int  ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
664 #endif // WITH_SMOKE
665
666 static int ptcache_dynamicpaint_totpoint(void *sd, int cfra)
667 {
668         DynamicPaintSurface *surface = (DynamicPaintSurface*)sd;
669
670         if (!surface->data) return 0;
671         else return surface->data->total_points;
672 }
673
674 #define DP_CACHE_VERSION "1.01"
675
676 static int  ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
677 {       
678         DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
679         int cache_compress = 1;
680
681         /* version header */
682         ptcache_file_write(pf, DP_CACHE_VERSION, 1, sizeof(char)*4);
683
684         if(surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
685                 unsigned int total_points=surface->data->total_points;
686                 unsigned int in_len;
687                 unsigned char *out;
688
689                 /* cache type */
690                 ptcache_file_write(pf, &surface->type, 1, sizeof(int));
691
692                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
693                         in_len = sizeof(PaintPoint)*total_points;
694                 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
695                                  surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
696                         in_len = sizeof(float)*total_points;
697                 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE)
698                         in_len = sizeof(PaintWavePoint)*total_points;
699                 else return 0;
700
701                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
702
703                 ptcache_file_compressed_write(pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress);
704                 MEM_freeN(out);
705
706         }
707         return 1;
708 }
709 static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
710 {
711         DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
712         char version[4];
713         
714         /* version header */
715         ptcache_file_read(pf, version, 1, sizeof(char)*4);
716         if (strncmp(version, DP_CACHE_VERSION,4)) {printf("Dynamic Paint: Invalid cache version: %s!\n",version); return 0;}
717
718         if(surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
719                 unsigned int data_len;
720                 int surface_type;
721
722                 /* cache type */
723                 ptcache_file_read(pf, &surface_type, 1, sizeof(int));
724
725                 if (surface_type != surface->type)
726                         return 0;
727
728                 /* read surface data */
729                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT)
730                         data_len = sizeof(PaintPoint);
731                 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
732                                  surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
733                         data_len = sizeof(float);
734                 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE)
735                         data_len = sizeof(PaintWavePoint);
736                 else return 0;
737
738                 ptcache_file_compressed_read(pf, (unsigned char*)surface->data->type_data, data_len*surface->data->total_points);
739
740         }
741         return 1;
742 }
743
744 /* Creating ID's */
745 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
746 {
747         memset(pid, 0, sizeof(PTCacheID));
748
749         pid->ob= ob;
750         pid->calldata= sb;
751         pid->type= PTCACHE_TYPE_SOFTBODY;
752         pid->cache= sb->pointcache;
753         pid->cache_ptr= &sb->pointcache;
754         pid->ptcaches= &sb->ptcaches;
755         pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
756
757         pid->write_point                        = ptcache_softbody_write;
758         pid->read_point                         = ptcache_softbody_read;
759         pid->interpolate_point          = ptcache_softbody_interpolate;
760
761         pid->write_stream                       = NULL;
762         pid->read_stream                        = NULL;
763
764         pid->write_extra_data           = NULL;
765         pid->read_extra_data            = NULL;
766         pid->interpolate_extra_data     = NULL;
767
768         pid->write_header                       = ptcache_basic_header_write;
769         pid->read_header                        = ptcache_basic_header_read;
770
771         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
772         pid->info_types= 0;
773
774         pid->stack_index = pid->cache->index;
775 }
776 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
777 {
778         memset(pid, 0, sizeof(PTCacheID));
779
780         pid->ob= ob;
781         pid->calldata= psys;
782         pid->type= PTCACHE_TYPE_PARTICLES;
783         pid->stack_index= psys->pointcache->index;
784         pid->cache= psys->pointcache;
785         pid->cache_ptr= &psys->pointcache;
786         pid->ptcaches= &psys->ptcaches;
787
788         if(psys->part->type != PART_HAIR)
789                 pid->flag |= PTCACHE_VEL_PER_SEC;
790
791         pid->totpoint                           = ptcache_particle_totpoint;
792         pid->totwrite                           = ptcache_particle_totwrite;
793
794         pid->write_point                                = ptcache_particle_write;
795         pid->read_point                         = ptcache_particle_read;
796         pid->interpolate_point          = ptcache_particle_interpolate;
797
798         pid->write_stream                       = NULL;
799         pid->read_stream                        = NULL;
800
801         pid->write_extra_data           = NULL;
802         pid->read_extra_data            = NULL;
803         pid->interpolate_extra_data     = NULL;
804
805         pid->write_header                       = ptcache_basic_header_write;
806         pid->read_header                        = ptcache_basic_header_read;
807
808         pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
809
810         if(psys->part->phystype == PART_PHYS_BOIDS)
811                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
812         else if(psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) {
813                 pid->write_extra_data = ptcache_particle_extra_write;
814                 pid->read_extra_data = ptcache_particle_extra_read;
815         }
816
817         if(psys->part->rotmode!=PART_ROT_VEL
818                 || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f)
819                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
820
821         if(psys->part->flag & PART_ROT_DYN)
822                 pid->data_types|= (1<<BPHYS_DATA_ROTATION);
823
824         pid->info_types= (1<<BPHYS_DATA_TIMES);
825 }
826 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
827 {
828         memset(pid, 0, sizeof(PTCacheID));
829
830         pid->ob= ob;
831         pid->calldata= clmd;
832         pid->type= PTCACHE_TYPE_CLOTH;
833         pid->stack_index= clmd->point_cache->index;
834         pid->cache= clmd->point_cache;
835         pid->cache_ptr= &clmd->point_cache;
836         pid->ptcaches= &clmd->ptcaches;
837         pid->totpoint= pid->totwrite= ptcache_cloth_totpoint;
838
839         pid->write_point                        = ptcache_cloth_write;
840         pid->read_point                         = ptcache_cloth_read;
841         pid->interpolate_point          = ptcache_cloth_interpolate;
842
843         pid->write_stream                       = NULL;
844         pid->read_stream                        = NULL;
845
846         pid->write_extra_data           = NULL;
847         pid->read_extra_data            = NULL;
848         pid->interpolate_extra_data     = NULL;
849
850         pid->write_header                       = ptcache_basic_header_write;
851         pid->read_header                        = ptcache_basic_header_read;
852
853         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
854         pid->info_types= 0;
855 }
856 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
857 {
858         SmokeDomainSettings *sds = smd->domain;
859
860         memset(pid, 0, sizeof(PTCacheID));
861
862         pid->ob= ob;
863         pid->calldata= smd;
864         
865         pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
866         pid->stack_index= sds->point_cache[0]->index;
867
868         pid->cache= sds->point_cache[0];
869         pid->cache_ptr= &(sds->point_cache[0]);
870         pid->ptcaches= &(sds->ptcaches[0]);
871
872         pid->totpoint= pid->totwrite= ptcache_smoke_totpoint;
873
874         pid->write_point                        = NULL;
875         pid->read_point                         = NULL;
876         pid->interpolate_point          = NULL;
877
878         pid->read_stream                        = ptcache_smoke_read;
879         pid->write_stream                       = ptcache_smoke_write;
880
881         pid->write_extra_data           = NULL;
882         pid->read_extra_data            = NULL;
883         pid->interpolate_extra_data     = NULL;
884
885         pid->write_header                       = ptcache_basic_header_write;
886         pid->read_header                        = ptcache_basic_header_read;
887
888         pid->data_types= 0;
889         pid->info_types= 0;
890
891         if(sds->fluid)
892                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW);
893         if(sds->wt)
894                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH);
895 }
896
897 void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
898 {
899
900         memset(pid, 0, sizeof(PTCacheID));
901
902         pid->ob= ob;
903         pid->calldata= surface;
904         pid->type= PTCACHE_TYPE_DYNAMICPAINT;
905         pid->cache= surface->pointcache;
906         pid->cache_ptr= &surface->pointcache;
907         pid->ptcaches= &surface->ptcaches;
908         pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint;
909
910         pid->write_point                        = NULL;
911         pid->read_point                         = NULL;
912         pid->interpolate_point          = NULL;
913
914         pid->write_stream                       = ptcache_dynamicpaint_write;
915         pid->read_stream                        = ptcache_dynamicpaint_read;
916
917         pid->write_extra_data           = NULL;
918         pid->read_extra_data            = NULL;
919         pid->interpolate_extra_data     = NULL;
920
921         pid->write_header                       = ptcache_basic_header_write;
922         pid->read_header                        = ptcache_basic_header_read;
923
924         pid->data_types= BPHYS_DATA_DYNAMICPAINT;
925         pid->info_types= 0;
926
927         pid->stack_index = pid->cache->index;
928 }
929
930 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
931 {
932         PTCacheID *pid;
933         ParticleSystem *psys;
934         ModifierData *md;
935
936         lb->first= lb->last= NULL;
937
938         if(ob->soft) {
939                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
940                 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
941                 BLI_addtail(lb, pid);
942         }
943
944         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
945                 if(psys->part==NULL)
946                         continue;
947                 
948                 /* check to make sure point cache is actually used by the particles */
949                 if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
950                         continue;
951
952                 /* hair needs to be included in id-list for cache edit mode to work */
953                 /* if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */
954                 /*      continue; */
955                         
956                 if(psys->part->type == PART_FLUID)
957                         continue;
958
959                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
960                 BKE_ptcache_id_from_particles(pid, ob, psys);
961                 BLI_addtail(lb, pid);
962         }
963
964         for(md=ob->modifiers.first; md; md=md->next) {
965                 if(md->type == eModifierType_Cloth) {
966                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
967                         BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
968                         BLI_addtail(lb, pid);
969                 }
970                 else if(md->type == eModifierType_Smoke) {
971                         SmokeModifierData *smd = (SmokeModifierData *)md;
972                         if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
973                         {
974                                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
975                                 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md);
976                                 BLI_addtail(lb, pid);
977                         }
978                 }
979                 else if(md->type == eModifierType_DynamicPaint) {
980                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
981                         if(pmd->canvas)
982                         {
983                                 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
984
985                                 for (; surface; surface=surface->next) {
986                                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
987                                         BKE_ptcache_id_from_dynamicpaint(pid, ob, surface);
988                                         BLI_addtail(lb, pid);
989                                 }
990                         }
991                 }
992         }
993
994         if(scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
995                 ListBase *lb_dupli_ob;
996
997                 if((lb_dupli_ob=object_duplilist(scene, ob))) {
998                         DupliObject *dob;
999                         for(dob= lb_dupli_ob->first; dob; dob= dob->next) {
1000                                 if(dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
1001                                         ListBase lb_dupli_pid;
1002                                         BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
1003                                         BLI_movelisttolist(lb, &lb_dupli_pid);
1004                                         if(lb_dupli_pid.first)
1005                                                 printf("Adding Dupli\n");
1006                                 }
1007                         }
1008
1009                         free_object_duplilist(lb_dupli_ob);     /* does restore */
1010                 }
1011         }
1012 }
1013
1014 /* File handling */
1015
1016 /*      Takes an Object ID and returns a unique name
1017         - id: object id
1018         - cfra: frame for the cache, can be negative
1019         - stack_index: index in the modifier stack. we can have cache for more then one stack_index
1020 */
1021
1022 #define MAX_PTCACHE_PATH FILE_MAX
1023 #define MAX_PTCACHE_FILE ((FILE_MAXDIR+FILE_MAXFILE)*2)
1024
1025 static int ptcache_path(PTCacheID *pid, char *filename)
1026 {
1027         Library *lib= (pid->ob)? pid->ob->id.lib: NULL;
1028         const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name;
1029         size_t i;
1030
1031         if(pid->cache->flag & PTCACHE_EXTERNAL) {
1032                 strcpy(filename, pid->cache->path);
1033
1034                 if(strncmp(filename, "//", 2)==0)
1035                         BLI_path_abs(filename, blendfilename);
1036
1037                 return BLI_add_slash(filename); /* new strlen() */
1038         }
1039         else if (G.relbase_valid || lib) {
1040                 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */
1041
1042                 BLI_split_dirfile(blendfilename, NULL, file);
1043                 i = strlen(file);
1044                 
1045                 /* remove .blend */
1046                 if (i > 6)
1047                         file[i-6] = '\0';
1048                 
1049                 BLI_snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
1050                 BLI_path_abs(filename, blendfilename);
1051                 return BLI_add_slash(filename); /* new strlen() */
1052         }
1053         
1054         /* use the temp path. this is weak but better then not using point cache at all */
1055         /* btempdir is assumed to exist and ALWAYS has a trailing slash */
1056         BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", btempdir, abs(getpid()));
1057         
1058         return BLI_add_slash(filename); /* new strlen() */
1059 }
1060
1061 static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
1062 {
1063         int len=0;
1064         char *idname;
1065         char *newname;
1066         filename[0] = '\0';
1067         newname = filename;
1068         
1069         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
1070         
1071         /* start with temp dir */
1072         if (do_path) {
1073                 len = ptcache_path(pid, filename);
1074                 newname += len;
1075         }
1076         if(pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
1077                 idname = (pid->ob->id.name+2);
1078                 /* convert chars to hex so they are always a valid filename */
1079                 while('\0' != *idname) {
1080                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
1081                         newname+=2;
1082                         len += 2;
1083                 }
1084         }
1085         else {
1086                 int temp = (int)strlen(pid->cache->name); 
1087                 strcpy(newname, pid->cache->name); 
1088                 newname+=temp;
1089                 len += temp;
1090         }
1091
1092         if (do_ext) {
1093
1094                 if(pid->cache->index < 0)
1095                         pid->cache->index =  pid->stack_index = object_insert_ptcache(pid->ob);
1096
1097                 if(pid->cache->flag & PTCACHE_EXTERNAL) {
1098                         if(pid->cache->index >= 0)
1099                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1100                         else
1101                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
1102                 }
1103                 else {
1104                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1105                 }
1106                 len += 16;
1107         }
1108         
1109         return len; /* make sure the above string is always 16 chars */
1110 }
1111
1112 /* youll need to close yourself after! */
1113 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
1114 {
1115         PTCacheFile *pf;
1116         FILE *fp = NULL;
1117         char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
1118
1119 #ifndef DURIAN_POINTCACHE_LIB_OK
1120         /* don't allow writing for linked objects */
1121         if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
1122                 return NULL;
1123 #endif
1124         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
1125         
1126         ptcache_filename(pid, filename, cfra, 1, 1);
1127
1128         if (mode==PTCACHE_FILE_READ) {
1129                 if (!BLI_exists(filename)) {
1130                         return NULL;
1131                 }
1132                  fp = fopen(filename, "rb");
1133         } else if (mode==PTCACHE_FILE_WRITE) {
1134                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
1135                 fp = fopen(filename, "wb");
1136         } else if (mode==PTCACHE_FILE_UPDATE) {
1137                 BLI_make_existing_file(filename);
1138                 fp = fopen(filename, "rb+");
1139         }
1140
1141         if (!fp)
1142                 return NULL;
1143
1144         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
1145         pf->fp= fp;
1146         pf->old_format = 0;
1147         pf->frame = cfra;
1148
1149         return pf;
1150 }
1151 static void ptcache_file_close(PTCacheFile *pf)
1152 {
1153         if(pf) {
1154                 fclose(pf->fp);
1155                 MEM_freeN(pf);
1156         }
1157 }
1158
1159 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
1160 {
1161         int r = 0;
1162         unsigned char compressed = 0;
1163         size_t in_len;
1164 #ifdef WITH_LZO
1165         size_t out_len = len;
1166 #endif
1167         unsigned char *in;
1168         unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
1169
1170         ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
1171         if(compressed) {
1172                 unsigned int size;
1173                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1174                 in_len = (size_t)size;
1175                 if(in_len==0) {
1176                         /* do nothing */
1177                 }
1178                 else {
1179                         in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
1180                         ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
1181 #ifdef WITH_LZO
1182                         if(compressed == 1)
1183                                 r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
1184 #endif
1185 #ifdef WITH_LZMA
1186                         if(compressed == 2)
1187                         {
1188                                 size_t sizeOfIt;
1189                                 size_t leni = in_len, leno = out_len;
1190                                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1191                                 sizeOfIt = (size_t)size;
1192                                 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
1193                                 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
1194                         }
1195 #endif
1196                         MEM_freeN(in);
1197                 }
1198         }
1199         else {
1200                 ptcache_file_read(pf, result, len, sizeof(unsigned char));
1201         }
1202
1203         MEM_freeN(props);
1204
1205         return r;
1206 }
1207 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
1208 {
1209         int r = 0;
1210         unsigned char compressed = 0;
1211         size_t out_len= 0;
1212         unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
1213         size_t sizeOfIt = 5;
1214
1215         (void)mode; /* unused when building w/o compression */
1216
1217 #ifdef WITH_LZO
1218         out_len= LZO_OUT_LEN(in_len);
1219         if(mode == 1) {
1220                 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
1221                 
1222                 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);  
1223                 if (!(r == LZO_E_OK) || (out_len >= in_len))
1224                         compressed = 0;
1225                 else
1226                         compressed = 1;
1227         }
1228 #endif
1229 #ifdef WITH_LZMA
1230         if(mode == 2) {
1231                 
1232                 r = LzmaCompress(out, &out_len, in, in_len,//assume sizeof(char)==1....
1233                                                 props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
1234
1235                 if(!(r == SZ_OK) || (out_len >= in_len))
1236                         compressed = 0;
1237                 else
1238                         compressed = 2;
1239         }
1240 #endif
1241         
1242         ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
1243         if(compressed) {
1244                 unsigned int size = out_len;
1245                 ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
1246                 ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
1247         }
1248         else
1249                 ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
1250
1251         if(compressed == 2)
1252         {
1253                 unsigned int size = sizeOfIt;
1254                 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
1255                 ptcache_file_write(pf, props, size, sizeof(unsigned char));
1256         }
1257
1258         MEM_freeN(props);
1259
1260         return r;
1261 }
1262 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
1263 {
1264         return (fread(f, size, tot, pf->fp) == tot);
1265 }
1266 static int ptcache_file_write(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
1267 {
1268         return (fwrite(f, size, tot, pf->fp) == tot);
1269 }
1270 static int ptcache_file_data_read(PTCacheFile *pf)
1271 {
1272         int i;
1273
1274         for(i=0; i<BPHYS_TOT_DATA; i++) {
1275                 if((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
1276                         return 0;
1277         }
1278         
1279         return 1;
1280 }
1281 static int ptcache_file_data_write(PTCacheFile *pf)
1282 {               
1283         int i;
1284
1285         for(i=0; i<BPHYS_TOT_DATA; i++) {
1286                 if((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
1287                         return 0;
1288         }
1289         
1290         return 1;
1291 }
1292 static int ptcache_file_header_begin_read(PTCacheFile *pf)
1293 {
1294         unsigned int typeflag=0;
1295         int error=0;
1296         char bphysics[8];
1297         
1298         pf->data_types = 0;
1299         
1300         if(fread(bphysics, sizeof(char), 8, pf->fp) != 8)
1301                 error = 1;
1302         
1303         if(!error && strncmp(bphysics, "BPHYSICS", 8))
1304                 error = 1;
1305
1306         if(!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp))
1307                 error = 1;
1308
1309         pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
1310         pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
1311         
1312         /* if there was an error set file as it was */
1313         if(error)
1314                 fseek(pf->fp, 0, SEEK_SET);
1315
1316         return !error;
1317 }
1318 static int ptcache_file_header_begin_write(PTCacheFile *pf)
1319 {
1320         const char *bphysics = "BPHYSICS";
1321         unsigned int typeflag = pf->type + pf->flag;
1322         
1323         if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
1324                 return 0;
1325
1326         if(!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp))
1327                 return 0;
1328         
1329         return 1;
1330 }
1331
1332 /* Data pointer handling */
1333 int BKE_ptcache_data_size(int data_type)
1334 {
1335         return ptcache_data_size[data_type];
1336 }
1337
1338 static void ptcache_file_pointers_init(PTCacheFile *pf)
1339 {
1340         int data_types = pf->data_types;
1341
1342         pf->cur[BPHYS_DATA_INDEX] =             (data_types & (1<<BPHYS_DATA_INDEX))    ?               &pf->data.index : NULL;
1343         pf->cur[BPHYS_DATA_LOCATION] =  (data_types & (1<<BPHYS_DATA_LOCATION)) ?               &pf->data.loc   : NULL;
1344         pf->cur[BPHYS_DATA_VELOCITY] =  (data_types & (1<<BPHYS_DATA_VELOCITY)) ?               &pf->data.vel   : NULL;
1345         pf->cur[BPHYS_DATA_ROTATION] =  (data_types & (1<<BPHYS_DATA_ROTATION)) ?               &pf->data.rot   : NULL;
1346         pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))?               &pf->data.ave   : NULL;
1347         pf->cur[BPHYS_DATA_SIZE] =              (data_types & (1<<BPHYS_DATA_SIZE))             ?               &pf->data.size  : NULL;
1348         pf->cur[BPHYS_DATA_TIMES] =             (data_types & (1<<BPHYS_DATA_TIMES))    ?               &pf->data.times : NULL;
1349         pf->cur[BPHYS_DATA_BOIDS] =             (data_types & (1<<BPHYS_DATA_BOIDS))    ?               &pf->data.boids : NULL;
1350 }
1351
1352 /* Check to see if point number "index" is in pm, uses binary search for index data. */
1353 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
1354 {
1355         if(pm->data[BPHYS_DATA_INDEX]) {
1356                 unsigned int *data = pm->data[BPHYS_DATA_INDEX];
1357                 unsigned int mid, low = 0, high = pm->totpoint - 1;
1358
1359                 if(index < *data || index > *(data+high))
1360                         return -1;
1361
1362                 /* check simple case for continuous indexes first */
1363                 if(index-*data < high && data[index-*data] == index)
1364                         return index-*data;
1365
1366                 while(low <= high) {
1367                         mid= (low + high)/2;
1368
1369                         if(data[mid] > index)
1370                                 high = mid - 1;
1371                         else if(data[mid] < index)
1372                                 low = mid + 1;
1373                         else
1374                                 return mid;
1375                 }
1376
1377                 return -1;
1378         }
1379         else {
1380                 return (index < pm->totpoint ? index : -1);
1381         }
1382 }
1383
1384 void BKE_ptcache_mem_pointers_init(PTCacheMem *pm)
1385 {
1386         int data_types = pm->data_types;
1387         int i;
1388
1389         for(i=0; i<BPHYS_TOT_DATA; i++)
1390                 pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL);
1391 }
1392
1393 void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
1394 {
1395         int i;
1396
1397         for(i=0; i<BPHYS_TOT_DATA; i++) {
1398                 if(pm->cur[i])
1399                         pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i];
1400         }
1401 }
1402 int  BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
1403 {
1404         int data_types = pm->data_types;
1405         int i, index = BKE_ptcache_mem_index_find(pm, point_index);
1406
1407         if(index < 0) {
1408                 /* Can't give proper location without reallocation, so don't give any location.
1409                  * Some points will be cached improperly, but this only happens with simulation
1410                  * steps bigger than cache->step, so the cache has to be recalculated anyways
1411                  * at some point.
1412                  */
1413                 return 0;
1414         }
1415
1416         for(i=0; i<BPHYS_TOT_DATA; i++)
1417                 pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL;
1418
1419         return 1;
1420 }
1421 static void ptcache_data_alloc(PTCacheMem *pm)
1422 {
1423         int data_types = pm->data_types;
1424         int totpoint = pm->totpoint;
1425         int i;
1426
1427         for(i=0; i<BPHYS_TOT_DATA; i++) {
1428                 if(data_types & (1<<i))
1429                         pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
1430         }
1431 }
1432 static void ptcache_data_free(PTCacheMem *pm)
1433 {
1434         void **data = pm->data;
1435         int i;
1436
1437         for(i=0; i<BPHYS_TOT_DATA; i++) {
1438                 if(data[i])
1439                         MEM_freeN(data[i]);
1440         }
1441 }
1442 static void ptcache_data_copy(void *from[], void *to[])
1443 {
1444         int i;
1445         for(i=0; i<BPHYS_TOT_DATA; i++) {
1446         /* note, durian file 03.4b_comp crashes if to[i] is not tested
1447          * its NULL, not sure if this should be fixed elsewhere but for now its needed */
1448                 if(from[i] && to[i])
1449                         memcpy(to[i], from[i], ptcache_data_size[i]);
1450         }
1451 }
1452
1453 static void ptcache_extra_free(PTCacheMem *pm)
1454 {
1455         PTCacheExtra *extra = pm->extradata.first;
1456
1457         if(extra) {
1458                 for(; extra; extra=extra->next) {
1459                         if(extra->data)
1460                                 MEM_freeN(extra->data);
1461                 }
1462
1463                 BLI_freelistN(&pm->extradata);
1464         }
1465 }
1466 static int ptcache_old_elemsize(PTCacheID *pid)
1467 {
1468         if(pid->type==PTCACHE_TYPE_SOFTBODY)
1469                 return 6 * sizeof(float);
1470         else if(pid->type==PTCACHE_TYPE_PARTICLES)
1471                 return sizeof(ParticleKey);
1472         else if(pid->type==PTCACHE_TYPE_CLOTH)
1473                 return 9 * sizeof(float);
1474
1475         return 0;
1476 }
1477
1478 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
1479 {
1480         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1481                 int cfra1=frame-1, cfra2=frame+1;
1482
1483                 while(cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1))
1484                         cfra1--;
1485
1486                 if(cfra1 < pid->cache->startframe)
1487                         cfra1 = 0;
1488
1489                 while(cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2))
1490                         cfra2++;
1491
1492                 if(cfra2 > pid->cache->endframe)
1493                         cfra2 = 0;
1494
1495                 if(cfra1 && !cfra2) {
1496                         *fra1 = 0;
1497                         *fra2 = cfra1;
1498                 }
1499                 else {
1500                         *fra1 = cfra1;
1501                         *fra2 = cfra2;
1502                 }
1503         }
1504         else if(pid->cache->mem_cache.first) {
1505                 PTCacheMem *pm = pid->cache->mem_cache.first;
1506                 PTCacheMem *pm2 = pid->cache->mem_cache.last;
1507
1508                 while(pm->next && pm->next->frame < frame)
1509                         pm= pm->next;
1510
1511                 if(pm2->frame < frame) {
1512                         pm2 = NULL;
1513                 }
1514                 else {
1515                         while(pm2->prev && pm2->prev->frame > frame) {
1516                                 pm2= pm2->prev;
1517                         }
1518                 }
1519
1520                 if(!pm2) {
1521                         *fra1 = 0;
1522                         *fra2 = pm->frame;
1523                 }
1524                 else {
1525                         *fra1 = pm->frame;
1526                         *fra2 = pm2->frame;
1527                 }
1528         }
1529 }
1530
1531 static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
1532 {
1533         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1534         PTCacheMem *pm = NULL;
1535         unsigned int i, error = 0;
1536
1537         if(pf == NULL)
1538                 return NULL;
1539
1540         if(!ptcache_file_header_begin_read(pf))
1541                 error = 1;
1542
1543         if(!error && (pf->type != pid->type || !pid->read_header(pf)))
1544                 error = 1;
1545
1546         if(!error) {
1547                 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1548
1549                 pm->totpoint = pf->totpoint;
1550                 pm->data_types = pf->data_types;
1551                 pm->frame = pf->frame;
1552
1553                 ptcache_data_alloc(pm);
1554
1555                 if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
1556                         for(i=0; i<BPHYS_TOT_DATA; i++) {
1557                                 unsigned int out_len = pm->totpoint*ptcache_data_size[i];
1558                                 if(pf->data_types & (1<<i))
1559                                         ptcache_file_compressed_read(pf, (unsigned char*)(pm->data[i]), out_len);
1560                         }
1561                 }
1562                 else {
1563                         BKE_ptcache_mem_pointers_init(pm);
1564                         ptcache_file_pointers_init(pf);
1565
1566                         for(i=0; i<pm->totpoint; i++) {
1567                                 if(!ptcache_file_data_read(pf)) {
1568                                         error = 1;
1569                                         break;
1570                                 }
1571                                 ptcache_data_copy(pf->cur, pm->cur);
1572                                 BKE_ptcache_mem_pointers_incr(pm);
1573                         }
1574                 }
1575         }
1576
1577         if(!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) {
1578                 unsigned int extratype = 0;
1579
1580                 while(ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) {
1581                         PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata");
1582
1583                         extra->type = extratype;
1584
1585                         ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int));
1586
1587                         extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data");
1588
1589                         if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS)
1590                                 ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]);
1591                         else
1592                                 ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
1593
1594                         BLI_addtail(&pm->extradata, extra);
1595                 }
1596         }
1597
1598         if(error && pm) {
1599                 ptcache_data_free(pm);
1600                 ptcache_extra_free(pm);
1601                 MEM_freeN(pm);
1602                 pm = NULL;
1603         }
1604
1605         ptcache_file_close(pf);
1606
1607         if (error && G.f & G_DEBUG) 
1608                 printf("Error reading from disk cache\n");
1609         
1610         return pm;
1611 }
1612 static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
1613 {
1614         PTCacheFile *pf = NULL;
1615         unsigned int i, error = 0;
1616         
1617         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame);
1618
1619         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
1620
1621         if(pf==NULL) {
1622                 if (G.f & G_DEBUG) 
1623                         printf("Error opening disk cache file for writing\n");
1624                 return 0;
1625         }
1626
1627         pf->data_types = pm->data_types;
1628         pf->totpoint = pm->totpoint;
1629         pf->type = pid->type;
1630         pf->flag = 0;
1631         
1632         if(pm->extradata.first)
1633                 pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
1634         
1635         if(pid->cache->compression)
1636                 pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
1637
1638         if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))
1639                 error = 1;
1640
1641         if(!error) {
1642                 if(pid->cache->compression) {
1643                         for(i=0; i<BPHYS_TOT_DATA; i++) {
1644                                 if(pm->data[i]) {
1645                                         unsigned int in_len = pm->totpoint*ptcache_data_size[i];
1646                                         unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
1647                                         ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression);
1648                                         MEM_freeN(out);
1649                                 }
1650                         }
1651                 }
1652                 else {
1653                         BKE_ptcache_mem_pointers_init(pm);
1654                         ptcache_file_pointers_init(pf);
1655
1656                         for(i=0; i<pm->totpoint; i++) {
1657                                 ptcache_data_copy(pm->cur, pf->cur);
1658                                 if(!ptcache_file_data_write(pf)) {
1659                                         error = 1;
1660                                         break;
1661                                 }
1662                                 BKE_ptcache_mem_pointers_incr(pm);
1663                         }
1664                 }
1665         }
1666
1667         if(!error && pm->extradata.first) {
1668                 PTCacheExtra *extra = pm->extradata.first;
1669
1670                 for(; extra; extra=extra->next) {
1671                         if(extra->data == NULL || extra->totdata == 0)
1672                                 continue;
1673
1674                         ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
1675                         ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
1676
1677                         if(pid->cache->compression) {
1678                                 unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
1679                                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
1680                                 ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression);
1681                                 MEM_freeN(out);
1682                         }
1683                         else {
1684                                 ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
1685                         }
1686                 }
1687         }
1688
1689         ptcache_file_close(pf);
1690         
1691         if (error && G.f & G_DEBUG) 
1692                 printf("Error writing to disk cache\n");
1693
1694         return error==0;
1695 }
1696
1697 static int ptcache_read_stream(PTCacheID *pid, int cfra)
1698 {
1699         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1700         int error = 0;
1701
1702         if(pid->read_stream == NULL)
1703                 return 0;
1704
1705         if(pf == NULL) {
1706                 if (G.f & G_DEBUG) 
1707                         printf("Error opening disk cache file for reading\n");
1708                 return 0;
1709         }
1710
1711         if(!ptcache_file_header_begin_read(pf))
1712                 error = 1;
1713
1714         if(!error && (pf->type != pid->type || !pid->read_header(pf)))
1715                 error = 1;
1716
1717         if(!error && pf->totpoint != pid->totpoint(pid->calldata, cfra))
1718                 error = 1;
1719
1720         if(!error) {
1721                 ptcache_file_pointers_init(pf);
1722
1723                 // we have stream reading here
1724                 if (!pid->read_stream(pf, pid->calldata))
1725                         error = 1;
1726         }
1727
1728         ptcache_file_close(pf);
1729         
1730         return error == 0;
1731 }
1732 static int ptcache_read(PTCacheID *pid, int cfra)
1733 {
1734         PTCacheMem *pm = NULL;
1735         int i;
1736         int *index = &i;
1737
1738         /* get a memory cache to read from */
1739         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1740                 pm = ptcache_disk_frame_to_mem(pid, cfra);
1741         }
1742         else {
1743                 pm = pid->cache->mem_cache.first;
1744                 
1745                 while(pm && pm->frame != cfra)
1746                         pm = pm->next;
1747         }
1748
1749         /* read the cache */
1750         if(pm) {
1751                 int totpoint = pm->totpoint;
1752
1753                 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
1754                         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra));
1755
1756                 BKE_ptcache_mem_pointers_init(pm);
1757
1758                 for(i=0; i<totpoint; i++) {
1759                         if(pm->data_types & (1<<BPHYS_DATA_INDEX))
1760                                 index = pm->cur[BPHYS_DATA_INDEX];
1761
1762                         pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL);
1763                 
1764                         BKE_ptcache_mem_pointers_incr(pm);
1765                 }
1766
1767                 if(pid->read_extra_data && pm->extradata.first)
1768                         pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
1769
1770                 /* clean up temporary memory cache */
1771                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1772                         ptcache_data_free(pm);
1773                         ptcache_extra_free(pm);
1774                         MEM_freeN(pm);
1775                 }
1776         }
1777
1778         return 1;
1779 }
1780 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
1781 {
1782         PTCacheMem *pm = NULL;
1783         int i;
1784         int *index = &i;
1785
1786         /* get a memory cache to read from */
1787         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1788                 pm = ptcache_disk_frame_to_mem(pid, cfra2);
1789         }
1790         else {
1791                 pm = pid->cache->mem_cache.first;
1792                 
1793                 while(pm && pm->frame != cfra2)
1794                         pm = pm->next;
1795         }
1796
1797         /* read the cache */
1798         if(pm) {
1799                 int totpoint = pm->totpoint;
1800
1801                 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
1802                         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra));
1803
1804                 BKE_ptcache_mem_pointers_init(pm);
1805
1806                 for(i=0; i<totpoint; i++) {
1807                         if(pm->data_types & (1<<BPHYS_DATA_INDEX))
1808                                 index = pm->cur[BPHYS_DATA_INDEX];
1809
1810                         pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL);
1811                         BKE_ptcache_mem_pointers_incr(pm);
1812                 }
1813
1814                 if(pid->interpolate_extra_data && pm->extradata.first)
1815                         pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
1816
1817                 /* clean up temporary memory cache */
1818                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1819                         ptcache_data_free(pm);
1820                         ptcache_extra_free(pm);
1821                         MEM_freeN(pm);
1822                 }
1823         }
1824
1825         return 1;
1826 }
1827 /* reads cache from disk or memory */
1828 /* possible to get old or interpolated result */
1829 int BKE_ptcache_read(PTCacheID *pid, float cfra)
1830 {
1831         int cfrai = (int)cfra, cfra1=0, cfra2=0;
1832         int ret = 0;
1833
1834         /* nothing to read to */
1835         if(pid->totpoint(pid->calldata, cfrai) == 0)
1836                 return 0;
1837
1838         if(pid->cache->flag & PTCACHE_READ_INFO) {
1839                 pid->cache->flag &= ~PTCACHE_READ_INFO;
1840                 ptcache_read(pid, 0);
1841         }
1842
1843         /* first check if we have the actual frame cached */
1844         if(cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai))
1845                 cfra1 = cfrai;
1846
1847         /* no exact cache frame found so try to find cached frames around cfra */
1848         if(cfra1 == 0)
1849                 ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
1850
1851         if(cfra1 == 0 && cfra2 == 0)
1852                 return 0;
1853
1854         /* don't read old cache if already simulated past cached frame */
1855         if(cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
1856                 return 0;
1857         if(cfra1 && cfra1 == cfra2)
1858                 return 0;
1859
1860         if(cfra1) {
1861                 
1862                 if(pid->read_stream) {
1863                         if (!ptcache_read_stream(pid, cfra1))
1864                                 return 0;
1865                 }
1866                 else if(pid->read_point)
1867                         ptcache_read(pid, cfra1);
1868         }
1869
1870         if(cfra2) {
1871                 
1872                 if(pid->read_stream) {
1873                         if (!ptcache_read_stream(pid, cfra2))
1874                                 return 0;
1875                 }
1876                 else if(pid->read_point) {
1877                         if(cfra1 && cfra2 && pid->interpolate_point)
1878                                 ptcache_interpolate(pid, cfra, cfra1, cfra2);
1879                         else
1880                                 ptcache_read(pid, cfra2);
1881                 }
1882         }
1883
1884         if(cfra1)
1885                 ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT);
1886         else if(cfra2) {
1887                 ret = PTCACHE_READ_OLD;
1888                 pid->cache->simframe = cfra2;
1889         }
1890
1891         if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
1892                 cfrai = (int)cfra;
1893                 /* clear invalid cache frames so that better stuff can be simulated */
1894                 if(pid->cache->flag & PTCACHE_OUTDATED) {
1895                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
1896                 }
1897                 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
1898                         if(cfra <= pid->cache->last_exact)
1899                                 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1900
1901                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact));
1902                 }
1903         }
1904
1905         return ret;
1906 }
1907 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
1908 {
1909         PTCacheFile *pf = NULL;
1910         int error = 0;
1911         
1912         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
1913
1914         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
1915
1916         if(pf==NULL) {
1917                 if (G.f & G_DEBUG) 
1918                         printf("Error opening disk cache file for writing\n");
1919                 return 0;
1920         }
1921
1922         pf->data_types = pid->data_types;
1923         pf->totpoint = totpoint;
1924         pf->type = pid->type;
1925         pf->flag = 0;
1926
1927         if(!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)))
1928                 error = 1;
1929
1930         if(!error && pid->write_stream)
1931                 pid->write_stream(pf, pid->calldata);
1932
1933         ptcache_file_close(pf);
1934
1935         if (error && G.f & G_DEBUG) 
1936                 printf("Error writing to disk cache\n");
1937
1938         return error == 0;
1939 }
1940 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
1941 {
1942         PointCache *cache = pid->cache;
1943         PTCacheMem *pm=NULL, *pm2=NULL;
1944         int totpoint = pid->totpoint(pid->calldata, cfra);
1945         int i, error = 0;
1946
1947         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1948
1949         pm->totpoint = pid->totwrite(pid->calldata, cfra);
1950         pm->data_types = cfra ? pid->data_types : pid->info_types;
1951
1952         ptcache_data_alloc(pm);
1953         BKE_ptcache_mem_pointers_init(pm);
1954
1955         if(overwrite) {
1956                 if(cache->flag & PTCACHE_DISK_CACHE) {
1957                         int fra = cfra-1;
1958
1959                         while(fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra))
1960                                 fra--;
1961                         
1962                         pm2 = ptcache_disk_frame_to_mem(pid, fra);
1963                 }
1964                 else
1965                         pm2 = cache->mem_cache.last;
1966         }
1967
1968         if(pid->write_point) {
1969                 for(i=0; i<totpoint; i++) {
1970                         int write = pid->write_point(i, pid->calldata, pm->cur, cfra);
1971                         if(write) {
1972                                 BKE_ptcache_mem_pointers_incr(pm);
1973
1974                                 /* newly born particles have to be copied to previous cached frame */
1975                                 if(overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2))
1976                                         pid->write_point(i, pid->calldata, pm2->cur, cfra);
1977                         }
1978                 }
1979         }
1980
1981         if(pid->write_extra_data)
1982                 pid->write_extra_data(pid->calldata, pm, cfra);
1983
1984         pm->frame = cfra;
1985
1986         if(cache->flag & PTCACHE_DISK_CACHE) {
1987                 error += !ptcache_mem_frame_to_disk(pid, pm);
1988
1989                 // if(pm) /* pm is always set */
1990                 {
1991                         ptcache_data_free(pm);
1992                         ptcache_extra_free(pm);
1993                         MEM_freeN(pm);
1994                 }
1995
1996                 if(pm2) {
1997                         error += !ptcache_mem_frame_to_disk(pid, pm2);
1998                         ptcache_data_free(pm2);
1999                         ptcache_extra_free(pm2);
2000                         MEM_freeN(pm2);
2001                 }
2002         }
2003         else {
2004                 BLI_addtail(&cache->mem_cache, pm);
2005         }
2006
2007         return error;
2008 }
2009 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
2010 {
2011         PointCache *cache = pid->cache;
2012         int ofra = 0, efra = cache->endframe;
2013
2014         /* allways start from scratch on the first frame */
2015         if(cfra && cfra == cache->startframe) {
2016                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
2017                 cache->flag &= ~PTCACHE_REDO_NEEDED;
2018                 return 1;
2019         }
2020
2021         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
2022                 if(cfra==0 && cache->startframe > 0)
2023                         return 1;
2024
2025                                 /* find last cached frame */
2026                 while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
2027                         efra--;
2028
2029                 /* find second last cached frame */
2030                 ofra = efra-1;
2031                 while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
2032                         ofra--;
2033         }
2034         else {
2035                 PTCacheMem *pm = cache->mem_cache.last;
2036                 /* don't write info file in memory */
2037                 if(cfra == 0)
2038                         return 0;
2039
2040                 if(pm == NULL)
2041                         return 1;
2042
2043                 efra = pm->frame;
2044                 ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
2045         }
2046
2047         if(efra >= cache->startframe && cfra > efra) {
2048                 if(ofra >= cache->startframe && efra - ofra < cache->step) {
2049                         /* overwrite previous frame */
2050                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
2051                         *overwrite = 1;
2052                 }
2053                 return 1;
2054         }
2055
2056         return 0;
2057 }
2058 /* writes cache to disk or memory */
2059 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
2060 {
2061         PointCache *cache = pid->cache;
2062         int totpoint = pid->totpoint(pid->calldata, cfra);
2063         int overwrite = 0, error = 0;
2064
2065         if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
2066                 return 0;
2067
2068         if(ptcache_write_needed(pid, cfra, &overwrite)==0)
2069                 return 0;
2070
2071         if(pid->write_stream) {
2072                 ptcache_write_stream(pid, cfra, totpoint);
2073         }
2074         else if(pid->write_point) {
2075                 error += ptcache_write(pid, cfra, overwrite);
2076         }
2077
2078         /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
2079         if(cfra - cache->last_exact == 1 || cfra == cache->startframe) {
2080                 cache->last_exact = cfra;
2081                 cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2082         }
2083         /* Don't mark skipped when writing info file (frame 0) */
2084         else if(cfra)
2085                 cache->flag |= PTCACHE_FRAMES_SKIPPED;
2086
2087         /* Update timeline cache display */
2088         if(cfra && cache->cached_frames)
2089                 cache->cached_frames[cfra-cache->startframe] = 1;
2090
2091         BKE_ptcache_update_info(pid);
2092
2093         return !error;
2094 }
2095 /* youll need to close yourself after!
2096  * mode - PTCACHE_CLEAR_ALL, 
2097
2098 */
2099 /* Clears & resets */
2100 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
2101 {
2102         unsigned int len; /* store the length of the string */
2103         unsigned int sta, end;
2104
2105         /* mode is same as fopen's modes */
2106         DIR *dir; 
2107         struct dirent *de;
2108         char path[MAX_PTCACHE_PATH];
2109         char filename[MAX_PTCACHE_FILE];
2110         char path_full[MAX_PTCACHE_FILE];
2111         char ext[MAX_PTCACHE_PATH];
2112
2113         if(!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED)
2114                 return;
2115
2116         if (pid->cache->flag & PTCACHE_IGNORE_CLEAR)
2117                 return;
2118
2119         sta = pid->cache->startframe;
2120         end = pid->cache->endframe;
2121
2122 #ifndef DURIAN_POINTCACHE_LIB_OK
2123         /* don't allow clearing for linked objects */
2124         if(pid->ob->id.lib)
2125                 return;
2126 #endif
2127
2128         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
2129         
2130         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
2131         switch (mode) {
2132         case PTCACHE_CLEAR_ALL:
2133         case PTCACHE_CLEAR_BEFORE:      
2134         case PTCACHE_CLEAR_AFTER:
2135                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
2136                         ptcache_path(pid, path);
2137                         
2138                         len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
2139                         
2140                         dir = opendir(path);
2141                         if (dir==NULL)
2142                                 return;
2143
2144                         BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
2145                         
2146                         while ((de = readdir(dir)) != NULL) {
2147                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2148                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2149                                                 if (mode == PTCACHE_CLEAR_ALL) {
2150                                                         pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2151                                                         BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2152                                                         BLI_delete(path_full, 0, 0);
2153                                                 } else {
2154                                                         /* read the number of the file */
2155                                                         unsigned int frame, len2 = (int)strlen(de->d_name);
2156                                                         char num[7];
2157
2158                                                         if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2159                                                                 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2160                                                                 frame = atoi(num);
2161                                                                 
2162                                                                 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || 
2163                                                                 (mode==PTCACHE_CLEAR_AFTER && frame > cfra)     ) {
2164                                                                         
2165                                                                         BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2166                                                                         BLI_delete(path_full, 0, 0);
2167                                                                         if(pid->cache->cached_frames && frame >=sta && frame <= end)
2168                                                                                 pid->cache->cached_frames[frame-sta] = 0;
2169                                                                 }
2170                                                         }
2171                                                 }
2172                                         }
2173                                 }
2174                         }
2175                         closedir(dir);
2176
2177                         if(mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames)
2178                                 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2179                 }
2180                 else {
2181                         PTCacheMem *pm= pid->cache->mem_cache.first;
2182                         PTCacheMem *link= NULL;
2183
2184                         if(mode == PTCACHE_CLEAR_ALL) {
2185                                 /*we want startframe if the cache starts before zero*/
2186                                 pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2187                                 for(; pm; pm=pm->next) {
2188                                         ptcache_data_free(pm);
2189                                         ptcache_extra_free(pm);
2190                                 }
2191                                 BLI_freelistN(&pid->cache->mem_cache);
2192
2193                                 if(pid->cache->cached_frames) 
2194                                         memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2195                         } else {
2196                                 while(pm) {
2197                                         if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra)     || 
2198                                         (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
2199                                                 link = pm;
2200                                                 if(pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end)
2201                                                         pid->cache->cached_frames[pm->frame-sta] = 0;
2202                                                 ptcache_data_free(pm);
2203                                                 ptcache_extra_free(pm);
2204                                                 pm = pm->next;
2205                                                 BLI_freelinkN(&pid->cache->mem_cache, link);
2206                                         }
2207                                         else
2208                                                 pm = pm->next;
2209                                 }
2210                         }
2211                 }
2212                 break;
2213                 
2214         case PTCACHE_CLEAR_FRAME:
2215                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
2216                         if(BKE_ptcache_id_exist(pid, cfra)) {
2217                                 ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
2218                                 BLI_delete(filename, 0, 0);
2219                         }
2220                 }
2221                 else {
2222                         PTCacheMem *pm = pid->cache->mem_cache.first;
2223
2224                         for(; pm; pm=pm->next) {
2225                                 if(pm->frame == cfra) {
2226                                         ptcache_data_free(pm);
2227                                         ptcache_extra_free(pm);
2228                                         BLI_freelinkN(&pid->cache->mem_cache, pm);
2229                                         break;
2230                                 }
2231                         }
2232                 }
2233                 if(pid->cache->cached_frames && cfra>=sta && cfra<=end)
2234                         pid->cache->cached_frames[cfra-sta] = 0;
2235                 break;
2236         }
2237
2238         BKE_ptcache_update_info(pid);
2239 }
2240 int  BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
2241 {
2242         if(!pid->cache)
2243                 return 0;
2244
2245         if(cfra<pid->cache->startframe || cfra > pid->cache->endframe)
2246                 return 0;
2247
2248         if(pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0)
2249                 return 0;
2250         
2251         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
2252                 char filename[MAX_PTCACHE_FILE];
2253                 
2254                 ptcache_filename(pid, filename, cfra, 1, 1);
2255
2256                 return BLI_exists(filename);
2257         }
2258         else {
2259                 PTCacheMem *pm = pid->cache->mem_cache.first;
2260
2261                 for(; pm; pm=pm->next) {
2262                         if(pm->frame==cfra)
2263                                 return 1;
2264                 }
2265                 return 0;
2266         }
2267 }
2268 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
2269 {
2270         Object *ob;
2271         PointCache *cache;
2272         /* float offset; unused for now */
2273         float time, nexttime;
2274
2275         /* TODO: this has to be sorter out once bsystem_time gets redone, */
2276         /*       now caches can handle interpolating etc. too - jahka */
2277
2278         /* time handling for point cache:
2279          * - simulation time is scaled by result of bsystem_time
2280          * - for offsetting time only time offset is taken into account, since
2281          *   that's always the same and can't be animated. a timeoffset which
2282          *   varies over time is not simpe to support.
2283          * - field and motion blur offsets are currently ignored, proper solution
2284          *   is probably to interpolate results from two frames for that ..
2285          */
2286
2287         ob= pid->ob;
2288         cache= pid->cache;
2289
2290         if(timescale) {
2291                 time= bsystem_time(scene, ob, cfra, 0.0f);
2292                 nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f);
2293
2294                 *timescale= MAX2(nexttime - time, 0.0f);
2295         }
2296
2297         if(startframe && endframe) {
2298                 *startframe= cache->startframe;
2299                 *endframe= cache->endframe;
2300
2301                 /* TODO: time handling with object offsets and simulated vs. cached
2302                  * particles isn't particularly easy, so for now what you see is what
2303                  * you get. In the future point cache could handle the whole particle
2304                  * system timing. */
2305 #if 0
2306                 if ((ob->partype & PARSLOW)==0) {
2307                         offset= give_timeoffset(ob);
2308
2309                         *startframe += (int)(offset+0.5f);
2310                         *endframe += (int)(offset+0.5f);
2311                 }
2312 #endif
2313         }
2314
2315         /* verify cached_frames array is up to date */
2316         if(cache->cached_frames) {
2317                 if(MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) {
2318                         MEM_freeN(cache->cached_frames);
2319                         cache->cached_frames = NULL;
2320                 }       
2321         }
2322
2323         if(cache->cached_frames==NULL && cache->endframe > cache->startframe) {
2324                 unsigned int sta=cache->startframe;
2325                 unsigned int end=cache->endframe;
2326
2327                 cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array");
2328
2329                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
2330                         /* mode is same as fopen's modes */
2331                         DIR *dir; 
2332                         struct dirent *de;
2333                         char path[MAX_PTCACHE_PATH];
2334                         char filename[MAX_PTCACHE_FILE];
2335                         char ext[MAX_PTCACHE_PATH];
2336                         unsigned int len; /* store the length of the string */
2337
2338                         ptcache_path(pid, path);
2339                         
2340                         len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */
2341                         
2342                         dir = opendir(path);
2343                         if (dir==NULL)
2344                                 return;
2345
2346                         BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
2347                         
2348                         while ((de = readdir(dir)) != NULL) {
2349                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2350                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2351                                                 /* read the number of the file */
2352                                                 unsigned int frame, len2 = (int)strlen(de->d_name);
2353                                                 char num[7];
2354
2355                                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2356                                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2357                                                         frame = atoi(num);
2358                                                         
2359                                                         if(frame >= sta && frame <= end)
2360                                                                 cache->cached_frames[frame-sta] = 1;
2361                                                 }
2362                                         }
2363                                 }
2364                         }
2365                         closedir(dir);
2366                 }
2367                 else {
2368                         PTCacheMem *pm= pid->cache->mem_cache.first;
2369
2370                         while(pm) {
2371                                 if(pm->frame >= sta && pm->frame <= end)
2372                                         cache->cached_frames[pm->frame-sta] = 1;
2373                                 pm = pm->next;
2374                         }
2375                 }
2376         }
2377 }
2378 int  BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
2379 {
2380         PointCache *cache;
2381         int reset, clear, after;
2382
2383         if(!pid->cache)
2384                 return 0;
2385
2386         cache= pid->cache;
2387         reset= 0;
2388         clear= 0;
2389         after= 0;
2390
2391         if(mode == PTCACHE_RESET_DEPSGRAPH) {
2392                 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
2393                         if(cache->flag & PTCACHE_QUICK_CACHE)
2394                                 clear= 1;
2395
2396                         after= 1;
2397                 }
2398
2399                 cache->flag |= PTCACHE_OUTDATED;
2400         }
2401         else if(mode == PTCACHE_RESET_BAKED) {
2402                 if(!BKE_ptcache_get_continue_physics()) {
2403                         reset= 1;
2404                         clear= 1;
2405                 }
2406                 else
2407                         cache->flag |= PTCACHE_OUTDATED;
2408         }
2409         else if(mode == PTCACHE_RESET_OUTDATED) {
2410                 reset = 1;
2411
2412                 if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
2413                         clear= 1;
2414                         cache->flag &= ~PTCACHE_OUTDATED;
2415                 }
2416         }
2417
2418         if(reset) {
2419                 BKE_ptcache_invalidate(cache);
2420                 cache->flag &= ~PTCACHE_REDO_NEEDED;
2421
2422                 if(pid->type == PTCACHE_TYPE_CLOTH)
2423                         cloth_free_modifier(pid->calldata);
2424                 else if(pid->type == PTCACHE_TYPE_SOFTBODY)
2425                         sbFreeSimulation(pid->calldata);
2426                 else if(pid->type == PTCACHE_TYPE_PARTICLES)
2427                         psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
2428                 else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
2429                         smokeModifier_reset(pid->calldata);
2430                 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
2431                         smokeModifier_reset_turbulence(pid->calldata);
2432                 else if(pid->type == PTCACHE_TYPE_DYNAMICPAINT)
2433                         dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata);
2434         }
2435         if(clear)
2436                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2437         else if(after)
2438                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
2439
2440         return (reset || clear || after);
2441 }
2442 int  BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
2443 {
2444         PTCacheID pid;
2445         ParticleSystem *psys;
2446         ModifierData *md;
2447         int reset, skip;
2448
2449         reset= 0;
2450         skip= 0;
2451
2452         if(ob->soft) {
2453                 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
2454                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2455         }
2456
2457         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
2458                 /* children or just redo can be calculated without reseting anything */
2459                 if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
2460                         skip = 1;
2461                 /* Baked cloth hair has to be checked too, because we don't want to reset */
2462                 /* particles or cloth in that case -jahka */
2463                 else if(psys->clmd) {
2464                         BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
2465                         if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
2466                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2467                         else
2468                                 skip = 1;
2469                 }
2470
2471                 if(skip == 0 && psys->part) {
2472                         BKE_ptcache_id_from_particles(&pid, ob, psys);
2473                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2474                 }
2475         }
2476
2477         for(md=ob->modifiers.first; md; md=md->next) {
2478                 if(md->type == eModifierType_Cloth) {
2479                         BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
2480                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2481                 }
2482                 if(md->type == eModifierType_Smoke) {
2483                         SmokeModifierData *smd = (SmokeModifierData *)md;
2484                         if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
2485                         {
2486                                 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md);
2487                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2488                         }
2489                 }
2490                 if(md->type == eModifierType_DynamicPaint) {
2491                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
2492                         if(pmd->canvas)
2493                         {
2494                                 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
2495
2496                                 for (; surface; surface=surface->next) {
2497                                         BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
2498                                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2499                                 }
2500                         }
2501                 }
2502         }
2503
2504         if (ob->type == OB_ARMATURE)
2505                 BIK_clear_cache(ob->pose);
2506
2507         return reset;
2508 }
2509
2510 /* Use this when quitting blender, with unsaved files */
2511 void BKE_ptcache_remove(void)
2512 {
2513         char path[MAX_PTCACHE_PATH];
2514         char path_full[MAX_PTCACHE_PATH];
2515         int rmdir = 1;
2516         
2517         ptcache_path(NULL, path);
2518
2519         if (BLI_exist(path)) {
2520                 /* The pointcache dir exists? - remove all pointcache */
2521
2522                 DIR *dir; 
2523                 struct dirent *de;
2524
2525                 dir = opendir(path);
2526                 if (dir==NULL)
2527                         return;
2528                 
2529                 while ((de = readdir(dir)) != NULL) {
2530                         if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
2531                                 /* do nothing */
2532                         } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
2533                                 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2534                                 BLI_delete(path_full, 0, 0);
2535                         } else {
2536                                 rmdir = 0; /* unknown file, dont remove the dir */
2537                         }
2538                 }
2539
2540                 closedir(dir);
2541         } else { 
2542                 rmdir = 0; /* path dosnt exist  */
2543         }
2544         
2545         if (rmdir) {
2546                 BLI_delete(path, 1, 0);
2547         }
2548 }
2549
2550 /* Continuous Interaction */
2551
2552 static int CONTINUE_PHYSICS = 0;
2553
2554 void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable)
2555 {
2556         Object *ob;
2557
2558         if(CONTINUE_PHYSICS != enable) {
2559                 CONTINUE_PHYSICS = enable;
2560
2561                 if(CONTINUE_PHYSICS == 0) {
2562                         for(ob=bmain->object.first; ob; ob=ob->id.next)
2563                                 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
2564                                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2565                 }
2566         }
2567 }
2568
2569 int  BKE_ptcache_get_continue_physics(void)
2570 {
2571         return CONTINUE_PHYSICS;
2572 }
2573
2574 /* Point Cache handling */
2575
2576 PointCache *BKE_ptcache_add(ListBase *ptcaches)
2577 {
2578         PointCache *cache;
2579
2580         cache= MEM_callocN(sizeof(PointCache), "PointCache");
2581         cache->startframe= 1;
2582         cache->endframe= 250;
2583         cache->step= 10;
2584         cache->index = -1;
2585
2586         BLI_addtail(ptcaches, cache);
2587
2588         return cache;
2589 }
2590
2591 void BKE_ptcache_free_mem(ListBase *mem_cache)
2592 {
2593         PTCacheMem *pm = mem_cache->first;
2594
2595         if(pm) {
2596                 for(; pm; pm=pm->next) {
2597                         ptcache_data_free(pm);
2598                         ptcache_extra_free(pm);
2599                 }
2600
2601                 BLI_freelistN(mem_cache);
2602         }
2603 }
2604 void BKE_ptcache_free(PointCache *cache)
2605 {
2606         BKE_ptcache_free_mem(&cache->mem_cache);
2607         if(cache->edit && cache->free_edit)
2608                 cache->free_edit(cache->edit);
2609         if(cache->cached_frames)
2610                 MEM_freeN(cache->cached_frames);
2611         MEM_freeN(cache);
2612 }
2613 void BKE_ptcache_free_list(ListBase *ptcaches)
2614 {
2615         PointCache *cache = ptcaches->first;
2616
2617         while(cache) {
2618                 BLI_remlink(ptcaches, cache);
2619                 BKE_ptcache_free(cache);
2620                 cache = ptcaches->first;
2621         }
2622 }
2623
2624 static PointCache *ptcache_copy(PointCache *cache)
2625 {
2626         PointCache *ncache;
2627
2628         ncache= MEM_dupallocN(cache);
2629
2630         /* hmm, should these be copied over instead? */
2631         ncache->mem_cache.first = NULL;
2632         ncache->mem_cache.last = NULL;
2633         ncache->cached_frames = NULL;
2634         ncache->edit = NULL;
2635
2636         ncache->flag= 0;
2637         ncache->simframe= 0;
2638
2639         return ncache;
2640 }
2641 /* returns first point cache */
2642 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old)
2643 {
2644         PointCache *cache = ptcaches_old->first;
2645
2646         ptcaches_new->first = ptcaches_new->last = NULL;
2647
2648         for(; cache; cache=cache->next)
2649                 BLI_addtail(ptcaches_new, ptcache_copy(cache));
2650
2651         return ptcaches_new->first;
2652 }
2653
2654
2655 /* Baking */
2656 void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
2657 {
2658         PTCacheBaker baker;
2659
2660         baker.bake=0;
2661         baker.break_data=NULL;
2662         baker.break_test=NULL;
2663         baker.pid=NULL;
2664         baker.progressbar=NULL;
2665         baker.progressend=NULL;
2666         baker.progresscontext=NULL;
2667         baker.render=0;
2668         baker.anim_init = 0;
2669         baker.main=bmain;
2670         baker.scene=scene;
2671         baker.quick_step=scene->physics_settings.quick_cache_step;
2672
2673         BKE_ptcache_bake(&baker);
2674 }
2675
2676 /* Simulation thread, no need for interlocks as data written in both threads
2677  are only unitary integers (I/O assumed to be atomic for them) */
2678 typedef struct {
2679         int break_operation;
2680         int thread_ended;
2681         int endframe;
2682         int step;
2683         int *cfra_ptr;
2684         Main *main;
2685         Scene *scene;
2686 } ptcache_bake_data;
2687
2688 static void ptcache_dt_to_str(char *str, double dtime)
2689 {
2690         if(dtime > 60.0) {
2691                 if(dtime > 3600.0)
2692                         sprintf(str, "%ih %im %is", (int)(dtime/3600), ((int)(dtime/60))%60, ((int)dtime) % 60);
2693                 else
2694                         sprintf(str, "%im %is", ((int)(dtime/60))%60, ((int)dtime) % 60);
2695         }
2696         else
2697                 sprintf(str, "%is", ((int)dtime) % 60);
2698 }
2699
2700 static void *ptcache_bake_thread(void *ptr) {
2701         int usetimer = 0, sfra, efra;
2702         double stime, ptime, ctime, fetd;
2703         char run[32], cur[32], etd[32];
2704
2705         ptcache_bake_data *data = (ptcache_bake_data*)ptr;
2706
2707         stime = ptime = PIL_check_seconds_timer();
2708         sfra = *data->cfra_ptr;
2709         efra = data->endframe;
2710
2711         for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) {
2712                 scene_update_for_newframe(data->main, data->scene, data->scene->lay);
2713                 if(G.background) {
2714                         printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe);
2715                 }
2716                 else {
2717                         ctime = PIL_check_seconds_timer();
2718
2719                         fetd = (ctime-ptime)*(efra-*data->cfra_ptr)/data->step;
2720
2721                         if(usetimer || fetd > 60.0) {
2722                                 usetimer = 1;
2723
2724                                 ptcache_dt_to_str(cur, ctime-ptime);
2725                                 ptcache_dt_to_str(run, ctime-stime);
2726                                 ptcache_dt_to_str(etd, fetd);
2727
2728                                 printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s          \r", run, *data->cfra_ptr-sfra+1, efra-sfra+1, ctime-ptime, etd);
2729                         }
2730                         ptime = ctime;
2731                 }
2732         }
2733
2734         if(usetimer) {
2735                 ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime);
2736                 printf("Bake %s %s (%i frames simulated).                       \n", (data->break_operation ? "canceled after" : "finished in"), run, *data->cfra_ptr-sfra);
2737         }
2738
2739         data->thread_ended = TRUE;
2740         return NULL;
2741 }
2742
2743 /* if bake is not given run simulations to current frame */
2744 void BKE_ptcache_bake(PTCacheBaker* baker)
2745 {
2746         Main *bmain = baker->main;
2747         Scene *scene = baker->scene;
2748         Scene *sce_iter; /* SETLOOPER macro only */
2749         Base *base;
2750         ListBase pidlist;
2751         PTCacheID *pid = baker->pid;
2752         PointCache *cache = NULL;
2753         float frameleno = scene->r.framelen;
2754         int cfrao = CFRA;
2755         int startframe = MAXFRAME;
2756         int bake = baker->bake;
2757         int render = baker->render;
2758         ListBase threads;
2759         ptcache_bake_data thread_data;
2760         int progress, old_progress;
2761         
2762         thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA;
2763         thread_data.step = baker->quick_step;
2764         thread_data.cfra_ptr = &CFRA;
2765         thread_data.scene = baker->scene;
2766         thread_data.main = baker->main;
2767
2768         G.afbreek = 0;
2769
2770         /* set caches to baking mode and figure out start frame */
2771         if(pid) {
2772                 /* cache/bake a single object */
2773                 cache = pid->cache;
2774                 if((cache->flag & PTCACHE_BAKED)==0) {
2775                         if(pid->type==PTCACHE_TYPE_PARTICLES) {
2776                                 ParticleSystem *psys= pid->calldata;
2777
2778                                 /* a bit confusing, could make this work better in the UI */
2779                                 if(psys->part->type == PART_EMITTER)
2780                                         psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
2781                         }
2782                         else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
2783                                 /* get all pids from the object and search for smoke low res */
2784                                 ListBase pidlist2;
2785                                 PTCacheID *pid2;
2786                                 BKE_ptcache_ids_from_object(&pidlist2, pid->ob, scene, MAX_DUPLI_RECUR);
2787                                 for(pid2=pidlist2.first; pid2; pid2=pid2->next) {
2788                                         if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) 
2789                                         {
2790                                                 if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) {
2791                                                         if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED)
2792                                                                 BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0);
2793                                                         if(bake) {
2794                                                                 pid2->cache->flag |= PTCACHE_BAKING;
2795                                                                 pid2->cache->flag &= ~PTCACHE_BAKED;
2796                                                         }
2797                                                 }
2798                                         }
2799                                 }
2800                                 BLI_freelistN(&pidlist2);
2801                         }
2802
2803                         if(bake || cache->flag & PTCACHE_REDO_NEEDED)
2804                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2805
2806                         startframe = MAX2(cache->last_exact, cache->startframe);
2807
2808                         if(bake) {
2809                                 thread_data.endframe = cache->endframe;
2810                                 cache->flag |= PTCACHE_BAKING;
2811                         }
2812                         else {
2813                                 thread_data.endframe = MIN2(thread_data.endframe, cache->endframe);
2814                         }
2815
2816                         cache->flag &= ~PTCACHE_BAKED;
2817                 }
2818         }
2819         else for(SETLOOPER(scene, sce_iter, base)) {
2820                 /* cache/bake everything in the scene */
2821                 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
2822
2823                 for(pid=pidlist.first; pid; pid=pid->next) {
2824                         cache = pid->cache;
2825                         if((cache->flag & PTCACHE_BAKED)==0) {
2826                                 if(pid->type==PTCACHE_TYPE_PARTICLES) {
2827                                         ParticleSystem *psys = (ParticleSystem*)pid->calldata;
2828                                         /* skip hair & keyed particles */
2829                                         if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
2830                                                 continue;
2831
2832                                         psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
2833                                 }
2834
2835                                 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
2836                                         && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
2837                                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2838
2839                                 startframe = MIN2(startframe, cache->startframe);
2840
2841                                 if(bake || render) {
2842                                         cache->flag |= PTCACHE_BAKING;
2843
2844                                         if(bake)
2845                                                 thread_data.endframe = MAX2(thread_data.endframe, cache->endframe);
2846                                 }
2847
2848                                 cache->flag &= ~PTCACHE_BAKED;
2849
2850                         }
2851                 }
2852                 BLI_freelistN(&pidlist);
2853         }
2854
2855         CFRA = startframe;
2856         scene->r.framelen = 1.0;
2857         thread_data.break_operation = FALSE;
2858         thread_data.thread_ended = FALSE;
2859         old_progress = -1;
2860
2861         WM_cursor_wait(1);
2862         
2863         if(G.background) {
2864                 ptcache_bake_thread((void*)&thread_data);
2865         }
2866         else {
2867                 BLI_init_threads(&threads, ptcache_bake_thread, 1);
2868                 BLI_insert_thread(&threads, (void*)&thread_data);
2869
2870                 while (thread_data.thread_ended == FALSE) {
2871
2872                         if(bake)
2873                                 progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe));
2874                         else
2875                                 progress = CFRA;
2876
2877                         /* NOTE: baking should not redraw whole ui as this slows things down */
2878                         if ((baker->progressbar) && (progress != old_progress)) {
2879                                 baker->progressbar(baker->progresscontext, progress);
2880                                 old_progress = progress;
2881                         }
2882
2883                         /* Delay to lessen CPU load from UI thread */
2884                         PIL_sleep_ms(200);
2885
2886                         /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
2887                         if(blender_test_break() && !thread_data.break_operation) {
2888                                 thread_data.break_operation = TRUE;
2889                                 if (baker->progressend)
2890                                         baker->progressend(baker->progresscontext);
2891                                 WM_cursor_wait(1);
2892                         }
2893                 }
2894
2895         BLI_end_threads(&threads);
2896         }
2897         /* clear baking flag */
2898         if(pid) {
2899                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
2900                 cache->flag |= PTCACHE_SIMULATION_VALID;
2901                 if(bake) {
2902                         cache->flag |= PTCACHE_BAKED;
2903                         /* write info file */
2904                         if(cache->flag & PTCACHE_DISK_CACHE)
2905                                 BKE_ptcache_write(pid, 0);
2906                 }
2907         }
2908         else for(SETLOOPER(scene, sce_iter, base)) {
2909                 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
2910
2911                 for(pid=pidlist.first; pid; pid=pid->next) {
2912                         /* skip hair particles */
2913                         if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
2914                                 continue;
2915                 
2916                         cache = pid->cache;
2917
2918                         if(thread_data.step > 1)
2919                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
2920                         else
2921                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
2922
2923                         cache->flag |= PTCACHE_SIMULATION_VALID;
2924
2925                         if(bake) {
2926                                 cache->flag |= PTCACHE_BAKED;
2927                                 if(cache->flag & PTCACHE_DISK_CACHE)
2928                                         BKE_ptcache_write(pid, 0);
2929                         }
2930                 }
2931                 BLI_freelistN(&pidlist);
2932         }
2933
2934         scene->r.framelen = frameleno;
2935         CFRA = cfrao;
2936         
2937         if(bake) /* already on cfra unless baking */
2938                 scene_update_for_newframe(bmain, scene, scene->lay);
2939
2940         if (thread_data.break_operation)
2941                 WM_cursor_wait(0);
2942         else if (baker->progressend)
2943                 baker->progressend(baker->progresscontext);
2944
2945         WM_cursor_wait(0);
2946
2947         /* TODO: call redraw all windows somehow */
2948 }
2949 /* Helpers */
2950 void BKE_ptcache_disk_to_mem(PTCacheID *pid)
2951 {
2952         PointCache *cache = pid->cache;
2953         PTCacheMem *pm = NULL;
2954         int baked = cache->flag & PTCACHE_BAKED;
2955         int cfra, sfra = cache->startframe, efra = cache->endframe;
2956
2957         /* Remove possible bake flag to allow clear */
2958         cache->flag &= ~PTCACHE_BAKED;
2959
2960         /* PTCACHE_DISK_CACHE flag was cleared already */
2961         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2962
2963         /* restore possible bake flag */
2964         cache->flag |= baked;
2965
2966         for(cfra=sfra; cfra <= efra; cfra++) {
2967                 pm = ptcache_disk_frame_to_mem(pid, cfra);
2968
2969                 if(pm)
2970                         BLI_addtail(&pid->cache->mem_cache, pm);
2971         }
2972 }
2973 void BKE_ptcache_mem_to_disk(PTCacheID *pid)
2974 {
2975         PointCache *cache = pid->cache;
2976         PTCacheMem *pm = cache->mem_cache.first;
2977         int baked = cache->flag & PTCACHE_BAKED;
2978
2979         /* Remove possible bake flag to allow clear */
2980         cache->flag &= ~PTCACHE_BAKED;
2981
2982         /* PTCACHE_DISK_CACHE flag was set already */
2983         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2984
2985         /* restore possible bake flag */
2986         cache->flag |= baked;
2987
2988         for(; pm; pm=pm->next) {
2989                 if(ptcache_mem_frame_to_disk(pid, pm)==0) {
2990                         cache->flag &= ~PTCACHE_DISK_CACHE;
2991                         break;
2992                 }
2993         }
2994
2995         /* write info file */
2996         if(cache->flag & PTCACHE_BAKED)
2997                 BKE_ptcache_write(pid, 0);
2998 }
2999 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
3000 {
3001         PointCache *cache = pid->cache;
3002         int last_exact = cache->last_exact;
3003
3004         if (!G.relbase_valid){
3005                 cache->flag &= ~PTCACHE_DISK_CACHE;
3006                 if (G.f & G_DEBUG) 
3007                         printf("File must be saved before using disk cache!\n");
3008                 return;
3009         }
3010
3011         if(cache->cached_frames) {
3012                 MEM_freeN(cache->cached_frames);
3013                 cache->cached_frames=NULL;
3014         }
3015
3016         if(cache->flag & PTCACHE_DISK_CACHE)
3017                 BKE_ptcache_mem_to_disk(pid);
3018         else
3019                 BKE_ptcache_disk_to_mem(pid);
3020
3021         cache->flag ^= PTCACHE_DISK_CACHE;
3022         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3023         cache->flag ^= PTCACHE_DISK_CACHE;
3024         
3025         cache->last_exact = last_exact;
3026
3027         BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL);
3028
3029         BKE_ptcache_update_info(pid);
3030 }
3031
3032 void BKE_ptcache_disk_cache_rename(PTCacheID *pid, char *from, char *to)
3033 {
3034         char old_name[80];
3035         int len; /* store the length of the string */
3036         /* mode is same as fopen's modes */
3037         DIR *dir; 
3038         struct dirent *de;
3039         char path[MAX_PTCACHE_PATH];
3040         char old_filename[MAX_PTCACHE_FILE];
3041         char new_path_full[MAX_PTCACHE_FILE];
3042         char old_path_full[MAX_PTCACHE_FILE];
3043         char ext[MAX_PTCACHE_PATH];
3044
3045         /* save old name */
3046         strcpy(old_name, pid->cache->name);
3047
3048         /* get "from" filename */
3049         strcpy(pid->cache->name, from);
3050
3051         len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */
3052
3053         ptcache_path(pid, path);
3054         dir = opendir(path);
3055         if(dir==NULL) {
3056                 strcpy(pid->cache->name, old_name);
3057                 return;
3058         }
3059
3060         BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
3061
3062         /* put new name into cache */
3063         strcpy(pid->cache->name, to);
3064
3065         while ((de = readdir(dir)) != NULL) {
3066                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
3067                         if (strncmp(old_filename, de->d_name, len ) == 0) { /* do we have the right prefix */
3068                                 /* read the number of the file */
3069                                 int frame, len2 = (int)strlen(de->d_name);
3070                                 char num[7];
3071
3072                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
3073                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
3074                                         frame = atoi(num);
3075
3076                                         BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name);
3077                                         ptcache_filename(pid, new_path_full, frame, 1, 1);
3078                                         BLI_rename(old_path_full, new_path_full);
3079                                 }
3080                         }
3081                 }
3082         }
3083         closedir(dir);
3084
3085         strcpy(pid->cache->name, old_name);
3086 }
3087
3088 void BKE_ptcache_load_external(PTCacheID *pid)
3089 {
3090         /*todo*/