CTX_wm_reports needs to return NULL when wm.manager is NULL (this happens in backgrou...
[blender.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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
46 #include "BKE_cloth.h"
47 #include "BKE_depsgraph.h"
48 #include "BKE_global.h"
49 #include "BKE_library.h"
50 #include "BKE_main.h"
51 #include "BKE_modifier.h"
52 #include "BKE_object.h"
53 #include "BKE_particle.h"
54 #include "BKE_pointcache.h"
55 #include "BKE_scene.h"
56 #include "BKE_smoke.h"
57 #include "BKE_softbody.h"
58 #include "BKE_utildefines.h"
59
60 #include "BLI_blenlib.h"
61
62 #include "smoke_API.h"
63
64 /* needed for directory lookup */
65 #ifndef WIN32
66   #include <dirent.h>
67 #else
68   #include "BLI_winstuff.h"
69 #endif
70
71 /* untitled blend's need getpid for a unique name */
72 #ifdef WIN32
73 #include <process.h>
74 #else
75 #include <unistd.h>
76 #endif
77
78 #ifdef _WIN32
79 #ifndef snprintf
80 #define snprintf _snprintf
81 #endif
82 #endif
83
84 static void ptcache_data_to(void **data, int type, int index, void *to);
85 static void ptcache_data_from(void **data, int type, void *from);
86
87 /* Common functions */
88 static int ptcache_read_basic_header(PTCacheFile *pf)
89 {
90         int error=0;
91
92         /* Custom functions should read these basic elements too! */
93         if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp))
94                 error = 1;
95         
96         if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp))
97                 error = 1;
98
99         return !error;
100 }
101 static int ptcache_write_basic_header(PTCacheFile *pf)
102 {
103         /* Custom functions should write these basic elements too! */
104         if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp))
105                 return 0;
106         
107         if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp))
108                 return 0;
109
110         return 1;
111 }
112 /* Softbody functions */
113 static int ptcache_write_softbody(int index, void *soft_v, void **data)
114 {
115         SoftBody *soft= soft_v;
116         BodyPoint *bp = soft->bpoint + index;
117
118         ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos);
119         ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec);
120
121         return 1;
122 }
123 static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data)
124 {
125         SoftBody *soft= soft_v;
126         BodyPoint *bp = soft->bpoint + index;
127
128         if(old_data) {
129                 memcpy(bp->pos, data, 3 * sizeof(float));
130                 memcpy(bp->vec, data + 3, 3 * sizeof(float));
131         }
132         else {
133                 ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos);
134                 ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
135         }
136 }
137 static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
138 {
139         SoftBody *soft= soft_v;
140         BodyPoint *bp = soft->bpoint + index;
141         ParticleKey keys[4];
142         float dfra;
143
144         if(cfra1 == cfra2)
145                 return;
146
147         VECCOPY(keys[1].co, bp->pos);
148         VECCOPY(keys[1].vel, bp->vec);
149
150         if(old_data) {
151                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
152                 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
153         }
154         else
155                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
156
157         dfra = cfra2 - cfra1;
158
159         VecMulf(keys[1].vel, dfra);
160         VecMulf(keys[2].vel, dfra);
161
162         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
163
164         VecMulf(keys->vel, 1.0f / dfra);
165
166         VECCOPY(bp->pos, keys->co);
167         VECCOPY(bp->vec, keys->vel);
168 }
169 static int ptcache_totpoint_softbody(void *soft_v)
170 {
171         SoftBody *soft= soft_v;
172         return soft->totpoint;
173 }
174 /* Particle functions */
175 static int ptcache_write_particle(int index, void *psys_v, void **data)
176 {
177         ParticleSystem *psys= psys_v;
178         ParticleData *pa = psys->particles + index;
179         float times[3] = {pa->time, pa->dietime, pa->lifetime};
180
181         if(data[BPHYS_DATA_INDEX]) {
182                 int step = psys->pointcache->step;
183                 /* No need to store unborn or died particles */
184                 if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time)
185                         return 0;
186         }
187         
188         ptcache_data_from(data, BPHYS_DATA_INDEX, &index);
189         ptcache_data_from(data, BPHYS_DATA_LOCATION, pa->state.co);
190         ptcache_data_from(data, BPHYS_DATA_VELOCITY, pa->state.vel);
191         ptcache_data_from(data, BPHYS_DATA_ROTATION, pa->state.rot);
192         ptcache_data_from(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
193         ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size);
194         ptcache_data_from(data, BPHYS_DATA_TIMES, times);
195
196         if(pa->boid)
197                 ptcache_data_from(data, BPHYS_DATA_TIMES, &pa->boid);
198
199         return 1;
200 }
201 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
202 {
203         ptcache_data_to(data, BPHYS_DATA_LOCATION, index, key->co);
204         ptcache_data_to(data, BPHYS_DATA_VELOCITY, index, key->vel);
205         ptcache_data_to(data, BPHYS_DATA_ROTATION, index, key->rot);
206         ptcache_data_to(data, BPHYS_DATA_AVELOCITY, index, key->ave);
207         key->time = time;
208 }
209 static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data)
210 {
211         ParticleSystem *psys= psys_v;
212         ParticleData *pa = psys->particles + index;
213
214         if(cfra > pa->state.time)
215                 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
216
217         if(old_data){
218                 /* old format cache */
219                 memcpy(&pa->state, old_data, sizeof(ParticleKey));
220                 return;
221         }
222
223         BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
224
225         if(data[BPHYS_DATA_SIZE])
226                 ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size);
227         
228         if(data[BPHYS_DATA_TIMES]) {
229                 float times[3];
230                 ptcache_data_to(data, BPHYS_DATA_TIMES, 0, &times);
231                 pa->time = times[0];
232                 pa->dietime = times[1];
233                 pa->lifetime = times[2];
234         }
235
236         if(pa->boid)
237                 ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &pa->boid);
238
239         /* determine velocity from previous location */
240         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
241                 if(cfra > pa->prev_state.time) {
242                         VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co);
243                         VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
244                 }
245                 else {
246                         VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co);
247                         VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
248                 }
249         }
250
251         /* determine rotation from velocity */
252         if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
253                 vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot);
254         }
255 }
256 static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
257 {
258         ParticleSystem *psys= psys_v;
259         ParticleData *pa = psys->particles + index;
260         ParticleKey keys[4];
261         float dfra;
262
263         cfra = MIN2(cfra, pa->dietime);
264         cfra1 = MIN2(cfra1, pa->dietime);
265         cfra2 = MIN2(cfra2, pa->dietime);
266
267         if(cfra1 == cfra2)
268                 return;
269
270         memcpy(keys+1, &pa->state, sizeof(ParticleKey));
271         if(old_data)
272                 memcpy(keys+2, old_data, sizeof(ParticleKey));
273         else
274                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
275
276         dfra = cfra2 - cfra1;
277
278         VecMulf(keys[1].vel, dfra / frs_sec);
279         VecMulf(keys[2].vel, dfra / frs_sec);
280
281         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
282         QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
283
284         VecMulf(pa->state.vel, frs_sec / dfra);
285
286         pa->state.time = cfra;
287 }
288
289 static int ptcache_totpoint_particle(void *psys_v)
290 {
291         ParticleSystem *psys = psys_v;
292         return psys->totpart;
293 }
294 static int ptcache_totwrite_particle(void *psys_v)
295 {
296         ParticleSystem *psys = psys_v;
297         int totwrite = 0;
298
299         /* TODO for later */
300         //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0) {
301         //      ParticleData *pa= psys->particles;
302         //      int p, step = psys->pointcache->step;
303
304         //      for(p=0; p<psys->totpart; p++,pa++)
305         //              totwrite += (pa->time - step > pa->state.time || pa->dietime + step > pa->state.time);
306         //}
307         //else
308                 totwrite= psys->totpart;
309
310         return totwrite;
311 }
312
313 /* Cloth functions */
314 static int ptcache_write_cloth(int index, void *cloth_v, void **data)
315 {
316         ClothModifierData *clmd= cloth_v;
317         Cloth *cloth= clmd->clothObject;
318         ClothVertex *vert = cloth->verts + index;
319
320         ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x);
321         ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v);
322         ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst);
323
324         return 1;
325 }
326 static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data)
327 {
328         ClothModifierData *clmd= cloth_v;
329         Cloth *cloth= clmd->clothObject;
330         ClothVertex *vert = cloth->verts + index;
331         
332         if(old_data) {
333                 memcpy(vert->x, data, 3 * sizeof(float));
334                 memcpy(vert->xconst, data + 3, 3 * sizeof(float));
335                 memcpy(vert->v, data + 6, 3 * sizeof(float));
336         }
337         else {
338                 ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x);
339                 ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v);
340                 ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst);
341         }
342 }
343 static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
344 {
345         ClothModifierData *clmd= cloth_v;
346         Cloth *cloth= clmd->clothObject;
347         ClothVertex *vert = cloth->verts + index;
348         ParticleKey keys[4];
349         float dfra;
350
351         if(cfra1 == cfra2)
352                 return;
353
354         VECCOPY(keys[1].co, vert->x);
355         VECCOPY(keys[1].vel, vert->v);
356
357         if(old_data) {
358                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
359                 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
360         }
361         else
362                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
363
364         dfra = cfra2 - cfra1;
365
366         VecMulf(keys[1].vel, dfra);
367         VecMulf(keys[2].vel, dfra);
368
369         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
370
371         VecMulf(keys->vel, 1.0f / dfra);
372
373         VECCOPY(vert->x, keys->co);
374         VECCOPY(vert->v, keys->vel);
375
376         /* should vert->xconst be interpolated somehow too? - jahka */
377 }
378
379 static int ptcache_totpoint_cloth(void *cloth_v)
380 {
381         ClothModifierData *clmd= cloth_v;
382         return clmd->clothObject->numverts;
383 }
384
385 /* Creating ID's */
386 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
387 {
388         ParticleSystemModifierData *psmd;
389         ModifierData *md;
390         int a;
391
392         memset(pid, 0, sizeof(PTCacheID));
393
394         pid->ob= ob;
395         pid->calldata= sb;
396         pid->type= PTCACHE_TYPE_SOFTBODY;
397         pid->cache= sb->pointcache;
398         pid->cache_ptr= &sb->pointcache;
399         pid->ptcaches= &sb->ptcaches;
400         pid->totpoint= pid->totwrite= ptcache_totpoint_softbody;
401
402         pid->write_elem= ptcache_write_softbody;
403         pid->write_stream = NULL;
404         pid->read_stream = NULL;
405         pid->read_elem= ptcache_read_softbody;
406         pid->interpolate_elem= ptcache_interpolate_softbody;
407
408         pid->write_header= ptcache_write_basic_header;
409         pid->read_header= ptcache_read_basic_header;
410
411         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
412         pid->info_types= 0;
413
414         if(sb->particles) {
415                 psmd= psys_get_modifier(ob, sb->particles);
416                 pid->stack_index= modifiers_indexInObject(ob, (ModifierData*)psmd);
417         }
418         else {
419                 for(a=0, md=ob->modifiers.first; md; md=md->next, a++) {
420                         if(md->type == eModifierType_Softbody) {
421                                 pid->stack_index = a;
422                                 break;
423                         }
424                 }
425         }
426 }
427
428 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
429 {
430         ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
431
432         memset(pid, 0, sizeof(PTCacheID));
433
434         pid->ob= ob;
435         pid->calldata= psys;
436         pid->type= PTCACHE_TYPE_PARTICLES;
437         pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)psmd);
438         pid->cache= psys->pointcache;
439         pid->cache_ptr= &psys->pointcache;
440         pid->ptcaches= &psys->ptcaches;
441
442         pid->write_elem= ptcache_write_particle;
443         pid->write_stream = NULL;
444         pid->read_stream = NULL;
445         pid->read_elem= ptcache_read_particle;
446         pid->interpolate_elem= ptcache_interpolate_particle;
447
448         pid->totpoint= ptcache_totpoint_particle;
449         pid->totwrite= ptcache_totwrite_particle;
450
451         pid->write_header= ptcache_write_basic_header;
452         pid->read_header= ptcache_read_basic_header;
453
454         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
455
456         /* TODO for later */
457         //if((psys->part->flag & (PART_UNBORN|PART_DIED))==0)
458         //      pid->data_types|= (1<<BPHYS_DATA_INDEX);
459
460         if(psys->part->phystype == PART_PHYS_BOIDS)
461                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
462
463         if(psys->part->rotmode || psys->part->avemode)
464                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
465
466         if(psys->part->flag & PART_ROT_DYN)
467                 pid->data_types|= (1<<BPHYS_DATA_ROTATION);
468
469         pid->info_types= (1<<BPHYS_DATA_TIMES);
470 }
471
472 /* Smoke functions */
473 static int ptcache_totpoint_smoke(void *smoke_v)
474 {
475         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
476         SmokeDomainSettings *sds = smd->domain;
477         
478         if(sds->fluid)
479         {
480                 return sds->res[0]*sds->res[1]*sds->res[2];
481         }
482         else
483                 return 0;
484 }
485
486 // forward decleration
487 static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size);
488
489 static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v)
490 {
491         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
492         SmokeDomainSettings *sds = smd->domain;
493         
494         if(sds->fluid)
495         {
496                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
497                 float *dens, *densold, *heat, *heatold, *vx, *vy, *vz;
498                 
499                 smoke_export(sds->fluid, &dens, &densold, &heat, &heatold, &vx, &vy, &vz);
500                 
501                 ptcache_file_write(pf, dens, res, sizeof(float));
502                 ptcache_file_write(pf, densold, res, sizeof(float));
503                 ptcache_file_write(pf, heat, res, sizeof(float));
504                 ptcache_file_write(pf, heatold, res, sizeof(float));
505                 ptcache_file_write(pf, vx, res, sizeof(float));
506                 ptcache_file_write(pf, vy, res, sizeof(float));
507                 ptcache_file_write(pf, vz, res, sizeof(float));
508                 
509                 return 1;
510         }
511
512         return 0;
513 }
514
515 // forward decleration
516 static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size);
517
518 static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v)
519 {
520         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
521         SmokeDomainSettings *sds = smd->domain;
522         
523         if(sds->fluid)
524         {
525                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
526                 float *dens, *densold, *heat, *heatold, *vx, *vy, *vz;
527                 
528                 smoke_export(sds->fluid, &dens, &densold, &heat, &heatold, &vx, &vy, &vz);
529
530                 ptcache_file_read(pf, dens, res, sizeof(float));
531                 ptcache_file_read(pf, densold, res, sizeof(float));
532                 ptcache_file_read(pf, heat, res, sizeof(float));
533                 ptcache_file_read(pf, heatold, res, sizeof(float));
534                 ptcache_file_read(pf, vx, res, sizeof(float));
535                 ptcache_file_read(pf, vy, res, sizeof(float));
536                 ptcache_file_read(pf, vz, res, sizeof(float));
537                 
538         }
539 }
540 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd, int num)
541 {
542         SmokeDomainSettings *sds = smd->domain;
543
544         memset(pid, 0, sizeof(PTCacheID));
545
546         pid->ob= ob;
547         pid->calldata= smd;
548         
549         // if(num == 0)
550         pid->type= PTCACHE_TYPE_SMOKE_DOMAIN_LOW;
551         // else if(num == 1)
552         //      pid->type= PTCACHE_TYPE_SMOKE_DOMAIN_HIGH;
553
554         pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)smd);
555
556         pid->cache= sds->point_cache;
557         pid->cache_ptr= &sds->point_cache;
558         pid->ptcaches= &sds->ptcaches;
559
560         
561         pid->totpoint= pid->totwrite= ptcache_totpoint_smoke;
562
563         pid->write_elem= NULL;
564         pid->read_elem= NULL;
565         pid->read_stream = ptcache_read_smoke;
566         pid->write_stream = ptcache_write_smoke;
567         pid->interpolate_elem= NULL;
568
569         pid->write_header= ptcache_write_basic_header;
570         pid->read_header= ptcache_read_basic_header;
571
572         pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy
573         pid->info_types= 0;
574 }
575
576 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
577 {
578         memset(pid, 0, sizeof(PTCacheID));
579
580         pid->ob= ob;
581         pid->calldata= clmd;
582         pid->type= PTCACHE_TYPE_CLOTH;
583         pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)clmd);
584         pid->cache= clmd->point_cache;
585         pid->cache_ptr= &clmd->point_cache;
586         pid->ptcaches= &clmd->ptcaches;
587         pid->totpoint= pid->totwrite= ptcache_totpoint_cloth;
588
589         pid->write_elem= ptcache_write_cloth;
590         pid->write_stream = NULL;
591         pid->read_stream = NULL;
592         pid->read_elem= ptcache_read_cloth;
593         pid->interpolate_elem= ptcache_interpolate_cloth;
594
595         pid->write_header= ptcache_write_basic_header;
596         pid->read_header= ptcache_read_basic_header;
597
598         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
599         pid->info_types= 0;
600 }
601
602 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
603 {
604         PTCacheID *pid;
605         ParticleSystem *psys;
606         ModifierData *md;
607
608         lb->first= lb->last= NULL;
609
610         if(ob->soft) {
611                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
612                 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
613                 BLI_addtail(lb, pid);
614         }
615
616         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
617                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
618                 BKE_ptcache_id_from_particles(pid, ob, psys);
619                 BLI_addtail(lb, pid);
620
621                 if(psys->soft) {
622                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
623                         BKE_ptcache_id_from_softbody(pid, ob, psys->soft);
624                         BLI_addtail(lb, pid);
625                 }
626         }
627
628         for(md=ob->modifiers.first; md; md=md->next) {
629                 if(md->type == eModifierType_Cloth) {
630                         pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
631                         BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
632                         BLI_addtail(lb, pid);
633                 }
634                 /*
635                 // enabled on next commit 
636                 if(md->type == eModifierType_Smoke) {
637                         SmokeModifierData *smd = (SmokeModifierData *)md;
638                         if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
639                         {
640                                 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
641                                 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md, 0);
642                                 BLI_addtail(lb, pid);
643                         }
644                 }
645                 */
646         }
647 }
648
649
650 /* File handling */
651
652 /*      Takes an Object ID and returns a unique name
653         - id: object id
654         - cfra: frame for the cache, can be negative
655         - stack_index: index in the modifier stack. we can have cache for more then one stack_index
656 */
657
658 #define MAX_PTCACHE_PATH FILE_MAX
659 #define MAX_PTCACHE_FILE ((FILE_MAXDIR+FILE_MAXFILE)*2)
660
661 static int ptcache_path(PTCacheID *pid, char *filename)
662 {
663         Library *lib;
664         size_t i;
665
666         lib= (pid)? pid->ob->id.lib: NULL;
667
668         if(pid->cache->flag & PTCACHE_EXTERNAL) {
669                 strcpy(filename, pid->cache->path);
670                 return BLI_add_slash(filename); /* new strlen() */
671         }
672         else if (G.relbase_valid || lib) {
673                 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */
674                 char *blendfilename;
675
676                 blendfilename= (lib)? lib->filename: G.sce;
677
678                 BLI_split_dirfile_basic(blendfilename, NULL, file);
679                 i = strlen(file);
680                 
681                 /* remove .blend */
682                 if (i > 6)
683                         file[i-6] = '\0';
684                 
685                 snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
686                 BLI_convertstringcode(filename, blendfilename);
687                 return BLI_add_slash(filename); /* new strlen() */
688         }
689         
690         /* use the temp path. this is weak but better then not using point cache at all */
691         /* btempdir is assumed to exist and ALWAYS has a trailing slash */
692         snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", btempdir, abs(getpid()));
693         
694         return BLI_add_slash(filename); /* new strlen() */
695 }
696
697 static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
698 {
699         int len=0;
700         char *idname;
701         char *newname;
702         filename[0] = '\0';
703         newname = filename;
704         
705         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
706         
707         /* start with temp dir */
708         if (do_path) {
709                 len = ptcache_path(pid, filename);
710                 newname += len;
711         }
712         if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
713                 idname = (pid->ob->id.name+2);
714                 /* convert chars to hex so they are always a valid filename */
715                 while('\0' != *idname) {
716                         snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
717                         newname+=2;
718                         len += 2;
719                 }
720         }
721         else {
722                 int temp = (int)strlen(pid->cache->name); 
723                 strcpy(newname, pid->cache->name); 
724                 newname+=temp;
725                 len += temp;
726         }
727
728         if (do_ext) {
729                 if(pid->cache->flag & PTCACHE_EXTERNAL) {
730                         if(pid->cache->index >= 0)
731                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
732                         else
733                                 snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
734                 }
735                 else {
736                         snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
737                 }
738                 len += 16;
739         }
740         
741         return len; /* make sure the above string is always 16 chars */
742 }
743
744 /* youll need to close yourself after! */
745 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
746 {
747         PTCacheFile *pf;
748         FILE *fp = NULL;
749         char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
750
751         /* don't allow writing for linked objects */
752         if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
753                 return NULL;
754
755         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
756         
757         BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
758
759         if (mode==PTCACHE_FILE_READ) {
760                 if (!BLI_exists(filename)) {
761                         return NULL;
762                 }
763                 fp = fopen(filename, "rb");
764         } else if (mode==PTCACHE_FILE_WRITE) {
765                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
766                 fp = fopen(filename, "wb");
767         }
768
769         if (!fp)
770                 return NULL;
771         
772         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
773         pf->fp= fp;
774         
775         return pf;
776 }
777
778 static void ptcache_file_close(PTCacheFile *pf)
779 {
780         fclose(pf->fp);
781         MEM_freeN(pf);
782 }
783
784 static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size)
785 {
786         return (fread(f, size, tot, pf->fp) == tot);
787 }
788 static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size)
789 {
790         return (fwrite(f, size, tot, pf->fp) == tot);
791 }
792 static int ptcache_file_read_data(PTCacheFile *pf)
793 {
794         int i;
795
796         for(i=0; i<BPHYS_TOT_DATA; i++) {
797                 if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
798                         return 0;
799         }
800         
801         return 1;
802 }
803 static int ptcache_file_write_data(PTCacheFile *pf)
804 {               
805         int i;
806
807         for(i=0; i<BPHYS_TOT_DATA; i++) {
808                 if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
809                         return 0;
810         }
811         
812         return 1;
813 }
814 static int ptcache_file_read_header_begin(PTCacheFile *pf)
815 {
816         int error=0;
817         char bphysics[8];
818         
819         pf->data_types = 0;
820         
821         if(fread(bphysics, sizeof(char), 8, pf->fp) != 8)
822                 error = 1;
823         
824         if(!error && strncmp(bphysics, "BPHYSICS", 8))
825                 error = 1;
826
827         if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp))
828                 error = 1;
829         
830         /* if there was an error set file as it was */
831         if(error)
832                 fseek(pf->fp, 0, SEEK_SET);
833
834         return !error;
835 }
836
837
838 static int ptcache_file_write_header_begin(PTCacheFile *pf)
839 {
840         char *bphysics = "BPHYSICS";
841         
842         if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
843                 return 0;
844
845         if(!fwrite(&pf->type, sizeof(int), 1, pf->fp))
846                 return 0;
847         
848         return 1;
849 }
850
851
852 /* Data pointer handling */
853 int BKE_ptcache_data_size(int data_type)
854 {
855         switch(data_type) {
856                 case BPHYS_DATA_INDEX:
857                         return sizeof(int);
858                 case BPHYS_DATA_LOCATION:
859                 case BPHYS_DATA_VELOCITY:
860                 case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */
861                 case BPHYS_DATA_TIMES:
862                         return 3 * sizeof(float);
863                 case BPHYS_DATA_ROTATION:
864                         return 4 * sizeof(float);
865                 case BPHYS_DATA_SIZE:
866                         return sizeof(float);
867                 case BPHYS_DATA_BOIDS:
868                         return sizeof(BoidData);
869                 default:
870                         return 0;
871         }
872 }
873 static void ptcache_data_to(void **data, int type, int index, void *to)
874 {
875         if(data[type]) {
876                 if(index)
877                         memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type));
878                 else
879                         memcpy(to, data[type], BKE_ptcache_data_size(type));
880         }
881 }
882
883 static void ptcache_data_from(void **data, int type, void *from)
884 {
885         if(data[type])
886                 memcpy(data[type], from, BKE_ptcache_data_size(type));
887 }
888
889 static void ptcache_file_init_pointers(PTCacheFile *pf)
890 {
891         int data_types = pf->data_types;
892
893         pf->cur[BPHYS_DATA_INDEX] =             data_types & (1<<BPHYS_DATA_INDEX) ?            &pf->data.index : NULL;
894         pf->cur[BPHYS_DATA_LOCATION] =  data_types & (1<<BPHYS_DATA_LOCATION) ?         &pf->data.loc   : NULL;
895         pf->cur[BPHYS_DATA_VELOCITY] =  data_types & (1<<BPHYS_DATA_VELOCITY) ?         &pf->data.vel   : NULL;
896         pf->cur[BPHYS_DATA_ROTATION] =  data_types & (1<<BPHYS_DATA_ROTATION) ?         &pf->data.rot   : NULL;
897         pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ?        &pf->data.ave   : NULL;
898         pf->cur[BPHYS_DATA_SIZE] =              data_types & (1<<BPHYS_DATA_SIZE)       ?               &pf->data.size  : NULL;
899         pf->cur[BPHYS_DATA_TIMES] =             data_types & (1<<BPHYS_DATA_TIMES) ?            &pf->data.times : NULL;
900         pf->cur[BPHYS_DATA_BOIDS] =             data_types & (1<<BPHYS_DATA_BOIDS) ?            &pf->data.boids : NULL;
901 }
902
903 static void ptcache_mem_init_pointers(PTCacheMem *pm)
904 {
905         int data_types = pm->data_types;
906         int i;
907
908         for(i=0; i<BPHYS_TOT_DATA; i++)
909                 pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL;
910 }
911
912 static void ptcache_mem_incr_pointers(PTCacheMem *pm)
913 {
914         int i;
915
916         for(i=0; i<BPHYS_TOT_DATA; i++) {
917                 if(pm->cur[i])
918                         pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i);
919         }
920 }
921 static void ptcache_alloc_data(PTCacheMem *pm)
922 {
923         int data_types = pm->data_types;
924         int totpoint = pm->totpoint;
925         int i;
926
927         for(i=0; i<BPHYS_TOT_DATA; i++) {
928                 if(data_types & (1<<i))
929                         pm->data[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data");
930         }
931 }
932 static void ptcache_free_data(void *data[])
933 {
934         int i;
935
936         for(i=0; i<BPHYS_TOT_DATA; i++) {
937                 if(data[i])
938                         MEM_freeN(data[i]);
939         }
940 }
941 static void ptcache_copy_data(void *from[], void *to[])
942 {
943         int i;
944         for(i=0; i<BPHYS_TOT_DATA; i++) {
945                 if(from[i])
946                         memcpy(to[i], from[i], BKE_ptcache_data_size(i));
947         }
948 }
949
950
951
952 static int ptcache_pid_old_elemsize(PTCacheID *pid)
953 {
954         if(pid->type==PTCACHE_TYPE_SOFTBODY)
955                 return 6 * sizeof(float);
956         else if(pid->type==PTCACHE_TYPE_PARTICLES)
957                 return sizeof(ParticleKey);
958         else if(pid->type==PTCACHE_TYPE_CLOTH)
959                 return 9 * sizeof(float);
960
961         return 0;
962 }
963
964 /* reads cache from disk or memory */
965 /* possible to get old or interpolated result */
966 int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec)
967 {
968         PTCacheFile *pf=NULL, *pf2=NULL;
969         PTCacheMem *pm=NULL, *pm2=NULL;
970         float old_data1[14], old_data2[14];
971         int cfrai = (int)cfra;
972         int old_elemsize = ptcache_pid_old_elemsize(pid);
973         int i, incr = old_elemsize / sizeof(float);
974
975         int cfra1 = 0, cfra2 = 0;
976         int totpoint = 0, totpoint2 = 0;
977         int *index = &i, *index2 = &i;
978         int use_old = 0, old_frame;
979
980         int ret = 0, error = 0;
981
982         /* nothing to read to */
983         if(pid->totpoint(pid->calldata) == 0)
984                 return 0;
985
986         if(pid->cache->flag & PTCACHE_READ_INFO) {
987                 pid->cache->flag &= ~PTCACHE_READ_INFO;
988                 BKE_ptcache_read_cache(pid, 0, frs_sec);
989         }
990
991
992         /* first check if we have the actual frame cached */
993         if(cfra == (float)cfrai) {
994                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
995                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
996                 }
997                 else {
998                         pm = pid->cache->mem_cache.first;
999
1000                         for(; pm; pm=pm->next) {
1001                                 if(pm->frame == cfrai)
1002                                         break;
1003                         }
1004                 }
1005         }
1006
1007         /* no exact cache frame found so try to find cached frames around cfra */
1008         if(!pm && !pf) {
1009                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1010                         pf=NULL;
1011                         while(cfrai > pid->cache->startframe && !pf) {
1012                                 cfrai--;
1013                                 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1014                                 cfra1 = cfrai;
1015                         }
1016
1017                         old_frame = cfrai;
1018
1019                         cfrai = (int)cfra;
1020                         while(cfrai < pid->cache->endframe && !pf2) {
1021                                 cfrai++;
1022                                 pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1023                                 cfra2 = cfrai;
1024                         }
1025
1026                         if(pf && !pf2) {
1027                                 pf2 = pf;
1028                                 pf = NULL;
1029                         }
1030                 }
1031                 else if(pid->cache->mem_cache.first){
1032                         pm = pid->cache->mem_cache.first;
1033
1034                         while(pm->next && pm->next->frame < cfra)
1035                                 pm= pm->next;
1036
1037                         if(pm) {
1038                                 old_frame = pm->frame;
1039                                 cfra1 = pm->frame;
1040                         }
1041
1042                         pm2 = pid->cache->mem_cache.last;
1043
1044                         if(pm2 && pm2->frame < cfra)
1045                                 pm2 = NULL;
1046                         else {
1047                                 while(pm2->prev && pm2->prev->frame > cfra)
1048                                         pm2= pm2->prev;
1049
1050                                 if(pm2)
1051                                         cfra2 = pm2->frame;
1052                         }
1053
1054                         if(pm && !pm2) {
1055                                 pm2 = pm;
1056                                 pm = NULL;
1057                         }
1058                 }
1059         }
1060
1061         if(!pm && !pm2 && !pf && !pf2)
1062                 return 0;
1063
1064         if(pm) {
1065                 ptcache_mem_init_pointers(pm);
1066                 totpoint = pm->totpoint;
1067                 index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
1068         }
1069         if(pm2) {
1070                 ptcache_mem_init_pointers(pm2);
1071                 totpoint2 = pm2->totpoint;
1072                 index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
1073         }
1074         if(pf) {
1075                 if(ptcache_file_read_header_begin(pf)) {
1076                         if(pf->type != pid->type) {
1077                                 /* todo report error */
1078                                 ptcache_file_close(pf);
1079                                 pf = NULL;
1080                         }
1081                         else if(pid->read_header(pf)) {
1082                                 ptcache_file_init_pointers(pf);
1083                                 totpoint = pf->totpoint;
1084                                 index = pf->data_types & BPHYS_DATA_INDEX ? &pf->data.index : &i;
1085                         }
1086                 }
1087                 else {
1088                         /* fall back to old cache file format */
1089                         use_old = 1;
1090                         totpoint = pid->totpoint(pid->calldata);
1091                 }
1092         }
1093         if(pf2) {
1094                 if(ptcache_file_read_header_begin(pf2)) {
1095                         if(pf2->type != pid->type) {
1096                                 /* todo report error */
1097                                 ptcache_file_close(pf2);
1098                                 pf2 = NULL;
1099                         }
1100                         else if(pid->read_header(pf2)) {
1101                                 ptcache_file_init_pointers(pf2);
1102                                 totpoint2 = pf2->totpoint;
1103                                 index2 = pf->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i;
1104                         }
1105                 }
1106                 else {
1107                         /* fall back to old cache file format */
1108                         use_old = 1;
1109                         totpoint2 = pid->totpoint(pid->calldata);
1110                 }
1111         }
1112
1113         /* don't read old cache if allready simulated past cached frame */
1114         if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe)
1115                 error = 1;
1116         if(cfra1 && cfra1==cfra2)
1117                 error = 1;
1118
1119         if(!error) 
1120         {
1121                 if(pf && pid->read_stream) {
1122                         if(totpoint != pid->totpoint(pid->calldata))
1123                                 error = 1;
1124                         else
1125                         {
1126                                 // we have stream writing here
1127                                 pid->read_stream(pf, pid->calldata);
1128                         }
1129                 }
1130         }
1131
1132         totpoint = MIN2(totpoint, pid->totpoint(pid->calldata));
1133
1134         if(!error) 
1135         {       
1136                 for(i=0; i<totpoint; i++) {
1137                         /* read old cache file format */
1138                         if(use_old) {
1139                                 if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize))
1140                                         pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1);
1141                                 else
1142                                         { error = 1; break; }
1143                         }
1144                         else {
1145                                 if(pid->read_elem && (pm || ptcache_file_read_data(pf)))
1146                                         pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL);
1147                                 else
1148                                         { error = 1; break; }
1149                         }
1150
1151                         if(pm) {
1152                                 ptcache_mem_incr_pointers(pm);
1153                                 index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
1154                         }
1155                 }
1156         }
1157
1158         if(!error) 
1159         {
1160                 if(pf2 && pid->read_stream) {
1161                         if(totpoint2 != pid->totpoint(pid->calldata))
1162                                 error = 1;
1163                         else
1164                         {
1165                                 // we have stream writing here
1166                                 pid->read_stream(pf2, pid->calldata);
1167                         }
1168                 }
1169         }
1170
1171         totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata));
1172
1173         if(!error) 
1174         {
1175                 for(i=0; i<totpoint2; i++) {
1176                         /* read old cache file format */
1177                         if(use_old) {
1178                                 if(pid->read_elem && ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) {
1179                                         if(!pf && pf2)
1180                                                 pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2);
1181                                         else if(pid->interpolate_elem)
1182                                                 pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2);
1183                                         else
1184                                         { error = 1; break; }
1185                                 }
1186                                 else
1187                                         { error = 1; break; }
1188                         }
1189                         else {
1190                                 if(pid->read_elem && (pm2 || ptcache_file_read_data(pf2))) {
1191                                         if((!pf && pf2) || (!pm && pm2))
1192                                                 pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL);
1193                                         else if(pid->interpolate_elem)
1194                                                 pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL);
1195                                         else
1196                                         { error = 1; break; }
1197                                 }
1198                                 else
1199                                         { error = 1; break; }
1200                         }
1201
1202                         if(pm2) {
1203                                 ptcache_mem_incr_pointers(pm2);
1204                                 index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
1205                         }
1206                 }
1207         }
1208
1209         if(pm || pf)
1210                 ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT;
1211         else if(pm2 || pf2) {
1212                 ret = PTCACHE_READ_OLD;
1213                 pid->cache->simframe = old_frame;
1214         }
1215
1216         if(pf) {
1217                 ptcache_file_close(pf);
1218                 pf = NULL;
1219         }
1220
1221         if(pf2) {
1222                 ptcache_file_close(pf2);
1223                 pf = NULL;
1224         }
1225
1226         if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
1227                 cfrai = (int)cfra;
1228                 /* clear invalid cache frames so that better stuff can be simulated */
1229                 if(pid->cache->flag & PTCACHE_OUTDATED) {
1230                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
1231                 }
1232                 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
1233                         if(cfra <= pid->cache->last_exact)
1234                                 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1235
1236                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact));
1237                 }
1238         }
1239
1240         return (error ? 0 : ret);
1241 }
1242 /* TODO for later */
1243 //static void ptcache_make_index_array(PTCacheMem *pm, int totpoint)
1244 //{
1245 //      int i, *index;
1246 //
1247 //      if(pm->index_array) {
1248 //              MEM_freeN(pm->index_array);
1249 //              pm->index_array = NULL;
1250 //      }
1251 //
1252 //      if(!pm->data[BPHYS_DATA_INDEX])
1253 //              return;
1254 //
1255 //      pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array");
1256 //      index = pm->data[BPHYS_DATA_INDEX];
1257 //
1258 //      for(i=0; i<pm->totpoint; i++, index++)
1259 //              pm->index_array[*index] = i;
1260 //}
1261 /* writes cache to disk or memory */
1262 int BKE_ptcache_write_cache(PTCacheID *pid, int cfra)
1263 {
1264         PointCache *cache = pid->cache;
1265         PTCacheFile *pf= NULL;
1266         int elemsize = ptcache_pid_old_elemsize(pid);
1267         int i, incr = elemsize / sizeof(float);
1268         int totpoint = pid->totpoint(pid->calldata);
1269         int add = 0, overwrite = 0;
1270
1271         if(totpoint == 0 || cfra < 0
1272                 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
1273                 return 0;
1274
1275         if(cache->flag & PTCACHE_DISK_CACHE) {
1276                 int efra = cache->endframe;
1277
1278                 if(cfra==0)
1279                         add = 1;
1280                 /* allways start from scratch on the first frame */
1281                 else if(cfra == cache->startframe) {
1282                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1283                         cache->flag &= ~PTCACHE_REDO_NEEDED;
1284                         add = 1;
1285                 }
1286                 else {
1287                         int ofra;
1288                         /* find last cached frame */
1289                         while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
1290                                 efra--;
1291
1292                         /* find second last cached frame */
1293                         ofra = efra-1;
1294                         while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
1295                                 ofra--;
1296
1297                         if(efra >= cache->startframe && cfra > efra) {
1298                                 if(ofra >= cache->startframe && efra - ofra < cache->step)
1299                                         overwrite = 1;
1300                                 else
1301                                         add = 1;
1302                         }
1303                 }
1304
1305                 if(add || overwrite) {
1306                         if(overwrite)
1307                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
1308
1309                         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
1310                         if(!pf)
1311                                 return 0;
1312
1313                         pf->type = pid->type;
1314                         pf->totpoint = cfra ? totpoint : pid->totwrite(pid->calldata);
1315                         pf->data_types = cfra ? pid->data_types : pid->info_types;
1316
1317                         if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
1318                                 ptcache_file_close(pf);
1319                                 return 0;
1320                         }
1321
1322                         ptcache_file_init_pointers(pf);
1323
1324                         if(pf && pid->write_stream) {
1325                                 // we have stream writing here
1326                                 pid->write_stream(pf, pid->calldata);
1327                         }
1328                         else
1329                                 for(i=0; i<totpoint; i++) {
1330                                         if(pid->write_elem && pid->write_elem(i, pid->calldata, pf->cur))
1331                                                 if(!ptcache_file_write_data(pf)) {
1332                                                         ptcache_file_close(pf);
1333                                                         return 0;
1334                                                 }
1335                                 }
1336                 }
1337         }
1338         else {
1339                 PTCacheMem *pm;
1340                 PTCacheMem *pm2;
1341
1342                 pm2 = cache->mem_cache.first;
1343                 
1344                 /* don't write info file in memory */
1345                 if(cfra==0)
1346                         return 1;
1347                 /* allways start from scratch on the first frame */
1348                 if(cfra == cache->startframe) {
1349                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1350                         cache->flag &= ~PTCACHE_REDO_NEEDED;
1351                         add = 1;
1352                 }
1353                 else if (cache->mem_cache.last) {
1354                         pm2 = cache->mem_cache.last;
1355
1356                         if(pm2 && cfra > pm2->frame) {
1357                                 if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
1358                                         overwrite = 1;
1359                                 else
1360                                         add = 1;
1361                         }
1362                 }
1363                 else
1364                         add = 1;
1365
1366                 if(add || overwrite) {
1367                         if(overwrite)
1368                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame);
1369
1370                         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1371
1372                         pm->totpoint = pid->totwrite(pid->calldata);
1373                         pm->data_types = cfra ? pid->data_types : pid->info_types;
1374
1375                         ptcache_alloc_data(pm);
1376                         ptcache_mem_init_pointers(pm);
1377
1378                         for(i=0; i<totpoint; i++) {
1379                                 if(pid->write_elem && pid->write_elem(i, pid->calldata, pm->cur))
1380                                         ptcache_mem_incr_pointers(pm);
1381                         }
1382                         //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
1383
1384                         pm->frame = cfra;
1385                         BLI_addtail(&cache->mem_cache, pm);
1386                 }
1387         }
1388
1389         if(add || overwrite) {
1390                 if(cfra - cache->last_exact == 1
1391                         || cfra == cache->startframe) {
1392                         cache->last_exact = cfra;
1393                         cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1394                 }
1395                 else
1396                         cache->flag |= PTCACHE_FRAMES_SKIPPED;
1397         }
1398         
1399         if(pf)
1400                 ptcache_file_close(pf);
1401
1402         BKE_ptcache_update_info(pid);
1403
1404         return 1;
1405 }
1406 /* youll need to close yourself after!
1407  * mode - PTCACHE_CLEAR_ALL, 
1408
1409 */
1410 /* Clears & resets */
1411 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
1412 {
1413         int len; /* store the length of the string */
1414
1415         /* mode is same as fopen's modes */
1416         DIR *dir; 
1417         struct dirent *de;
1418         char path[MAX_PTCACHE_PATH];
1419         char filename[MAX_PTCACHE_FILE];
1420         char path_full[MAX_PTCACHE_FILE];
1421         char ext[MAX_PTCACHE_PATH];
1422
1423         if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
1424                 return;
1425
1426         /* don't allow clearing for linked objects */
1427         if(pid->ob->id.lib)
1428                 return;
1429
1430         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
1431         
1432         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
1433         switch (mode) {
1434         case PTCACHE_CLEAR_ALL:
1435         case PTCACHE_CLEAR_BEFORE:      
1436         case PTCACHE_CLEAR_AFTER:
1437                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1438                         ptcache_path(pid, path);
1439                         
1440                         len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
1441                         
1442                         dir = opendir(path);
1443                         if (dir==NULL)
1444                                 return;
1445
1446                         snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
1447                         
1448                         while ((de = readdir(dir)) != NULL) {
1449                                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
1450                                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
1451                                                 if (mode == PTCACHE_CLEAR_ALL) {
1452                                                         pid->cache->last_exact = 0;
1453                                                         BLI_join_dirfile(path_full, path, de->d_name);
1454                                                         BLI_delete(path_full, 0, 0);
1455                                                 } else {
1456                                                         /* read the number of the file */
1457                                                         int frame, len2 = (int)strlen(de->d_name);
1458                                                         char num[7];
1459
1460                                                         if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
1461                                                                 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
1462                                                                 frame = atoi(num);
1463                                                                 
1464                                                                 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) || 
1465                                                                 (mode==PTCACHE_CLEAR_AFTER && frame > cfra)     ) {
1466                                                                         
1467                                                                         BLI_join_dirfile(path_full, path, de->d_name);
1468                                                                         BLI_delete(path_full, 0, 0);
1469                                                                 }
1470                                                         }
1471                                                 }
1472                                         }
1473                                 }
1474                         }
1475                         closedir(dir);
1476                 }
1477                 else {
1478                         PTCacheMem *pm= pid->cache->mem_cache.first;
1479                         PTCacheMem *link= NULL;
1480
1481                         if(mode == PTCACHE_CLEAR_ALL) {
1482                                 pid->cache->last_exact = 0;
1483                                 for(; pm; pm=pm->next)
1484                                         ptcache_free_data(pm->data);
1485                                 BLI_freelistN(&pid->cache->mem_cache);
1486                         } else {
1487                                 while(pm) {
1488                                         if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra)     || 
1489                                         (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
1490                                                 link = pm;
1491                                                 pm = pm->next;
1492                                                 ptcache_free_data(link->data);
1493                                                 BLI_freelinkN(&pid->cache->mem_cache, link);
1494                                         }
1495                                         else
1496                                                 pm = pm->next;
1497                                 }
1498                         }
1499                 }
1500                 break;
1501                 
1502         case PTCACHE_CLEAR_FRAME:
1503                 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1504                         if(BKE_ptcache_id_exist(pid, cfra)) {
1505                                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
1506                                 BLI_delete(filename, 0, 0);
1507                         }
1508                 }
1509                 else {
1510                         PTCacheMem *pm = pid->cache->mem_cache.first;
1511
1512                         for(; pm; pm=pm->next) {
1513                                 if(pm->frame == cfra) {
1514                                         ptcache_free_data(pm->data);
1515                                         BLI_freelinkN(&pid->cache->mem_cache, pm);
1516                                         break;
1517                                 }
1518                         }
1519                 }
1520                 break;
1521         }
1522
1523         BKE_ptcache_update_info(pid);
1524 }
1525
1526 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
1527 {
1528         if(!pid->cache)
1529                 return 0;
1530         
1531         if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1532                 char filename[MAX_PTCACHE_FILE];
1533                 
1534                 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
1535
1536                 return BLI_exists(filename);
1537         }
1538         else {
1539                 PTCacheMem *pm = pid->cache->mem_cache.first;
1540
1541                 for(; pm; pm=pm->next) {
1542                         if(pm->frame==cfra)
1543                                 return 1;
1544                 }
1545                 return 0;
1546         }
1547 }
1548
1549 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
1550 {
1551         Object *ob;
1552         PointCache *cache;
1553         float offset, time, nexttime;
1554
1555         /* TODO: this has to be sorter out once bsystem_time gets redone, */
1556         /*       now caches can handle interpolating etc. too - jahka */
1557
1558         /* time handling for point cache:
1559          * - simulation time is scaled by result of bsystem_time
1560          * - for offsetting time only time offset is taken into account, since
1561          *   that's always the same and can't be animated. a timeoffset which
1562          *   varies over time is not simpe to support.
1563          * - field and motion blur offsets are currently ignored, proper solution
1564          *   is probably to interpolate results from two frames for that ..
1565          */
1566
1567         ob= pid->ob;
1568         cache= pid->cache;
1569
1570         if(timescale) {
1571                 time= bsystem_time(scene, ob, cfra, 0.0f);
1572                 nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f);
1573
1574                 *timescale= MAX2(nexttime - time, 0.0f);
1575         }
1576
1577         if(startframe && endframe) {
1578                 *startframe= cache->startframe;
1579                 *endframe= cache->endframe;
1580
1581                 // XXX ipoflag is depreceated - old animation system stuff
1582                 if (/*(ob->ipoflag & OB_OFFS_PARENT) &&*/ (ob->partype & PARSLOW)==0) {
1583                         offset= give_timeoffset(ob);
1584
1585                         *startframe += (int)(offset+0.5f);
1586                         *endframe += (int)(offset+0.5f);
1587                 }
1588         }
1589 }
1590
1591 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
1592 {
1593         PointCache *cache;
1594         int reset, clear, after;
1595
1596         if(!pid->cache)
1597                 return 0;
1598
1599         cache= pid->cache;
1600         reset= 0;
1601         clear= 0;
1602         after= 0;
1603
1604         if(mode == PTCACHE_RESET_DEPSGRAPH) {
1605                 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
1606                         if(cache->flag & PTCACHE_QUICK_CACHE)
1607                                 clear= 1;
1608
1609                         after= 1;
1610                 }
1611
1612                 cache->flag |= PTCACHE_OUTDATED;
1613         }
1614         else if(mode == PTCACHE_RESET_BAKED) {
1615                 if(!BKE_ptcache_get_continue_physics()) {
1616                         reset= 1;
1617                         clear= 1;
1618                 }
1619                 else
1620                         cache->flag |= PTCACHE_OUTDATED;
1621         }
1622         else if(mode == PTCACHE_RESET_OUTDATED) {
1623                 reset = 1;
1624
1625                 if(cache->flag & PTCACHE_OUTDATED)
1626                         if(!(cache->flag & PTCACHE_BAKED))
1627                                 clear= 1;
1628         }
1629
1630         if(reset) {
1631                 cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
1632                 cache->simframe= 0;
1633                 cache->last_exact= 0;
1634
1635                 if(pid->type == PTCACHE_TYPE_CLOTH)
1636                         cloth_free_modifier(pid->ob, pid->calldata);
1637                 else if(pid->type == PTCACHE_TYPE_SOFTBODY)
1638                         sbFreeSimulation(pid->calldata);
1639                 else if(pid->type == PTCACHE_TYPE_PARTICLES)
1640                         psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
1641                 else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN_LOW)
1642                         smokeModifier_reset(pid->calldata);
1643         }
1644         if(clear)
1645                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1646         else if(after)
1647                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
1648
1649         return (reset || clear || after);
1650 }
1651
1652 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
1653 {
1654         PTCacheID pid;
1655         ParticleSystem *psys;
1656         ModifierData *md;
1657         int reset, skip;
1658
1659         reset= 0;
1660         skip= 0;
1661
1662         if(ob->soft) {
1663                 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
1664                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1665         }
1666
1667         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1668                 /* Baked softbody hair has to be checked first, because we don't want to reset */
1669                 /* particles or softbody in that case -jahka */
1670                 if(psys->soft) {
1671                         BKE_ptcache_id_from_softbody(&pid, ob, psys->soft);
1672                         if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
1673                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1674                         else
1675                                 skip = 1;
1676                 }
1677                 else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
1678                         skip = 1;
1679
1680                 if(skip == 0) {
1681                         BKE_ptcache_id_from_particles(&pid, ob, psys);
1682                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1683                 }
1684         }
1685
1686         for(md=ob->modifiers.first; md; md=md->next) {
1687                 if(md->type == eModifierType_Cloth) {
1688                         BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
1689                         reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1690                 }
1691                 /*
1692                 // enabled on next commit 
1693                 if(md->type == eModifierType_Smoke) {
1694                         SmokeModifierData *smd = (SmokeModifierData *)md;
1695                         if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
1696                         {
1697                                 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md, 0);
1698                                 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
1699                         }
1700                 }
1701                 */
1702         }
1703
1704         return reset;
1705 }
1706
1707 /* Use this when quitting blender, with unsaved files */
1708 void BKE_ptcache_remove(void)
1709 {
1710         char path[MAX_PTCACHE_PATH];
1711         char path_full[MAX_PTCACHE_PATH];
1712         int rmdir = 1;
1713         
1714         ptcache_path(NULL, path);
1715
1716         if (BLI_exist(path)) {
1717                 /* The pointcache dir exists? - remove all pointcache */
1718
1719                 DIR *dir; 
1720                 struct dirent *de;
1721
1722                 dir = opendir(path);
1723                 if (dir==NULL)
1724                         return;
1725                 
1726                 while ((de = readdir(dir)) != NULL) {
1727                         if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
1728                                 /* do nothing */
1729                         } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
1730                                 BLI_join_dirfile(path_full, path, de->d_name);
1731                                 BLI_delete(path_full, 0, 0);
1732                         } else {
1733                                 rmdir = 0; /* unknown file, dont remove the dir */
1734                         }
1735                 }
1736
1737                 closedir(dir);
1738         } else { 
1739                 rmdir = 0; /* path dosnt exist  */
1740         }
1741         
1742         if (rmdir) {
1743                 BLI_delete(path, 1, 0);
1744         }
1745 }
1746
1747 /* Continuous Interaction */
1748
1749 static int CONTINUE_PHYSICS = 0;
1750
1751 void BKE_ptcache_set_continue_physics(Scene *scene, int enable)
1752 {
1753         Object *ob;
1754
1755         if(CONTINUE_PHYSICS != enable) {
1756                 CONTINUE_PHYSICS = enable;
1757
1758                 if(CONTINUE_PHYSICS == 0) {
1759                         for(ob=G.main->object.first; ob; ob=ob->id.next)
1760                                 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
1761                                         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
1762                 }
1763         }
1764 }
1765
1766 int BKE_ptcache_get_continue_physics()
1767 {
1768         return CONTINUE_PHYSICS;
1769 }
1770
1771 /* Point Cache handling */
1772
1773 PointCache *BKE_ptcache_add(ListBase *ptcaches)
1774 {
1775         PointCache *cache;
1776
1777         cache= MEM_callocN(sizeof(PointCache), "PointCache");
1778         cache->startframe= 1;
1779         cache->endframe= 250;
1780         cache->step= 10;
1781
1782         BLI_addtail(ptcaches, cache);
1783
1784         return cache;
1785 }
1786
1787 void BKE_ptache_free_mem(PointCache *cache)
1788 {
1789         PTCacheMem *pm = cache->mem_cache.first;
1790
1791         if(pm) {
1792                 for(; pm; pm=pm->next) {
1793                         ptcache_free_data(pm->data);
1794                         if(pm->index_array)
1795                                 MEM_freeN(pm->index_array);
1796                 }
1797
1798                 BLI_freelistN(&cache->mem_cache);
1799         }
1800 }
1801 void BKE_ptcache_free(PointCache *cache)
1802 {
1803         BKE_ptache_free_mem(cache);
1804         MEM_freeN(cache);
1805 }
1806 void BKE_ptcache_free_list(ListBase *ptcaches)
1807 {
1808         PointCache *cache = ptcaches->first;
1809
1810         for(; cache; cache=cache->next)
1811                 BKE_ptache_free_mem(cache);
1812
1813         BLI_freelistN(ptcaches);
1814 }
1815
1816 static PointCache *ptcache_copy(PointCache *cache)
1817 {
1818         PointCache *ncache;
1819
1820         ncache= MEM_dupallocN(cache);
1821
1822         /* hmm, should these be copied over instead? */
1823         ncache->mem_cache.first = NULL;
1824         ncache->mem_cache.last = NULL;
1825
1826         ncache->flag= 0;
1827         ncache->simframe= 0;
1828
1829         return ncache;
1830 }
1831 /* returns first point cache */
1832 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old)
1833 {
1834         PointCache *cache = ptcaches_old->first;
1835
1836         ptcaches_new->first = ptcaches_new->last = NULL;
1837
1838         for(; cache; cache=cache->next)
1839                 BLI_addtail(ptcaches_new, ptcache_copy(cache));
1840
1841         return ptcaches_new->first;
1842 }
1843
1844
1845 /* Baking */
1846 static int count_quick_cache(Scene *scene, int *quick_step)
1847 {
1848         Base *base = scene->base.first;
1849         PTCacheID *pid;
1850         ListBase pidlist;
1851         int autocache_count= 0;
1852
1853         for(base = scene->base.first; base; base = base->next) {
1854                 if(base->object) {
1855                         BKE_ptcache_ids_from_object(&pidlist, base->object);
1856
1857                         for(pid=pidlist.first; pid; pid=pid->next) {
1858                                 if((pid->cache->flag & PTCACHE_BAKED)
1859                                         || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
1860                                         continue;
1861
1862                                 if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
1863                                         if(!autocache_count)
1864                                                 *quick_step = pid->cache->step;
1865                                         else
1866                                                 *quick_step = MIN2(*quick_step, pid->cache->step);
1867
1868                                         autocache_count++;
1869                                 }
1870                         }
1871
1872                         BLI_freelistN(&pidlist);
1873                 }
1874         }
1875
1876         return autocache_count;
1877 }
1878 void BKE_ptcache_quick_cache_all(Scene *scene)
1879 {
1880         PTCacheBaker baker;
1881
1882         baker.bake=0;
1883         baker.break_data=NULL;
1884         baker.break_test=NULL;
1885         baker.pid=NULL;
1886         baker.progressbar=NULL;
1887         baker.progresscontext=NULL;
1888         baker.render=0;
1889         baker.anim_init = 0;
1890         baker.scene=scene;
1891
1892         if(count_quick_cache(scene, &baker.quick_step))
1893                 BKE_ptcache_make_cache(&baker);
1894 }
1895
1896 /* if bake is not given run simulations to current frame */
1897 void BKE_ptcache_make_cache(PTCacheBaker* baker)
1898 {
1899         Scene *scene = baker->scene;
1900         Base *base;
1901         ListBase pidlist;
1902         PTCacheID *pid = baker->pid;
1903         PointCache *cache;
1904         float frameleno = scene->r.framelen;
1905         int cfrao = CFRA;
1906         int startframe = MAXFRAME;
1907         int endframe = baker->anim_init ? scene->r.sfra : CFRA;
1908         int bake = baker->bake;
1909         int render = baker->render;
1910         int step = baker->quick_step;
1911
1912         G.afbreek = 0;
1913
1914         /* set caches to baking mode and figure out start frame */
1915         if(pid) {
1916                 /* cache/bake a single object */
1917                 cache = pid->cache;
1918                 if((cache->flag & PTCACHE_BAKED)==0) {
1919                         if(pid->type==PTCACHE_TYPE_PARTICLES)
1920                                 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
1921
1922                         if(bake || cache->flag & PTCACHE_REDO_NEEDED)
1923                                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1924
1925                         startframe = MAX2(cache->last_exact, cache->startframe);
1926
1927                         if(bake) {
1928                                 endframe = cache->endframe;
1929                                 cache->flag |= PTCACHE_BAKING;
1930                         }
1931                         else {
1932                                 endframe = MIN2(endframe, cache->endframe);
1933                         }
1934
1935                         cache->flag &= ~PTCACHE_BAKED;
1936                 }
1937         }
1938         else for(base=scene->base.first; base; base= base->next) {
1939                 /* cache/bake everything in the scene */
1940                 BKE_ptcache_ids_from_object(&pidlist, base->object);
1941
1942                 for(pid=pidlist.first; pid; pid=pid->next) {
1943                         cache = pid->cache;
1944                         if((cache->flag & PTCACHE_BAKED)==0) {
1945                                 if(pid->type==PTCACHE_TYPE_PARTICLES) {
1946                                         ParticleSystem *psys = (ParticleSystem*)pid->calldata;
1947                                         /* skip hair & keyed particles */
1948                                         if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
1949                                                 continue;
1950
1951                                         psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
1952                                 }
1953
1954                                 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
1955                                         && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
1956                                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
1957
1958                                 startframe = MIN2(startframe, cache->startframe);
1959
1960                                 if(bake || render) {
1961                                         cache->flag |= PTCACHE_BAKING;
1962
1963                                         if(bake)
1964                                                 endframe = MAX2(endframe, cache->endframe);
1965                                 }
1966
1967                                 cache->flag &= ~PTCACHE_BAKED;
1968
1969                         }
1970                 }
1971                 BLI_freelistN(&pidlist);
1972         }
1973
1974         CFRA= startframe;
1975         scene->r.framelen = 1.0;
1976
1977         for(; CFRA <= endframe; CFRA+=step) {
1978                 int prog;
1979
1980                 if(bake)
1981                         prog = (int)(100.0f * (float)(CFRA - startframe)/(float)(endframe-startframe));
1982                 else
1983                         prog = CFRA;
1984
1985                 /* NOTE: baking should not redraw whole ui as this slows things down */
1986                 if(baker->progressbar)
1987                         baker->progressbar(baker->progresscontext, prog);
1988                 
1989                 scene_update_for_newframe(scene, scene->lay);
1990
1991                 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
1992                 if(baker->break_test && baker->break_test(baker->break_data))
1993                         break;
1994         }
1995
1996         /* clear baking flag */
1997         if(pid) {
1998                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
1999                 cache->flag |= PTCACHE_SIMULATION_VALID;
2000                 if(bake) {
2001                         cache->flag |= PTCACHE_BAKED;
2002                         /* write info file */
2003                         if(cache->flag & PTCACHE_DISK_CACHE)
2004                                 BKE_ptcache_write_cache(pid, 0);
2005                 }
2006         }
2007         else for(base=scene->base.first; base; base= base->next) {
2008                 BKE_ptcache_ids_from_object(&pidlist, base->object);
2009
2010                 for(pid=pidlist.first; pid; pid=pid->next) {
2011                         /* skip hair particles */
2012                         if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
2013                                 continue;
2014                 
2015                         cache = pid->cache;
2016
2017                         if(step > 1)
2018                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
2019                         else
2020                                 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
2021
2022                         cache->flag |= PTCACHE_SIMULATION_VALID;
2023
2024                         if(bake) {
2025                                 cache->flag |= PTCACHE_BAKED;
2026                                 if(cache->flag & PTCACHE_DISK_CACHE)
2027                                         BKE_ptcache_write_cache(pid, 0);
2028                         }
2029                 }
2030                 BLI_freelistN(&pidlist);
2031         }
2032
2033         scene->r.framelen = frameleno;
2034         CFRA = cfrao;
2035
2036         if(bake) /* already on cfra unless baking */
2037                 scene_update_for_newframe(scene, scene->lay);
2038
2039         /* TODO: call redraw all windows somehow */
2040 }
2041 /* Helpers */
2042 void BKE_ptcache_disk_to_mem(PTCacheID *pid)
2043 {
2044         PointCache *cache = pid->cache;
2045         PTCacheFile *pf;
2046         PTCacheMem *pm;
2047
2048         int cfra, sfra = cache->startframe, efra = cache->endframe;
2049         int i;
2050
2051         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2052
2053         for(cfra=sfra; cfra <= efra; cfra++) {
2054                 pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
2055
2056                 if(pf) {
2057                         if(!ptcache_file_read_header_begin(pf)) {
2058                                 printf("Can't yet convert old cache format\n");
2059                                 cache->flag |= PTCACHE_DISK_CACHE;
2060                                 ptcache_file_close(pf);
2061                                 return;
2062                         }
2063
2064                         if(pf->type != pid->type || !pid->read_header(pf)) {
2065                                 cache->flag |= PTCACHE_DISK_CACHE;
2066                                 ptcache_file_close(pf);
2067                                 return;
2068                         }
2069                         
2070                         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2071
2072                         pm->totpoint = pf->totpoint;
2073                         pm->data_types = pf->data_types;
2074                         pm->frame = cfra;
2075
2076                         ptcache_alloc_data(pm);
2077                         ptcache_mem_init_pointers(pm);
2078                         ptcache_file_init_pointers(pf);
2079
2080                         for(i=0; i<pm->totpoint; i++) {
2081                                 if(!ptcache_file_read_data(pf)) {
2082                                         printf("Error reading from disk cache\n");
2083                                         
2084                                         cache->flag |= PTCACHE_DISK_CACHE;
2085                                         
2086                                         ptcache_free_data(pm->data);
2087                                         MEM_freeN(pm);
2088                                         ptcache_file_close(pf);
2089
2090                                         return;
2091                                 }
2092                                 ptcache_copy_data(pf->cur, pm->cur);
2093                                 ptcache_mem_incr_pointers(pm);
2094                         }
2095
2096                         //ptcache_make_index_array(pm, pid->totpoint(pid->calldata));
2097
2098                         BLI_addtail(&pid->cache->mem_cache, pm);
2099
2100                         ptcache_file_close(pf);
2101                 }
2102         }
2103
2104 }
2105 void BKE_ptcache_mem_to_disk(PTCacheID *pid)
2106 {
2107         PointCache *cache = pid->cache;
2108         PTCacheFile *pf;
2109         PTCacheMem *pm;
2110         int i;
2111
2112         pm = cache->mem_cache.first;
2113
2114         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2115
2116         for(; pm; pm=pm->next) {
2117                 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
2118
2119                 if(pf) {
2120                         pf->data_types = pm->data_types;
2121                         pf->totpoint = pm->totpoint;
2122                         pf->type = pid->type;
2123
2124                         ptcache_mem_init_pointers(pm);
2125                         ptcache_file_init_pointers(pf);
2126
2127                         if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
2128                                 printf("Error writing to disk cache\n");
2129                                 cache->flag &= ~PTCACHE_DISK_CACHE;
2130
2131                                 ptcache_file_close(pf);
2132                                 return;
2133                         }
2134
2135                         for(i=0; i<pm->totpoint; i++) {
2136                                 ptcache_copy_data(pm->cur, pf->cur);
2137                                 if(!ptcache_file_write_data(pf)) {
2138                                         printf("Error writing to disk cache\n");
2139                                         cache->flag &= ~PTCACHE_DISK_CACHE;
2140
2141                                         ptcache_file_close(pf);
2142                                         return;
2143                                 }
2144                                 ptcache_mem_incr_pointers(pm);
2145                         }
2146
2147                         ptcache_file_close(pf);
2148
2149                         /* write info file */
2150                         if(cache->flag & PTCACHE_BAKED)
2151                                 BKE_ptcache_write_cache(pid, 0);
2152                 }
2153                 else
2154                         printf("Error creating disk cache file\n");
2155         }
2156 }
2157 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
2158 {
2159         PointCache *cache = pid->cache;
2160         int last_exact = cache->last_exact;
2161
2162         if (!G.relbase_valid){
2163                 cache->flag &= ~PTCACHE_DISK_CACHE;
2164                 printf("File must be saved before using disk cache!\n");
2165                 return;
2166         }
2167
2168         if(cache->flag & PTCACHE_DISK_CACHE)
2169                 BKE_ptcache_mem_to_disk(pid);
2170         else
2171                 BKE_ptcache_disk_to_mem(pid);
2172
2173         cache->flag ^= PTCACHE_DISK_CACHE;
2174         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2175         cache->flag ^= PTCACHE_DISK_CACHE;
2176         
2177         cache->last_exact = last_exact;
2178
2179         BKE_ptcache_update_info(pid);
2180 }
2181
2182 void BKE_ptcache_load_external(PTCacheID *pid)
2183 {
2184         /*todo*/
2185         PointCache *cache = pid->cache;
2186         int len; /* store the length of the string */
2187         int info = 0;
2188
2189         /* mode is same as fopen's modes */
2190         DIR *dir; 
2191         struct dirent *de;
2192         char path[MAX_PTCACHE_PATH];
2193         char filename[MAX_PTCACHE_FILE];
2194         char ext[MAX_PTCACHE_PATH];
2195
2196         if(!cache)
2197                 return;
2198
2199         cache->startframe = MAXFRAME;
2200         cache->endframe = -1;
2201         cache->totpoint = 0;
2202
2203         ptcache_path(pid, path);
2204         
2205         len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */
2206         
2207         dir = opendir(path);
2208         if (dir==NULL)
2209                 return;
2210
2211         if(cache->index >= 0)
2212                 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
2213         else
2214                 strcpy(ext, PTCACHE_EXT);
2215         
2216         while ((de = readdir(dir)) != NULL) {
2217                 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2218                         if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2219                                 /* read the number of the file */
2220                                 int frame, len2 = (int)strlen(de->d_name);
2221                                 char num[7];
2222
2223                                 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2224                                         BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2225                                         frame = atoi(num);
2226
2227                                         if(frame) {
2228                                                 cache->startframe = MIN2(cache->startframe, frame);
2229                                                 cache->endframe = MAX2(cache->endframe, frame);
2230                                         }
2231                                         else
2232                                                 info = 1;
2233                                 }
2234                         }
2235                 }
2236         }
2237         closedir(dir);
2238
2239         if(cache->startframe != MAXFRAME) {
2240                 PTCacheFile *pf;
2241
2242                 /* read totpoint from info file (frame 0) */
2243                 if(info) {
2244                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
2245
2246                         if(pf) {
2247                                 if(ptcache_file_read_header_begin(pf)) {
2248                                         if(pf->type == pid->type && pid->read_header(pf)) {
2249                                                 cache->totpoint = pf->totpoint;
2250                                                 cache->flag |= PTCACHE_READ_INFO;
2251                                         }
2252                                         else {
2253                                                 cache->totpoint = 0;
2254                                         }
2255                                 }
2256                                 ptcache_file_close(pf);
2257                         }
2258                 }
2259                 /* or from any old format cache file */
2260                 else {
2261                         float old_data[14];
2262                         int elemsize = ptcache_pid_old_elemsize(pid);
2263                         pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
2264
2265                         if(pf) {
2266                                 while(ptcache_file_read(pf, old_data, 1, elemsize))
2267                                         cache->totpoint++;
2268                                 
2269                                 ptcache_file_close(pf);
2270                         }
2271                 }
2272         }
2273
2274         cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
2275
2276         BKE_ptcache_update_info(pid);
2277 }
2278
2279 void BKE_ptcache_update_info(PTCacheID *pid)
2280 {
2281         PointCache *cache = pid->cache;
2282         int totframes = 0;
2283         char mem_info[64];
2284
2285         if(cache->flag & PTCACHE_EXTERNAL) {
2286                 int cfra = cache->startframe;
2287
2288                 for(; cfra<=cache->endframe; cfra++) {
2289                         if(BKE_ptcache_id_exist(pid, cfra))
2290                                 totframes++;
2291                 }
2292
2293                 if(totframes && cache->totpoint)
2294                         sprintf(cache->info, "%i points found!", cache->totpoint);
2295                 else
2296                         sprintf(cache->info, "No valid data to read!");
2297                 return;
2298         }
2299
2300         if(cache->flag & PTCACHE_DISK_CACHE) {
2301                 int cfra = cache->startframe;
2302
2303                 for(; cfra<=cache->endframe; cfra++) {
2304                         if(BKE_ptcache_id_exist(pid, cfra))
2305                                 totframes++;
2306                 }
2307
2308                 sprintf(mem_info, "%i frames on disk", totframes);
2309         }
2310         else {
2311                 PTCacheMem *pm = cache->mem_cache.first;                
2312                 float framesize = 0.0f, bytes = 0.0f;
2313                 int mb;
2314
2315                 if(pm)
2316                         framesize = (float)ptcache_pid_old_elemsize(pid) * (float)pm->totpoint;
2317                 
2318                 for(; pm; pm=pm->next)
2319                         totframes++;
2320
2321                 bytes = totframes * framesize;
2322
2323                 mb = (bytes > 1024.0f * 1024.0f);
2324
2325                 sprintf(mem_info, "%i frames in memory (%.1f %s)",
2326                         totframes,
2327                         bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
2328                         mb ? "Mb" : "kb");
2329         }
2330
2331         if(cache->flag & PTCACHE_OUTDATED) {
2332                 sprintf(cache->info, "%s, cache is outdated!", mem_info);
2333         }
2334         else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
2335                 sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
2336         }
2337         else
2338                 sprintf(cache->info, "%s.", mem_info);
2339 }