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