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