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