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