Patch #34204: [Render Animation] Fails with "Error: Specified sample_fmt is not suppo...
[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)) {
844                 printf("Dynamic Paint: Invalid cache version: %s!\n", version);
845                 return 0;
846         }
847
848         if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
849                 unsigned int data_len;
850                 int surface_type;
851
852                 /* cache type */
853                 ptcache_file_read(pf, &surface_type, 1, sizeof(int));
854
855                 if (surface_type != surface->type)
856                         return 0;
857
858                 /* read surface data */
859                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
860                         data_len = sizeof(PaintPoint);
861                 }
862                 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
863                          surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
864                 {
865                         data_len = sizeof(float);
866                 }
867                 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
868                         data_len = sizeof(PaintWavePoint);
869                 }
870                 else {
871                         return 0;
872                 }
873
874                 ptcache_file_compressed_read(pf, (unsigned char *)surface->data->type_data, data_len*surface->data->total_points);
875
876         }
877         return 1;
878 }
879
880 /* Rigid Body functions */
881 static int  ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
882 {
883         RigidBodyWorld *rbw = rb_v;
884         Object *ob = NULL;
885         
886         if (rbw->objects)
887                 ob = rbw->objects[index];
888         
889         if (ob && ob->rigidbody_object) {
890                 RigidBodyOb *rbo = ob->rigidbody_object;
891                 
892                 if (rbo->type == RBO_TYPE_ACTIVE) {
893 #ifdef WITH_BULLET
894                         RB_body_get_position(rbo->physics_object, rbo->pos);
895                         RB_body_get_orientation(rbo->physics_object, rbo->orn);
896 #endif
897                         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
898                         PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
899                 }
900         }
901
902         return 1;
903 }
904 static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data)
905 {
906         RigidBodyWorld *rbw = rb_v;
907         Object *ob = NULL;
908         
909         if (rbw->objects)
910                 ob = rbw->objects[index];
911         
912         if (ob && ob->rigidbody_object) {
913                 RigidBodyOb *rbo = ob->rigidbody_object;
914                 
915                 if (rbo->type == RBO_TYPE_ACTIVE) {
916                         
917                         if (old_data) {
918                                 memcpy(rbo->pos, data, 3 * sizeof(float));
919                                 memcpy(rbo->orn, data + 3, 4 * sizeof(float));
920                         }
921                         else {
922                                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos);
923                                 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn);
924                         }
925                 }
926         }
927 }
928 static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
929 {
930         RigidBodyWorld *rbw = rb_v;
931         Object *ob = NULL;
932         ParticleKey keys[4];
933         float dfra;
934         
935         if (rbw->objects)
936                 ob = rbw->objects[index];
937         
938         if (ob && ob->rigidbody_object) {
939                 RigidBodyOb *rbo = ob->rigidbody_object;
940                 
941                 if (rbo->type == RBO_TYPE_ACTIVE) {
942                         
943                         copy_v3_v3(keys[1].co, rbo->pos);
944                         copy_v3_v3(keys[1].rot, rbo->orn);
945                         
946                         if (old_data) {
947                                 memcpy(keys[2].co, data, 3 * sizeof(float));
948                                 memcpy(keys[2].rot, data + 3, 4 * sizeof(float));
949                         }
950                         else {
951                                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
952                         }
953                         
954                         dfra = cfra2 - cfra1;
955                 
956                         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
957                         interp_qt_qtqt(keys->rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
958                         
959                         copy_v3_v3(rbo->pos, keys->co);
960                         copy_v3_v3(rbo->orn, keys->rot);
961                 }
962         }
963 }
964 static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
965 {
966         RigidBodyWorld *rbw = rb_v;
967         
968         return rbw->numbodies;
969 }
970
971 /* Creating ID's */
972 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
973 {
974         memset(pid, 0, sizeof(PTCacheID));
975
976         pid->ob= ob;
977         pid->calldata= sb;
978         pid->type= PTCACHE_TYPE_SOFTBODY;
979         pid->cache= sb->pointcache;
980         pid->cache_ptr= &sb->pointcache;
981         pid->ptcaches= &sb->ptcaches;
982         pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
983
984         pid->write_point                        = ptcache_softbody_write;
985         pid->read_point                         = ptcache_softbody_read;
986         pid->interpolate_point          = ptcache_softbody_interpolate;
987
988         pid->write_stream                       = NULL;
989         pid->read_stream                        = NULL;
990
991         pid->write_extra_data           = NULL;
992         pid->read_extra_data            = NULL;
993         pid->interpolate_extra_data     = NULL;
994
995         pid->write_header                       = ptcache_basic_header_write;
996         pid->read_header                        = ptcache_basic_header_read;
997
998         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
999         pid->info_types= 0;
1000
1001         pid->stack_index = pid->cache->index;
1002
1003         pid->default_step = 10;
1004         pid->max_step = 20;
1005 }
1006 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
1007 {
1008         memset(pid, 0, sizeof(PTCacheID));
1009
1010         pid->ob= ob;
1011         pid->calldata= psys;
1012         pid->type= PTCACHE_TYPE_PARTICLES;
1013         pid->stack_index= psys->pointcache->index;
1014         pid->cache= psys->pointcache;
1015         pid->cache_ptr= &psys->pointcache;
1016         pid->ptcaches= &psys->ptcaches;
1017
1018         if (psys->part->type != PART_HAIR)
1019                 pid->flag |= PTCACHE_VEL_PER_SEC;
1020
1021         pid->totpoint                           = ptcache_particle_totpoint;
1022         pid->totwrite                           = ptcache_particle_totwrite;
1023
1024         pid->write_point                                = ptcache_particle_write;
1025         pid->read_point                         = ptcache_particle_read;
1026         pid->interpolate_point          = ptcache_particle_interpolate;
1027
1028         pid->write_stream                       = NULL;
1029         pid->read_stream                        = NULL;
1030
1031         pid->write_extra_data           = NULL;
1032         pid->read_extra_data            = NULL;
1033         pid->interpolate_extra_data     = NULL;
1034
1035         pid->write_header                       = ptcache_basic_header_write;
1036         pid->read_header                        = ptcache_basic_header_read;
1037
1038         pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
1039
1040         if (psys->part->phystype == PART_PHYS_BOIDS)
1041                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
1042         else if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) {
1043                 pid->write_extra_data = ptcache_particle_extra_write;
1044                 pid->read_extra_data = ptcache_particle_extra_read;
1045         }
1046
1047         if (psys->part->flag & PART_ROTATIONS) {
1048                 pid->data_types|= (1<<BPHYS_DATA_ROTATION);
1049
1050                 if (psys->part->rotmode != PART_ROT_VEL  ||
1051                     psys->part->avemode == PART_AVE_RAND ||
1052                     psys->part->avefac != 0.0f)
1053                 {
1054                         pid->data_types |= (1 << BPHYS_DATA_AVELOCITY);
1055                 }
1056         }
1057
1058         pid->info_types= (1<<BPHYS_DATA_TIMES);
1059
1060         pid->default_step = 10;
1061         pid->max_step = 20;
1062 }
1063 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
1064 {
1065         memset(pid, 0, sizeof(PTCacheID));
1066
1067         pid->ob= ob;
1068         pid->calldata= clmd;
1069         pid->type= PTCACHE_TYPE_CLOTH;
1070         pid->stack_index= clmd->point_cache->index;
1071         pid->cache= clmd->point_cache;
1072         pid->cache_ptr= &clmd->point_cache;
1073         pid->ptcaches= &clmd->ptcaches;
1074         pid->totpoint= pid->totwrite= ptcache_cloth_totpoint;
1075
1076         pid->write_point                        = ptcache_cloth_write;
1077         pid->read_point                         = ptcache_cloth_read;
1078         pid->interpolate_point          = ptcache_cloth_interpolate;
1079
1080         pid->write_stream                       = NULL;
1081         pid->read_stream                        = NULL;
1082
1083         pid->write_extra_data           = NULL;
1084         pid->read_extra_data            = NULL;
1085         pid->interpolate_extra_data     = NULL;
1086
1087         pid->write_header                       = ptcache_basic_header_write;
1088         pid->read_header                        = ptcache_basic_header_read;
1089
1090         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
1091         pid->info_types= 0;
1092
1093         pid->default_step = 1;
1094         pid->max_step = 1;
1095 }
1096 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
1097 {
1098         SmokeDomainSettings *sds = smd->domain;
1099
1100         memset(pid, 0, sizeof(PTCacheID));
1101
1102         pid->ob= ob;
1103         pid->calldata= smd;
1104         
1105         pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
1106         pid->stack_index= sds->point_cache[0]->index;
1107
1108         pid->cache= sds->point_cache[0];
1109         pid->cache_ptr= &(sds->point_cache[0]);
1110         pid->ptcaches= &(sds->ptcaches[0]);
1111
1112         pid->totpoint= pid->totwrite= ptcache_smoke_totpoint;
1113
1114         pid->write_point                        = NULL;
1115         pid->read_point                         = NULL;
1116         pid->interpolate_point          = NULL;
1117
1118         pid->read_stream                        = ptcache_smoke_read;
1119         pid->write_stream                       = ptcache_smoke_write;
1120
1121         pid->write_extra_data           = NULL;
1122         pid->read_extra_data            = NULL;
1123         pid->interpolate_extra_data     = NULL;
1124
1125         pid->write_header                       = ptcache_basic_header_write;
1126         pid->read_header                        = ptcache_basic_header_read;
1127
1128         pid->data_types= 0;
1129         pid->info_types= 0;
1130
1131         if (sds->fluid)
1132                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW);
1133         if (sds->wt)
1134                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH);
1135
1136         pid->default_step = 1;
1137         pid->max_step = 1;
1138 }
1139
1140 void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
1141 {
1142
1143         memset(pid, 0, sizeof(PTCacheID));
1144
1145         pid->ob= ob;
1146         pid->calldata= surface;
1147         pid->type= PTCACHE_TYPE_DYNAMICPAINT;
1148         pid->cache= surface->pointcache;
1149         pid->cache_ptr= &surface->pointcache;
1150         pid->ptcaches= &surface->ptcaches;
1151         pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint;
1152
1153         pid->write_point                        = NULL;
1154         pid->read_point                         = NULL;
1155         pid->interpolate_point          = NULL;
1156
1157         pid->write_stream                       = ptcache_dynamicpaint_write;
1158         pid->read_stream                        = ptcache_dynamicpaint_read;
1159
1160         pid->write_extra_data           = NULL;
1161         pid->read_extra_data            = NULL;
1162         pid->interpolate_extra_data     = NULL;
1163
1164         pid->write_header                       = ptcache_basic_header_write;
1165         pid->read_header                        = ptcache_basic_header_read;
1166
1167         pid->data_types= BPHYS_DATA_DYNAMICPAINT;
1168         pid->info_types= 0;
1169
1170         pid->stack_index = pid->cache->index;
1171
1172         pid->default_step = 1;
1173         pid->max_step = 1;
1174 }
1175
1176 void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
1177 {
1178         
1179         memset(pid, 0, sizeof(PTCacheID));
1180         
1181         pid->ob= ob;
1182         pid->calldata= rbw;
1183         pid->type= PTCACHE_TYPE_RIGIDBODY;
1184         pid->cache= rbw->pointcache;
1185         pid->cache_ptr= &rbw->pointcache;
1186         pid->ptcaches= &rbw->ptcaches;
1187         pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
1188         
1189         pid->write_point                        = ptcache_rigidbody_write;
1190         pid->read_point                         = ptcache_rigidbody_read;
1191         pid->interpolate_point          = ptcache_rigidbody_interpolate;
1192         
1193         pid->write_stream                       = NULL;
1194         pid->read_stream                        = NULL;
1195         
1196         pid->write_extra_data           = NULL;
1197         pid->read_extra_data            = NULL;
1198         pid->interpolate_extra_data     = NULL;
1199         
1200         pid->write_header                       = ptcache_basic_header_write;
1201         pid->read_header                        = ptcache_basic_header_read;
1202         
1203         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_ROTATION);
1204         pid->info_types= 0;
1205         
1206         pid->stack_index = pid->cache->index;
1207         
1208         pid->default_step = 1;
1209         pid->max_step = 1;
1210 }
1211
1212 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
1213 {
1214         PTCacheID *pid;
1215         ParticleSystem *psys;
1216         ModifierData *md;
1217
1218         lb->first= lb->last= NULL;
1219
1220         if (ob->soft) {
1221                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1222                 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
1223                 BLI_addtail(lb, pid);
1224         }
1225
1226         for (psys=ob->particlesystem.first; psys; psys=psys->next) {
1227                 if (psys->part==NULL)
1228                         continue;
1229                 
1230                 /* check to make sure point cache is actually used by the particles */
1231                 if (ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
1232                         continue;
1233
1234                 /* hair needs to be included in id-list for cache edit mode to work */
1235                 /* if (psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */
1236                 /*      continue; */
1237                         
1238                 if (psys->part->type == PART_FLUID)
1239                         continue;
1240
1241                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1242                 BKE_ptcache_id_from_particles(pid, ob, psys);
1243                 BLI_addtail(lb, pid);
1244         }
1245
1246         for (md=ob->modifiers.first; md; md=md->next) {
1247                 if (md->type == eModifierType_Cloth) {
1248                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1249                         BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
1250                         BLI_addtail(lb, pid);
1251                 }
1252                 else if (md->type == eModifierType_Smoke) {
1253                         SmokeModifierData *smd = (SmokeModifierData *)md;
1254                         if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1255                                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1256                                 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md);
1257                                 BLI_addtail(lb, pid);
1258                         }
1259                 }
1260                 else if (md->type == eModifierType_DynamicPaint) {
1261                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
1262                         if (pmd->canvas) {
1263                                 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
1264
1265                                 for (; surface; surface=surface->next) {
1266                                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1267                                         BKE_ptcache_id_from_dynamicpaint(pid, ob, surface);
1268                                         BLI_addtail(lb, pid);
1269                                 }
1270                         }
1271                 }
1272         }
1273         
1274         if (scene && ob->rigidbody_object && scene->rigidbody_world) {
1275                 pid = MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1276                 BKE_ptcache_id_from_rigidbody(pid, ob, scene->rigidbody_world);
1277                 BLI_addtail(lb, pid);
1278         }
1279
1280         if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
1281                 ListBase *lb_dupli_ob;
1282
1283                 /* don't update the dupli groups, we only want their pid's */
1284                 if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE, FALSE))) {
1285                         DupliObject *dob;
1286                         for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
1287                                 if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
1288                                         ListBase lb_dupli_pid;
1289                                         BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
1290                                         BLI_movelisttolist(lb, &lb_dupli_pid);
1291                                         if (lb_dupli_pid.first)
1292                                                 printf("Adding Dupli\n");
1293                                 }
1294                         }
1295
1296                         free_object_duplilist(lb_dupli_ob);     /* does restore */
1297                 }
1298         }
1299 }
1300
1301 /* File handling */
1302
1303 /* Takes an Object ID and returns a unique name
1304  * - id: object id
1305  * - cfra: frame for the cache, can be negative
1306  * - stack_index: index in the modifier stack. we can have cache for more then one stack_index
1307  */
1308
1309 #define MAX_PTCACHE_PATH FILE_MAX
1310 #define MAX_PTCACHE_FILE (FILE_MAX * 2)
1311
1312 static int ptcache_path(PTCacheID *pid, char *filename)
1313 {
1314         Library *lib= (pid->ob)? pid->ob->id.lib: NULL;
1315         const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name;
1316         size_t i;
1317
1318         if (pid->cache->flag & PTCACHE_EXTERNAL) {
1319                 strcpy(filename, pid->cache->path);
1320
1321                 if (BLI_path_is_rel(filename)) {
1322                         BLI_path_abs(filename, blendfilename);
1323                 }
1324
1325                 return BLI_add_slash(filename); /* new strlen() */
1326         }
1327         else if (G.relbase_valid || lib) {
1328                 char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
1329
1330                 BLI_split_file_part(blendfilename, file, sizeof(file));
1331                 i = strlen(file);
1332                 
1333                 /* remove .blend */
1334                 if (i > 6)
1335                         file[i-6] = '\0';
1336                 
1337                 BLI_snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
1338                 BLI_path_abs(filename, blendfilename);
1339                 return BLI_add_slash(filename); /* new strlen() */
1340         }
1341         
1342         /* use the temp path. this is weak but better then not using point cache at all */
1343         /* temporary directory is assumed to exist and ALWAYS has a trailing slash */
1344         BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", BLI_temporary_dir(), abs(getpid()));
1345         
1346         return BLI_add_slash(filename); /* new strlen() */
1347 }
1348
1349 static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
1350 {
1351         int len=0;
1352         char *idname;
1353         char *newname;
1354         filename[0] = '\0';
1355         newname = filename;
1356         
1357         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
1358         
1359         /* start with temp dir */
1360         if (do_path) {
1361                 len = ptcache_path(pid, filename);
1362                 newname += len;
1363         }
1364         if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
1365                 idname = (pid->ob->id.name+2);
1366                 /* convert chars to hex so they are always a valid filename */
1367                 while ('\0' != *idname) {
1368                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
1369                         newname+=2;
1370                         len += 2;
1371                 }
1372         }
1373         else {
1374                 int temp = (int)strlen(pid->cache->name); 
1375                 strcpy(newname, pid->cache->name); 
1376                 newname+=temp;
1377                 len += temp;
1378         }
1379
1380         if (do_ext) {
1381
1382                 if (pid->cache->index < 0)
1383                         pid->cache->index =  pid->stack_index = BKE_object_insert_ptcache(pid->ob);
1384
1385                 if (pid->cache->flag & PTCACHE_EXTERNAL) {
1386                         if (pid->cache->index >= 0)
1387                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1388                         else
1389                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
1390                 }
1391                 else {
1392                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1393                 }
1394                 len += 16;
1395         }
1396         
1397         return len; /* make sure the above string is always 16 chars */
1398 }
1399
1400 /* youll need to close yourself after! */
1401 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
1402 {
1403         PTCacheFile *pf;
1404         FILE *fp = NULL;
1405         char filename[FILE_MAX * 2];
1406
1407 #ifndef DURIAN_POINTCACHE_LIB_OK
1408         /* don't allow writing for linked objects */
1409         if (pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
1410                 return NULL;
1411 #endif
1412         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
1413         
1414         ptcache_filename(pid, filename, cfra, 1, 1);
1415
1416         if (mode==PTCACHE_FILE_READ) {
1417                 if (!BLI_exists(filename)) {
1418                         return NULL;
1419                 }
1420                 fp = BLI_fopen(filename, "rb");
1421         }
1422         else if (mode==PTCACHE_FILE_WRITE) {
1423                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
1424                 fp = BLI_fopen(filename, "wb");
1425         }
1426         else if (mode==PTCACHE_FILE_UPDATE) {
1427                 BLI_make_existing_file(filename);
1428                 fp = BLI_fopen(filename, "rb+");
1429         }
1430
1431         if (!fp)
1432                 return NULL;
1433
1434         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
1435         pf->fp= fp;
1436         pf->old_format = 0;
1437         pf->frame = cfra;
1438
1439         return pf;
1440 }
1441 static void ptcache_file_close(PTCacheFile *pf)
1442 {
1443         if (pf) {
1444                 fclose(pf->fp);
1445                 MEM_freeN(pf);
1446         }
1447 }
1448
1449 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
1450 {
1451         int r = 0;
1452         unsigned char compressed = 0;
1453         size_t in_len;
1454 #ifdef WITH_LZO
1455         size_t out_len = len;
1456 #endif
1457         unsigned char *in;
1458         unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
1459
1460         ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
1461         if (compressed) {
1462                 unsigned int size;
1463                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1464                 in_len = (size_t)size;
1465                 if (in_len==0) {
1466                         /* do nothing */
1467                 }
1468                 else {
1469                         in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
1470                         ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
1471 #ifdef WITH_LZO
1472                         if (compressed == 1)
1473                                 r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
1474 #endif
1475 #ifdef WITH_LZMA
1476                         if (compressed == 2) {
1477                                 size_t sizeOfIt;
1478                                 size_t leni = in_len, leno = len;
1479                                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1480                                 sizeOfIt = (size_t)size;
1481                                 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
1482                                 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
1483                         }
1484 #endif
1485                         MEM_freeN(in);
1486                 }
1487         }
1488         else {
1489                 ptcache_file_read(pf, result, len, sizeof(unsigned char));
1490         }
1491
1492         MEM_freeN(props);
1493
1494         return r;
1495 }
1496 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
1497 {
1498         int r = 0;
1499         unsigned char compressed = 0;
1500         size_t out_len= 0;
1501         unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
1502         size_t sizeOfIt = 5;
1503
1504         (void)mode; /* unused when building w/o compression */
1505
1506 #ifdef WITH_LZO
1507         out_len= LZO_OUT_LEN(in_len);
1508         if (mode == 1) {
1509                 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
1510                 
1511                 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
1512                 if (!(r == LZO_E_OK) || (out_len >= in_len))
1513                         compressed = 0;
1514                 else
1515                         compressed = 1;
1516         }
1517 #endif
1518 #ifdef WITH_LZMA
1519         if (mode == 2) {
1520                 
1521                 r = LzmaCompress(out, &out_len, in, in_len, //assume sizeof(char)==1....
1522                                  props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
1523
1524                 if (!(r == SZ_OK) || (out_len >= in_len))
1525                         compressed = 0;
1526                 else
1527                         compressed = 2;
1528         }
1529 #endif
1530         
1531         ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
1532         if (compressed) {
1533                 unsigned int size = out_len;
1534                 ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
1535                 ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
1536         }
1537         else
1538                 ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
1539
1540         if (compressed == 2) {
1541                 unsigned int size = sizeOfIt;
1542                 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
1543                 ptcache_file_write(pf, props, size, sizeof(unsigned char));
1544         }
1545
1546         MEM_freeN(props);
1547
1548         return r;
1549 }
1550 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
1551 {
1552         return (fread(f, size, tot, pf->fp) == tot);
1553 }
1554 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size)
1555 {
1556         return (fwrite(f, size, tot, pf->fp) == tot);
1557 }
1558 static int ptcache_file_data_read(PTCacheFile *pf)
1559 {
1560         int i;
1561
1562         for (i=0; i<BPHYS_TOT_DATA; i++) {
1563                 if ((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
1564                         return 0;
1565         }
1566         
1567         return 1;
1568 }
1569 static int ptcache_file_data_write(PTCacheFile *pf)
1570 {               
1571         int i;
1572
1573         for (i=0; i<BPHYS_TOT_DATA; i++) {
1574                 if ((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
1575                         return 0;
1576         }
1577         
1578         return 1;
1579 }
1580 static int ptcache_file_header_begin_read(PTCacheFile *pf)
1581 {
1582         unsigned int typeflag=0;
1583         int error=0;
1584         char bphysics[8];
1585         
1586         pf->data_types = 0;
1587         
1588         if (fread(bphysics, sizeof(char), 8, pf->fp) != 8)
1589                 error = 1;
1590         
1591         if (!error && strncmp(bphysics, "BPHYSICS", 8))
1592                 error = 1;
1593
1594         if (!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp))
1595                 error = 1;
1596
1597         pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
1598         pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
1599         
1600         /* if there was an error set file as it was */
1601         if (error)
1602                 fseek(pf->fp, 0, SEEK_SET);
1603
1604         return !error;
1605 }
1606 static int ptcache_file_header_begin_write(PTCacheFile *pf)
1607 {
1608         const char *bphysics = "BPHYSICS";
1609         unsigned int typeflag = pf->type + pf->flag;
1610         
1611         if (fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
1612                 return 0;
1613
1614         if (!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp))
1615                 return 0;
1616         
1617         return 1;
1618 }
1619
1620 /* Data pointer handling */
1621 int BKE_ptcache_data_size(int data_type)
1622 {
1623         return ptcache_data_size[data_type];
1624 }
1625
1626 static void ptcache_file_pointers_init(PTCacheFile *pf)
1627 {
1628         int data_types = pf->data_types;
1629
1630         pf->cur[BPHYS_DATA_INDEX] =             (data_types & (1<<BPHYS_DATA_INDEX))    ?               &pf->data.index : NULL;
1631         pf->cur[BPHYS_DATA_LOCATION] =  (data_types & (1<<BPHYS_DATA_LOCATION)) ?               &pf->data.loc   : NULL;
1632         pf->cur[BPHYS_DATA_VELOCITY] =  (data_types & (1<<BPHYS_DATA_VELOCITY)) ?               &pf->data.vel   : NULL;
1633         pf->cur[BPHYS_DATA_ROTATION] =  (data_types & (1<<BPHYS_DATA_ROTATION)) ?               &pf->data.rot   : NULL;
1634         pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))?               &pf->data.ave   : NULL;
1635         pf->cur[BPHYS_DATA_SIZE] =              (data_types & (1<<BPHYS_DATA_SIZE))             ?               &pf->data.size  : NULL;
1636         pf->cur[BPHYS_DATA_TIMES] =             (data_types & (1<<BPHYS_DATA_TIMES))    ?               &pf->data.times : NULL;
1637         pf->cur[BPHYS_DATA_BOIDS] =             (data_types & (1<<BPHYS_DATA_BOIDS))    ?               &pf->data.boids : NULL;
1638 }
1639
1640 /* Check to see if point number "index" is in pm, uses binary search for index data. */
1641 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
1642 {
1643         if (pm->data[BPHYS_DATA_INDEX]) {
1644                 unsigned int *data = pm->data[BPHYS_DATA_INDEX];
1645                 unsigned int mid, low = 0, high = pm->totpoint - 1;
1646
1647                 if (index < *data || index > *(data+high))
1648                         return -1;
1649
1650                 /* check simple case for continuous indexes first */
1651                 if (index-*data < high && data[index-*data] == index)
1652                         return index-*data;
1653
1654                 while (low <= high) {
1655                         mid= (low + high)/2;
1656
1657                         if (data[mid] > index)
1658                                 high = mid - 1;
1659                         else if (data[mid] < index)
1660                                 low = mid + 1;
1661                         else
1662                                 return mid;
1663                 }
1664
1665                 return -1;
1666         }
1667         else {
1668                 return (index < pm->totpoint ? index : -1);
1669         }
1670 }
1671
1672 void BKE_ptcache_mem_pointers_init(PTCacheMem *pm)
1673 {
1674         int data_types = pm->data_types;
1675         int i;
1676
1677         for (i=0; i<BPHYS_TOT_DATA; i++)
1678                 pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL);
1679 }
1680
1681 void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
1682 {
1683         int i;
1684
1685         for (i=0; i<BPHYS_TOT_DATA; i++) {
1686                 if (pm->cur[i])
1687                         pm->cur[i] = (char *)pm->cur[i] + ptcache_data_size[i];
1688         }
1689 }
1690 int  BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
1691 {
1692         int data_types = pm->data_types;
1693         int i, index = BKE_ptcache_mem_index_find(pm, point_index);
1694
1695         if (index < 0) {
1696                 /* Can't give proper location without reallocation, so don't give any location.
1697                  * Some points will be cached improperly, but this only happens with simulation
1698                  * steps bigger than cache->step, so the cache has to be recalculated anyways
1699                  * at some point.
1700                  */
1701                 return 0;
1702         }
1703
1704         for (i=0; i<BPHYS_TOT_DATA; i++)
1705                 pm->cur[i] = data_types & (1<<i) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL;
1706
1707         return 1;
1708 }
1709 static void ptcache_data_alloc(PTCacheMem *pm)
1710 {
1711         int data_types = pm->data_types;
1712         int totpoint = pm->totpoint;
1713         int i;
1714
1715         for (i=0; i<BPHYS_TOT_DATA; i++) {
1716                 if (data_types & (1<<i))
1717                         pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
1718         }
1719 }
1720 static void ptcache_data_free(PTCacheMem *pm)
1721 {
1722         void **data = pm->data;
1723         int i;
1724
1725         for (i=0; i<BPHYS_TOT_DATA; i++) {
1726                 if (data[i])
1727                         MEM_freeN(data[i]);
1728         }
1729 }
1730 static void ptcache_data_copy(void *from[], void *to[])
1731 {
1732         int i;
1733         for (i=0; i<BPHYS_TOT_DATA; i++) {
1734         /* note, durian file 03.4b_comp crashes if to[i] is not tested
1735          * its NULL, not sure if this should be fixed elsewhere but for now its needed */
1736                 if (from[i] && to[i])
1737                         memcpy(to[i], from[i], ptcache_data_size[i]);
1738         }
1739 }
1740
1741 static void ptcache_extra_free(PTCacheMem *pm)
1742 {
1743         PTCacheExtra *extra = pm->extradata.first;
1744
1745         if (extra) {
1746                 for (; extra; extra=extra->next) {
1747                         if (extra->data)
1748                                 MEM_freeN(extra->data);
1749                 }
1750
1751                 BLI_freelistN(&pm->extradata);
1752         }
1753 }
1754 static int ptcache_old_elemsize(PTCacheID *pid)
1755 {
1756         if (pid->type==PTCACHE_TYPE_SOFTBODY)
1757                 return 6 * sizeof(float);
1758         else if (pid->type==PTCACHE_TYPE_PARTICLES)
1759                 return sizeof(ParticleKey);
1760         else if (pid->type==PTCACHE_TYPE_CLOTH)
1761                 return 9 * sizeof(float);
1762
1763         return 0;
1764 }
1765
1766 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
1767 {
1768         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
1769                 int cfra1=frame, cfra2=frame+1;
1770
1771                 while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1))
1772                         cfra1--;
1773
1774                 if (cfra1 < pid->cache->startframe)
1775                         cfra1 = 0;
1776
1777                 while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2))
1778                         cfra2++;
1779
1780                 if (cfra2 > pid->cache->endframe)
1781                         cfra2 = 0;
1782
1783                 if (cfra1 && !cfra2) {
1784                         *fra1 = 0;
1785                         *fra2 = cfra1;
1786                 }
1787                 else {
1788                         *fra1 = cfra1;
1789                         *fra2 = cfra2;
1790                 }
1791         }
1792         else if (pid->cache->mem_cache.first) {
1793                 PTCacheMem *pm = pid->cache->mem_cache.first;
1794                 PTCacheMem *pm2 = pid->cache->mem_cache.last;
1795
1796                 while (pm->next && pm->next->frame <= frame)
1797                         pm= pm->next;
1798
1799                 if (pm2->frame < frame) {
1800                         pm2 = NULL;
1801                 }
1802                 else {
1803                         while (pm2->prev && pm2->prev->frame > frame) {
1804                                 pm2= pm2->prev;
1805                         }
1806                 }
1807
1808                 if (!pm2) {
1809                         *fra1 = 0;
1810                         *fra2 = pm->frame;
1811                 }
1812                 else {
1813                         *fra1 = pm->frame;
1814                         *fra2 = pm2->frame;
1815                 }
1816         }
1817 }
1818
1819 static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
1820 {
1821         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1822         PTCacheMem *pm = NULL;
1823         unsigned int i, error = 0;
1824
1825         if (pf == NULL)
1826                 return NULL;
1827
1828         if (!ptcache_file_header_begin_read(pf))
1829                 error = 1;
1830
1831         if (!error && (pf->type != pid->type || !pid->read_header(pf)))
1832                 error = 1;
1833
1834         if (!error) {
1835                 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1836
1837                 pm->totpoint = pf->totpoint;
1838                 pm->data_types = pf->data_types;
1839                 pm->frame = pf->frame;
1840
1841                 ptcache_data_alloc(pm);
1842
1843                 if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
1844                         for (i=0; i<BPHYS_TOT_DATA; i++) {
1845                                 unsigned int out_len = pm->totpoint*ptcache_data_size[i];
1846                                 if (pf->data_types & (1<<i))
1847                                         ptcache_file_compressed_read(pf, (unsigned char *)(pm->data[i]), out_len);
1848                         }
1849                 }
1850                 else {
1851                         BKE_ptcache_mem_pointers_init(pm);
1852                         ptcache_file_pointers_init(pf);
1853
1854                         for (i=0; i<pm->totpoint; i++) {
1855                                 if (!ptcache_file_data_read(pf)) {
1856                                         error = 1;
1857                                         break;
1858                                 }
1859                                 ptcache_data_copy(pf->cur, pm->cur);
1860                                 BKE_ptcache_mem_pointers_incr(pm);
1861                         }
1862                 }
1863         }
1864
1865         if (!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) {
1866                 unsigned int extratype = 0;
1867
1868                 while (ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) {
1869                         PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata");
1870
1871                         extra->type = extratype;
1872
1873                         ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int));
1874
1875                         extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data");
1876
1877                         if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS)
1878                                 ptcache_file_compressed_read(pf, (unsigned char *)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]);
1879                         else
1880                                 ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
1881
1882                         BLI_addtail(&pm->extradata, extra);
1883                 }
1884         }
1885
1886         if (error && pm) {
1887                 ptcache_data_free(pm);
1888                 ptcache_extra_free(pm);
1889                 MEM_freeN(pm);
1890                 pm = NULL;
1891         }
1892
1893         ptcache_file_close(pf);
1894
1895         if (error && G.debug & G_DEBUG)
1896                 printf("Error reading from disk cache\n");
1897         
1898         return pm;
1899 }
1900 static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
1901 {
1902         PTCacheFile *pf = NULL;
1903         unsigned int i, error = 0;
1904         
1905         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame);
1906
1907         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
1908
1909         if (pf==NULL) {
1910                 if (G.debug & G_DEBUG)
1911                         printf("Error opening disk cache file for writing\n");
1912                 return 0;
1913         }
1914
1915         pf->data_types = pm->data_types;
1916         pf->totpoint = pm->totpoint;
1917         pf->type = pid->type;
1918         pf->flag = 0;
1919         
1920         if (pm->extradata.first)
1921                 pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
1922         
1923         if (pid->cache->compression)
1924                 pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
1925
1926         if (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))
1927                 error = 1;
1928
1929         if (!error) {
1930                 if (pid->cache->compression) {
1931                         for (i=0; i<BPHYS_TOT_DATA; i++) {
1932                                 if (pm->data[i]) {
1933                                         unsigned int in_len = pm->totpoint*ptcache_data_size[i];
1934                                         unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
1935                                         ptcache_file_compressed_write(pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression);
1936                                         MEM_freeN(out);
1937                                 }
1938                         }
1939                 }
1940                 else {
1941                         BKE_ptcache_mem_pointers_init(pm);
1942                         ptcache_file_pointers_init(pf);
1943
1944                         for (i=0; i<pm->totpoint; i++) {
1945                                 ptcache_data_copy(pm->cur, pf->cur);
1946                                 if (!ptcache_file_data_write(pf)) {
1947                                         error = 1;
1948                                         break;
1949                                 }
1950                                 BKE_ptcache_mem_pointers_incr(pm);
1951                         }
1952                 }
1953         }
1954
1955         if (!error && pm->extradata.first) {
1956                 PTCacheExtra *extra = pm->extradata.first;
1957
1958                 for (; extra; extra=extra->next) {
1959                         if (extra->data == NULL || extra->totdata == 0)
1960                                 continue;
1961
1962                         ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
1963                         ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
1964
1965                         if (pid->cache->compression) {
1966                                 unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
1967                                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
1968                                 ptcache_file_compressed_write(pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression);
1969                                 MEM_freeN(out);
1970                         }
1971                         else {
1972                                 ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
1973                         }
1974                 }
1975         }
1976
1977         ptcache_file_close(pf);
1978         
1979         if (error && G.debug & G_DEBUG)
1980                 printf("Error writing to disk cache\n");
1981
1982         return error==0;
1983 }
1984
1985 static int ptcache_read_stream(PTCacheID *pid, int cfra)
1986 {
1987         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1988         int error = 0;
1989
1990         if (pid->read_stream == NULL)
1991                 return 0;
1992
1993         if (pf == NULL) {
1994                 if (G.debug & G_DEBUG)
1995                         printf("Error opening disk cache file for reading\n");
1996                 return 0;
1997         }
1998
1999         if (!ptcache_file_header_begin_read(pf))
2000                 error = 1;
2001
2002         if (!error && (pf->type != pid->type || !pid->read_header(pf)))
2003                 error = 1;
2004
2005         if (!error && pf->totpoint != pid->totpoint(pid->calldata, cfra))
2006                 error = 1;
2007
2008         if (!error) {
2009                 ptcache_file_pointers_init(pf);
2010
2011                 // we have stream reading here
2012                 if (!pid->read_stream(pf, pid->calldata))
2013                         error = 1;
2014         }
2015
2016         ptcache_file_close(pf);
2017         
2018         return error == 0;
2019 }
2020 static int ptcache_read(PTCacheID *pid, int cfra)
2021 {
2022         PTCacheMem *pm = NULL;
2023         int i;
2024         int *index = &i;
2025
2026         /* get a memory cache to read from */
2027         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2028                 pm = ptcache_disk_frame_to_mem(pid, cfra);
2029         }
2030         else {
2031                 pm = pid->cache->mem_cache.first;
2032                 
2033                 while (pm && pm->frame != cfra)
2034                         pm = pm->next;
2035         }
2036
2037         /* read the cache */
2038         if (pm) {
2039                 int totpoint = pm->totpoint;
2040
2041                 if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
2042                         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra));
2043
2044                 BKE_ptcache_mem_pointers_init(pm);
2045
2046                 for (i=0; i<totpoint; i++) {
2047                         if (pm->data_types & (1<<BPHYS_DATA_INDEX))
2048                                 index = pm->cur[BPHYS_DATA_INDEX];
2049
2050                         pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL);
2051                 
2052                         BKE_ptcache_mem_pointers_incr(pm);
2053                 }
2054
2055                 if (pid->read_extra_data && pm->extradata.first)
2056                         pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
2057
2058                 /* clean up temporary memory cache */
2059                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2060                         ptcache_data_free(pm);
2061                         ptcache_extra_free(pm);
2062                         MEM_freeN(pm);
2063                 }
2064         }
2065
2066         return 1;
2067 }
2068 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
2069 {
2070         PTCacheMem *pm = NULL;
2071         int i;
2072         int *index = &i;
2073
2074         /* get a memory cache to read from */
2075         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2076                 pm = ptcache_disk_frame_to_mem(pid, cfra2);
2077         }
2078         else {
2079                 pm = pid->cache->mem_cache.first;
2080                 
2081                 while (pm && pm->frame != cfra2)
2082                         pm = pm->next;
2083         }
2084
2085         /* read the cache */
2086         if (pm) {
2087                 int totpoint = pm->totpoint;
2088
2089                 if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
2090                         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra));
2091
2092                 BKE_ptcache_mem_pointers_init(pm);
2093
2094                 for (i=0; i<totpoint; i++) {
2095                         if (pm->data_types & (1<<BPHYS_DATA_INDEX))
2096                                 index = pm->cur[BPHYS_DATA_INDEX];
2097
2098                         pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL);
2099                         BKE_ptcache_mem_pointers_incr(pm);
2100                 }
2101
2102                 if (pid->interpolate_extra_data && pm->extradata.first)
2103                         pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
2104
2105                 /* clean up temporary memory cache */
2106                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2107                         ptcache_data_free(pm);
2108                         ptcache_extra_free(pm);
2109                         MEM_freeN(pm);
2110                 }
2111         }
2112
2113         return 1;
2114 }
2115 /* reads cache from disk or memory */
2116 /* possible to get old or interpolated result */
2117 int BKE_ptcache_read(PTCacheID *pid, float cfra)
2118 {
2119         int cfrai = (int)floor(cfra), cfra1=0, cfra2=0;
2120         int ret = 0;
2121
2122         /* nothing to read to */
2123         if (pid->totpoint(pid->calldata, cfrai) == 0)
2124                 return 0;
2125
2126         if (pid->cache->flag & PTCACHE_READ_INFO) {
2127                 pid->cache->flag &= ~PTCACHE_READ_INFO;
2128                 ptcache_read(pid, 0);
2129         }
2130
2131         /* first check if we have the actual frame cached */
2132         if (cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai))
2133                 cfra1 = cfrai;
2134
2135         /* no exact cache frame found so try to find cached frames around cfra */
2136         if (cfra1 == 0)
2137                 ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
2138
2139         if (cfra1 == 0 && cfra2 == 0)
2140                 return 0;
2141
2142         /* don't read old cache if already simulated past cached frame */
2143         if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
2144                 return 0;
2145         if (cfra1 && cfra1 == cfra2)
2146                 return 0;
2147
2148         if (cfra1) {
2149                 
2150                 if (pid->read_stream) {
2151                         if (!ptcache_read_stream(pid, cfra1))
2152                                 return 0;
2153                 }
2154                 else if (pid->read_point)
2155                         ptcache_read(pid, cfra1);
2156         }
2157
2158         if (cfra2) {
2159                 
2160                 if (pid->read_stream) {
2161                         if (!ptcache_read_stream(pid, cfra2))
2162                                 return 0;
2163                 }
2164                 else if (pid->read_point) {
2165                         if (cfra1 && cfra2 && pid->interpolate_point)
2166                                 ptcache_interpolate(pid, cfra, cfra1, cfra2);
2167                         else
2168                                 ptcache_read(pid, cfra2);
2169                 }
2170         }
2171
2172         if (cfra1)
2173                 ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT);
2174         else if (cfra2) {
2175                 ret = PTCACHE_READ_OLD;
2176                 pid->cache->simframe = cfra2;
2177         }
2178
2179         cfrai = (int)cfra;
2180         /* clear invalid cache frames so that better stuff can be simulated */
2181         if (pid->cache->flag & PTCACHE_OUTDATED) {
2182                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
2183         }
2184         else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
2185                 if (cfra <= pid->cache->last_exact)
2186                         pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2187
2188                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact));
2189         }
2190
2191         return ret;
2192 }
2193 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
2194 {
2195         PTCacheFile *pf = NULL;
2196         int error = 0;
2197         
2198         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
2199
2200         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
2201
2202         if (pf==NULL) {
2203                 if (G.debug & G_DEBUG)
2204                         printf("Error opening disk cache file for writing\n");
2205                 return 0;
2206         }
2207
2208         pf->data_types = pid->data_types;
2209         pf->totpoint = totpoint;
2210         pf->type = pid->type;
2211         pf->flag = 0;
2212
2213         if (!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)))
2214                 error = 1;
2215
2216         if (!error && pid->write_stream)
2217                 pid->write_stream(pf, pid->calldata);
2218
2219         ptcache_file_close(pf);
2220
2221         if (error && G.debug & G_DEBUG)
2222                 printf("Error writing to disk cache\n");
2223
2224         return error == 0;
2225 }
2226 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
2227 {
2228         PointCache *cache = pid->cache;
2229         PTCacheMem *pm=NULL, *pm2=NULL;
2230         int totpoint = pid->totpoint(pid->calldata, cfra);
2231         int i, error = 0;
2232
2233         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2234
2235         pm->totpoint = pid->totwrite(pid->calldata, cfra);
2236         pm->data_types = cfra ? pid->data_types : pid->info_types;
2237
2238         ptcache_data_alloc(pm);
2239         BKE_ptcache_mem_pointers_init(pm);
2240
2241         if (overwrite) {
2242                 if (cache->flag & PTCACHE_DISK_CACHE) {
2243                         int fra = cfra-1;
2244
2245                         while (fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra))
2246                                 fra--;
2247                         
2248                         pm2 = ptcache_disk_frame_to_mem(pid, fra);
2249                 }
2250                 else
2251                         pm2 = cache->mem_cache.last;
2252         }
2253
2254         if (pid->write_point) {
2255                 for (i=0; i<totpoint; i++) {
2256                         int write = pid->write_point(i, pid->calldata, pm->cur, cfra);
2257                         if (write) {
2258                                 BKE_ptcache_mem_pointers_incr(pm);
2259
2260                                 /* newly born particles have to be copied to previous cached frame */
2261                                 if (overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2))
2262                                         pid->write_point(i, pid->calldata, pm2->cur, cfra);
2263                         }
2264                 }
2265         }
2266
2267         if (pid->write_extra_data)
2268                 pid->write_extra_data(pid->calldata, pm, cfra);
2269
2270         pm->frame = cfra;
2271
2272         if (cache->flag & PTCACHE_DISK_CACHE) {
2273                 error += !ptcache_mem_frame_to_disk(pid, pm);
2274
2275                 // if (pm) /* pm is always set */
2276                 {
2277                         ptcache_data_free(pm);
2278                         ptcache_extra_free(pm);
2279                         MEM_freeN(pm);
2280                 }
2281
2282                 if (pm2) {
2283                         error += !ptcache_mem_frame_to_disk(pid, pm2);
2284                         ptcache_data_free(pm2);
2285                         ptcache_extra_free(pm2);
2286                         MEM_freeN(pm2);
2287                 }
2288         }
2289         else {
2290                 BLI_addtail(&cache->mem_cache, pm);
2291         }
2292
2293         return error;
2294 }
2295 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
2296 {
2297         PointCache *cache = pid->cache;
2298         int ofra = 0, efra = cache->endframe;
2299
2300         /* allways start from scratch on the first frame */
2301         if (cfra && cfra == cache->startframe) {
2302                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
2303                 cache->flag &= ~PTCACHE_REDO_NEEDED;
2304                 return 1;
2305         }
2306
2307         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2308                 if (cfra==0 && cache->startframe > 0)
2309                         return 1;
2310
2311                                 /* find last cached frame */
2312                 while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
2313                         efra--;
2314
2315                 /* find second last cached frame */
2316                 ofra = efra-1;
2317                 while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
2318                         ofra--;
2319         }
2320         else {
2321                 PTCacheMem *pm = cache->mem_cache.last;
2322                 /* don't write info file in memory */
2323                 if (cfra == 0)
2324                         return 0;
2325
2326                 if (pm == NULL)
2327                         return 1;
2328
2329                 efra = pm->frame;
2330                 ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
2331         }
2332
2333         if (efra >= cache->startframe && cfra > efra) {
2334                 if (ofra >= cache->startframe && efra - ofra < cache->step) {
2335                         /* overwrite previous frame */
2336                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
2337                         *overwrite = 1;
2338                 }
2339                 return 1;
2340         }
2341
2342         return 0;
2343 }
2344 /* writes cache to disk or memory */
2345 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
2346 {
2347         PointCache *cache = pid->cache;
2348         int totpoint = pid->totpoint(pid->calldata, cfra);
2349         int overwrite = 0, error = 0;
2350
2351         if (totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
2352                 return 0;
2353
2354         if (ptcache_write_needed(pid, cfra, &overwrite)==0)
2355                 return 0;
2356
2357         if (pid->write_stream) {
2358                 ptcache_write_stream(pid, cfra, totpoint);
2359         }
2360         else if (pid->write_point) {
2361                 error += ptcache_write(pid, cfra, overwrite);
2362         }
2363
2364         /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
2365         if (cfra - cache->last_exact == 1 || cfra == cache->startframe) {
2366                 cache->last_exact = cfra;
2367                 cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2368         }
2369         /* Don't mark skipped when writing info file (frame 0) */
2370         else if (cfra)
2371                 cache->flag |= PTCACHE_FRAMES_SKIPPED;
2372
2373         /* Update timeline cache display */
2374         if (cfra && cache->cached_frames)
2375                 cache->cached_frames[cfra-cache->startframe] = 1;
2376
2377         BKE_ptcache_update_info(pid);
2378
2379         return !error;
2380 }
2381 /* youll need to close yourself after!
2382  * mode - PTCACHE_CLEAR_ALL, 
2383  */
2384
2385 /* Clears & resets */
2386 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
2387 {
2388         unsigned int len; /* store the length of the string */
2389         unsigned int sta, end;
2390
2391         /* mode is same as fopen's modes */
2392         DIR *dir; 
2393         struct dirent *de;
2394         char path[MAX_PTCACHE_PATH];
2395         char filename[MAX_PTCACHE_FILE];
2396         char path_full[MAX_PTCACHE_FILE];
2397         char ext[MAX_PTCACHE_PATH];
2398
2399         if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED)
2400                 return;
2401
2402         if (pid->cache->flag & PTCACHE_IGNORE_CLEAR)
2403                 return;
2404
2405         sta = pid->cache->startframe;
2406         end = pid->cache->endframe;
2407
2408 #ifndef DURIAN_POINTCACHE_LIB_OK
2409         /* don't allow clearing for linked objects */
2410         if (pid->ob->id.lib)
2411                 return;
2412 #endif
2413
2414         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
2415         
2416         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
2417         switch (mode) {
2418         case PTCACHE_CLEAR_ALL:
2419         case PTCACHE_CLEAR_BEFORE:
2420         case PTCACHE_CLEAR_AFTER:
2421                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2422                         ptcache_path(pid, path);
2423                         
2424                         len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
2425                         
2426                         dir = opendir(path);
2427                         if (dir==NULL)
2428                                 return;
2429
2430                         BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
2431                         
2432                         while ((de = readdir(dir)) != NULL) {
2433                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2434                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2435                                                 if (mode == PTCACHE_CLEAR_ALL) {
2436                                                         pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2437                                                         BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2438                                                         BLI_delete(path_full, false, false);
2439                                                 }
2440                                                 else {
2441                                                         /* read the number of the file */
2442                                                         unsigned int frame, len2 = (int)strlen(de->d_name);
2443                                                         char num[7];
2444
2445                                                         if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2446                                                                 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2447                                                                 frame = atoi(num);
2448                                                                 
2449                                                                 if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
2450                                                                     (mode == PTCACHE_CLEAR_AFTER && frame > cfra))
2451                                                                 {
2452                                                                         
2453                                                                         BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2454                                                                         BLI_delete(path_full, false, false);
2455                                                                         if (pid->cache->cached_frames && frame >=sta && frame <= end)
2456                                                                                 pid->cache->cached_frames[frame-sta] = 0;
2457                                                                 }
2458                                                         }
2459                                                 }
2460                                         }
2461                                 }
2462                         }
2463                         closedir(dir);
2464
2465                         if (mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames)
2466                                 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2467                 }
2468                 else {
2469                         PTCacheMem *pm= pid->cache->mem_cache.first;
2470                         PTCacheMem *link= NULL;
2471
2472                         if (mode == PTCACHE_CLEAR_ALL) {
2473                                 /*we want startframe if the cache starts before zero*/
2474                                 pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2475                                 for (; pm; pm=pm->next) {
2476                                         ptcache_data_free(pm);
2477                                         ptcache_extra_free(pm);
2478                                 }
2479                                 BLI_freelistN(&pid->cache->mem_cache);
2480
2481                                 if (pid->cache->cached_frames) 
2482                                         memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2483                         }
2484                         else {
2485                                 while (pm) {
2486                                         if ((mode == PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
2487                                             (mode == PTCACHE_CLEAR_AFTER && pm->frame > cfra))
2488                                         {
2489                                                 link = pm;
2490                                                 if (pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end)
2491                                                         pid->cache->cached_frames[pm->frame-sta] = 0;
2492                                                 ptcache_data_free(pm);
2493                                                 ptcache_extra_free(pm);
2494                                                 pm = pm->next;
2495                                                 BLI_freelinkN(&pid->cache->mem_cache, link);
2496                                         }
2497                                         else
2498                                                 pm = pm->next;
2499                                 }
2500                         }
2501                 }
2502                 break;
2503                 
2504         case PTCACHE_CLEAR_FRAME:
2505                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2506                         if (BKE_ptcache_id_exist(pid, cfra)) {
2507                                 ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
2508                                 BLI_delete(filename, false, false);
2509                         }
2510                 }
2511                 else {
2512                         PTCacheMem *pm = pid->cache->mem_cache.first;
2513
2514                         for (; pm; pm=pm->next) {
2515                                 if (pm->frame == cfra) {
2516                                         ptcache_data_free(pm);
2517                                         ptcache_extra_free(pm);
2518                                         BLI_freelinkN(&pid->cache->mem_cache, pm);
2519                                         break;
2520                                 }
2521                         }
2522                 }
2523                 if (pid->cache->cached_frames && cfra >= sta && cfra <= end)
2524                         pid->cache->cached_frames[cfra-sta] = 0;
2525                 break;
2526         }
2527
2528         BKE_ptcache_update_info(pid);
2529 }
2530 int  BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
2531 {
2532         if (!pid->cache)
2533                 return 0;
2534
2535         if (cfra<pid->cache->startframe || cfra > pid->cache->endframe)
2536                 return 0;
2537
2538         if (pid->cache->cached_frames &&        pid->cache->cached_frames[cfra-pid->cache->startframe]==0)
2539                 return 0;
2540         
2541         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2542                 char filename[MAX_PTCACHE_FILE];
2543                 
2544                 ptcache_filename(pid, filename, cfra, 1, 1);
2545
2546                 return BLI_exists(filename);
2547         }
2548         else {
2549                 PTCacheMem *pm = pid->cache->mem_cache.first;
2550
2551                 for (; pm; pm=pm->next) {
2552                         if (pm->frame==cfra)
2553                                 return 1;
2554                 }
2555                 return 0;
2556         }
2557 }
2558 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
2559 {
2560         /* Object *ob; */ /* UNUSED */
2561         PointCache *cache;
2562         /* float offset; unused for now */
2563         float time, nexttime;
2564
2565         /* TODO: this has to be sorted out once bsystem_time gets redone, */
2566         /*       now caches can handle interpolating etc. too - jahka */
2567
2568         /* time handling for point cache:
2569          * - simulation time is scaled by result of bsystem_time
2570          * - for offsetting time only time offset is taken into account, since
2571          *   that's always the same and can't be animated. a timeoffset which
2572          *   varies over time is not simple to support.
2573          * - field and motion blur offsets are currently ignored, proper solution
2574          *   is probably to interpolate results from two frames for that ..
2575          */
2576
2577         /* ob= pid->ob; */ /* UNUSED */
2578         cache= pid->cache;
2579
2580         if (timescale) {
2581                 time= BKE_scene_frame_get(scene);
2582                 nexttime = BKE_scene_frame_get_from_ctime(scene, CFRA + 1.0f);
2583                 
2584                 *timescale= MAX2(nexttime - time, 0.0f);
2585         }
2586
2587         if (startframe && endframe) {
2588                 *startframe= cache->startframe;
2589                 *endframe= cache->endframe;
2590
2591                 /* TODO: time handling with object offsets and simulated vs. cached
2592                  * particles isn't particularly easy, so for now what you see is what
2593                  * you get. In the future point cache could handle the whole particle
2594                  * system timing. */
2595 #if 0
2596                 if ((ob->partype & PARSLOW)==0) {
2597                         offset= ob->sf;
2598
2599                         *startframe += (int)(offset+0.5f);
2600                         *endframe += (int)(offset+0.5f);
2601                 }
2602 #endif
2603         }
2604
2605         /* verify cached_frames array is up to date */
2606         if (cache->cached_frames) {
2607                 if (MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) {
2608                         MEM_freeN(cache->cached_frames);
2609                         cache->cached_frames = NULL;
2610                 }
2611         }
2612
2613         if (cache->cached_frames==NULL && cache->endframe > cache->startframe) {
2614                 unsigned int sta=cache->startframe;
2615                 unsigned int end=cache->endframe;
2616
2617                 cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array");
2618
2619                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2620                         /* mode is same as fopen's modes */
2621                         DIR *dir; 
2622                         struct dirent *de;
2623                         char path[MAX_PTCACHE_PATH];
2624                         char filename[MAX_PTCACHE_FILE];
2625                         char ext[MAX_PTCACHE_PATH];
2626                         unsigned int len; /* store the length of the string */
2627
2628                         ptcache_path(pid, path);
2629                         
2630                         len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */
2631                         
2632                         dir = opendir(path);
2633                         if (dir==NULL)
2634                                 return;
2635
2636                         BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
2637                         
2638                         while ((de = readdir(dir)) != NULL) {
2639                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2640                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2641                                                 /* read the number of the file */
2642                                                 unsigned int frame, len2 = (int)strlen(de->d_name);
2643                                                 char num[7];
2644
2645                                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2646                                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2647                                                         frame = atoi(num);
2648                                                         
2649                                                         if (frame >= sta && frame <= end)
2650                                                                 cache->cached_frames[frame-sta] = 1;
2651                                                 }
2652                                         }
2653                                 }
2654                         }
2655                         closedir(dir);
2656                 }
2657                 else {
2658                         PTCacheMem *pm= pid->cache->mem_cache.first;
2659
2660                         while (pm) {
2661                                 if (pm->frame >= sta && pm->frame <= end)
2662                                         cache->cached_frames[pm->frame-sta] = 1;
2663                                 pm = pm->next;
2664                         }
2665                 }
2666         }
2667 }
2668 int  BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
2669 {
2670         PointCache *cache;
2671         int reset, clear, after;
2672
2673         if (!pid->cache)
2674                 return 0;
2675
2676         cache= pid->cache;
2677         reset= 0;
2678         clear= 0;
2679         after= 0;
2680
2681         if (mode == PTCACHE_RESET_DEPSGRAPH) {
2682                 if (!(cache->flag & PTCACHE_BAKED)) {
2683
2684                         after= 1;
2685                 }
2686
2687                 cache->flag |= PTCACHE_OUTDATED;
2688         }
2689         else if (mode == PTCACHE_RESET_BAKED) {
2690                 cache->flag |= PTCACHE_OUTDATED;
2691         }
2692         else if (mode == PTCACHE_RESET_OUTDATED) {
2693                 reset = 1;
2694
2695                 if (cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
2696                         clear= 1;
2697                         cache->flag &= ~PTCACHE_OUTDATED;
2698                 }
2699         }
2700
2701         if (reset) {
2702                 BKE_ptcache_invalidate(cache);
2703                 cache->flag &= ~PTCACHE_REDO_NEEDED;
2704
2705                 if (pid->type == PTCACHE_TYPE_CLOTH)
2706                         cloth_free_modifier(pid->calldata);
2707                 else if (pid->type == PTCACHE_TYPE_SOFTBODY)
2708                         sbFreeSimulation(pid->calldata);
2709                 else if (pid->type == PTCACHE_TYPE_PARTICLES)
2710                         psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
2711 #if 0
2712                 else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
2713                         smokeModifier_reset(pid->calldata);
2714                 else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
2715                         smokeModifier_reset_turbulence(pid->calldata);
2716 #endif
2717                 else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT)
2718                         dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata);
2719         }
2720         if (clear)
2721                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2722         else if (after)
2723                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
2724
2725         return (reset || clear || after);
2726 }
2727 int  BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
2728 {
2729         PTCacheID pid;
2730         ParticleSystem *psys;
2731         ModifierData *md;
2732         int reset, skip;
2733
2734         reset= 0;
2735         skip= 0;
2736
2737         if (ob->soft) {
2738                 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
2739                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2740         }
2741
2742         for (psys=ob->particlesystem.first; psys; psys=psys->next) {
2743                 /* children or just redo can be calculated without resetting anything */
2744                 if (psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
2745                         skip = 1;
2746                 /* Baked cloth hair has to be checked too, because we don't want to reset */
2747                 /* particles or cloth in that case -jahka */
2748                 else if (psys->clmd) {
2749                         BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
2750                         if (mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
2751                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2752                         else
2753                                 skip = 1;
2754                 }
2755
2756                 if (skip == 0 && psys->part) {
2757                         BKE_ptcache_id_from_particles(&pid, ob, psys);
2758                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2759                 }
2760         }
2761
2762         for (md=ob->modifiers.first; md; md=md->next) {
2763                 if (md->type == eModifierType_Cloth) {
2764                         BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
2765                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2766                 }
2767                 if (md->type == eModifierType_Smoke) {
2768                         SmokeModifierData *smd = (SmokeModifierData *)md;
2769                         if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
2770                                 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md);
2771                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2772                         }
2773                 }
2774                 if (md->type == eModifierType_DynamicPaint) {
2775                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
2776                         if (pmd->canvas) {
2777                                 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
2778
2779                                 for (; surface; surface=surface->next) {
2780                                         BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
2781                                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2782                                 }
2783                         }
2784                 }
2785         }
2786
2787         if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) {
2788                 if (ob->rigidbody_object)
2789                         ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE;
2790                 BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world);
2791                 /* only flag as outdated, resetting should happen on start frame */
2792                 pid.cache->flag |= PTCACHE_OUTDATED;
2793         }
2794
2795         if (ob->type == OB_ARMATURE)
2796                 BIK_clear_cache(ob->pose);
2797
2798         return reset;
2799 }
2800
2801 /* Use this when quitting blender, with unsaved files */
2802 void BKE_ptcache_remove(void)
2803 {
2804         char path[MAX_PTCACHE_PATH];
2805         char path_full[MAX_PTCACHE_PATH];
2806         int rmdir = 1;
2807         
2808         ptcache_path(NULL, path);
2809
2810         if (BLI_exists(path)) {
2811                 /* The pointcache dir exists? - remove all pointcache */
2812
2813                 DIR *dir; 
2814                 struct dirent *de;
2815
2816                 dir = opendir(path);
2817                 if (dir==NULL)
2818                         return;
2819                 
2820                 while ((de = readdir(dir)) != NULL) {
2821                         if ( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
2822                                 /* do nothing */
2823                         }
2824                         else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
2825                                 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2826                                 BLI_delete(path_full, false, false);
2827                         }
2828                         else {
2829                                 rmdir = 0; /* unknown file, don't remove the dir */
2830                         }
2831                 }
2832
2833                 closedir(dir);
2834         }
2835         else {
2836                 rmdir = 0; /* path dosnt exist  */
2837         }
2838         
2839         if (rmdir) {
2840                 BLI_delete(path, true, false);
2841         }
2842 }
2843
2844 /* Point Cache handling */
2845
2846 PointCache *BKE_ptcache_add(ListBase *ptcaches)
2847 {
2848         PointCache *cache;
2849
2850         cache= MEM_callocN(sizeof(PointCache), "PointCache");
2851         cache->startframe= 1;
2852         cache->endframe= 250;
2853         cache->step= 10;
2854         cache->index = -1;
2855
2856         BLI_addtail(ptcaches, cache);
2857
2858         return cache;
2859 }
2860
2861 void BKE_ptcache_free_mem(ListBase *mem_cache)
2862 {
2863         PTCacheMem *pm = mem_cache->first;
2864
2865         if (pm) {
2866                 for (; pm; pm=pm->next) {
2867                         ptcache_data_free(pm);
2868                         ptcache_extra_free(pm);
2869                 }
2870
2871                 BLI_freelistN(mem_cache);
2872         }
2873 }
2874 void BKE_ptcache_free(PointCache *cache)
2875 {
2876         BKE_ptcache_free_mem(&cache->mem_cache);
2877         if (cache->edit && cache->free_edit)
2878                 cache->free_edit(cache->edit);
2879         if (cache->cached_frames)
2880                 MEM_freeN(cache->cached_frames);
2881         MEM_freeN(cache);
2882 }
2883 void BKE_ptcache_free_list(ListBase *ptcaches)
2884 {
2885         PointCache *cache = ptcaches->first;
2886
2887         while (cache) {
2888                 BLI_remlink(ptcaches, cache);
2889                 BKE_ptcache_free(cache);
2890                 cache = ptcaches->first;
2891         }
2892 }
2893
2894 static PointCache *ptcache_copy(PointCache *cache, int copy_data)
2895 {
2896         PointCache *ncache;
2897
2898         ncache= MEM_dupallocN(cache);
2899
2900         ncache->mem_cache.first = NULL;
2901         ncache->mem_cache.last = NULL;
2902
2903         if (copy_data == FALSE) {
2904                 ncache->mem_cache.first = NULL;
2905                 ncache->mem_cache.last = NULL;
2906                 ncache->cached_frames = NULL;
2907
2908                 /* flag is a mix of user settings and simulator/baking state */
2909                 ncache->flag= ncache->flag & (PTCACHE_DISK_CACHE|PTCACHE_EXTERNAL|PTCACHE_IGNORE_LIBPATH);
2910                 ncache->simframe= 0;
2911         }
2912         else {
2913                 PTCacheMem *pm;
2914
2915                 for (pm = cache->mem_cache.first; pm; pm = pm->next) {
2916                         PTCacheMem *pmn = MEM_dupallocN(pm);
2917                         int i;
2918
2919                         for (i = 0; i < BPHYS_TOT_DATA; i++) {
2920                                 if (pmn->data[i])
2921                                         pmn->data[i] = MEM_dupallocN(pm->data[i]);
2922                         }
2923
2924                         BKE_ptcache_mem_pointers_init(pm);
2925
2926                         BLI_addtail(&ncache->mem_cache, pmn);
2927                 }
2928
2929                 if (ncache->cached_frames)
2930                         ncache->cached_frames = MEM_dupallocN(cache->cached_frames);
2931         }
2932
2933         /* hmm, should these be copied over instead? */
2934         ncache->edit = NULL;
2935
2936         return ncache;
2937 }
2938
2939 /* returns first point cache */
2940 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old, int copy_data)
2941 {
2942         PointCache *cache = ptcaches_old->first;
2943
2944         ptcaches_new->first = ptcaches_new->last = NULL;
2945
2946         for (; cache; cache=cache->next)
2947                 BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data));
2948
2949         return ptcaches_new->first;
2950 }
2951
2952 /* Disabled this code; this is being called on scene_update_tagged, and that in turn gets called on 
2953  * every user action changing stuff, and then it runs a complete bake??? (ton) */
2954
2955 /* Baking */
2956 void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
2957 {
2958         PTCacheBaker baker;
2959
2960         baker.bake=0;
2961         baker.break_data=NULL;
2962         baker.break_test=NULL;
2963         baker.pid=NULL;
2964         baker.progressbar=NULL;
2965         baker.progressend=NULL;
2966         baker.progresscontext=NULL;
2967         baker.render=0;
2968         baker.anim_init = 0;
2969         baker.main=bmain;
2970         baker.scene=scene;
2971         baker.quick_step=scene->physics_settings.quick_cache_step;
2972
2973         BKE_ptcache_bake(&baker);
2974 }
2975
2976 /* Simulation thread, no need for interlocks as data written in both threads
2977  * are only unitary integers (I/O assumed to be atomic for them) */
2978 typedef struct {
2979         int break_operation;
2980         int thread_ended;
2981         int endframe;
2982         int step;
2983         int *cfra_ptr;
2984         Main *main;
2985         Scene *scene;
2986 } ptcache_bake_data;
2987
2988 static void ptcache_dt_to_str(char *str, double dtime)
2989 {
2990         if (dtime > 60.0) {
2991                 if (dtime > 3600.0)
2992                         sprintf(str, "%ih %im %is", (int)(dtime/3600), ((int)(dtime/60))%60, ((int)dtime) % 60);
2993                 else
2994                         sprintf(str, "%im %is", ((int)(dtime/60))%60, ((int)dtime) % 60);
2995         }
2996         else
2997                 sprintf(str, "%is", ((int)dtime) % 60);
2998 }
2999
3000 static void *ptcache_bake_thread(void *ptr)
3001 {
3002         int use_timer = FALSE, sfra, efra;
3003         double stime, ptime, ctime, fetd;
3004         char run[32], cur[32], etd[32];
3005
3006         ptcache_bake_data *data = (ptcache_bake_data*)ptr;
3007
3008         stime = ptime = PIL_check_seconds_timer();
3009         sfra = *data->cfra_ptr;
3010         efra = data->endframe;
3011
3012         for (; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) {
3013                 BKE_scene_update_for_newframe(data->main, data->scene, data->scene->lay);
3014                 if (G.background) {
3015                         printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe);
3016                 }
3017                 else {
3018                         ctime = PIL_check_seconds_timer();
3019
3020                         fetd = (ctime-ptime)*(efra-*data->cfra_ptr)/data->step;
3021
3022                         if (use_timer || fetd > 60.0) {
3023                                 use_timer = TRUE;
3024
3025                                 ptcache_dt_to_str(cur, ctime-ptime);
3026                                 ptcache_dt_to_str(run, ctime-stime);
3027                                 ptcache_dt_to_str(etd, fetd);
3028
3029                                 printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r", run, *data->cfra_ptr-sfra+1, efra-sfra+1, ctime-ptime, etd);
3030                         }
3031                         ptime = ctime;
3032                 }
3033         }
3034
3035         if (use_timer) {
3036                 ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime);
3037                 printf("Bake %s %s (%i frames simulated).\n", (data->break_operation ? "canceled after" : "finished in"), run, *data->cfra_ptr-sfra);
3038         }
3039
3040         data->thread_ended = TRUE;
3041         return NULL;
3042 }
3043
3044 /* if bake is not given run simulations to current frame */
3045 void BKE_ptcache_bake(PTCacheBaker *baker)
3046 {
3047         Main *bmain = baker->main;
3048         Scene *scene = baker->scene;
3049         Scene *sce_iter; /* SETLOOPER macro only */
3050         Base *base;
3051         ListBase pidlist;
3052         PTCacheID *pid = baker->pid;
3053         PointCache *cache = NULL;
3054         float frameleno = scene->r.framelen;
3055         int cfrao = CFRA;
3056         int startframe = MAXFRAME;
3057         int bake = baker->bake;
3058         int render = baker->render;
3059         ListBase threads;
3060         ptcache_bake_data thread_data;
3061         int progress, old_progress;
3062         
3063         thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA;
3064         thread_data.step = baker->quick_step;
3065         thread_data.cfra_ptr = &CFRA;
3066         thread_data.scene = baker->scene;
3067         thread_data.main = baker->main;
3068
3069         G.is_break = FALSE;
3070
3071         /* set caches to baking mode and figure out start frame */
3072         if (pid) {
3073                 /* cache/bake a single object */
3074                 cache = pid->cache;
3075                 if ((cache->flag & PTCACHE_BAKED)==0) {
3076                         if (pid->type==PTCACHE_TYPE_PARTICLES) {
3077                                 ParticleSystem *psys= pid->calldata;
3078
3079                                 /* a bit confusing, could make this work better in the UI */
3080                                 if (psys->part->type == PART_EMITTER)
3081                                         psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
3082                         }
3083                         else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
3084                                 /* get all pids from the object and search for smoke low res */
3085                                 ListBase pidlist2;
3086                                 PTCacheID *pid2;
3087                                 BKE_ptcache_ids_from_object(&pidlist2, pid->ob, scene, MAX_DUPLI_RECUR);
3088                                 for (pid2=pidlist2.first; pid2; pid2=pid2->next) {
3089                                         if (pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
3090                                                 if (pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) {
3091                                                         if (bake || pid2->cache->flag & PTCACHE_REDO_NEEDED)
3092                                                                 BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0);
3093                                                         if (bake) {
3094                                                                 pid2->cache->flag |= PTCACHE_BAKING;
3095                                                                 pid2->cache->flag &= ~PTCACHE_BAKED;
3096                                                         }
3097                                                 }
3098                                         }
3099                                 }
3100                                 BLI_freelistN(&pidlist2);
3101                         }
3102
3103                         if (bake || cache->flag & PTCACHE_REDO_NEEDED)
3104                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3105
3106                         startframe = MAX2(cache->last_exact, cache->startframe);
3107
3108                         if (bake) {
3109                                 thread_data.endframe = cache->endframe;
3110                                 cache->flag |= PTCACHE_BAKING;
3111                         }
3112                         else {
3113                                 thread_data.endframe = MIN2(thread_data.endframe, cache->endframe);
3114                         }
3115
3116                         cache->flag &= ~PTCACHE_BAKED;
3117                 }
3118         }
3119         else {
3120                 for (SETLOOPER(scene, sce_iter, base)) {
3121                         /* cache/bake everything in the scene */
3122                         BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
3123
3124                         for (pid=pidlist.first; pid; pid=pid->next) {
3125                                 cache = pid->cache;
3126                                 if ((cache->flag & PTCACHE_BAKED)==0) {
3127                                         if (pid->type==PTCACHE_TYPE_PARTICLES) {
3128                                                 ParticleSystem *psys = (ParticleSystem*)pid->calldata;
3129                                                 /* skip hair & keyed particles */
3130                                                 if (psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
3131                                                         continue;
3132
3133                                                 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
3134                                         }
3135
3136                                         if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) &&
3137                                             (render || bake))
3138                                         {
3139                                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3140                                         }
3141
3142                                         startframe = MIN2(startframe, cache->startframe);