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