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