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