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