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