3 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20 * All rights reserved.
22 * Contributor(s): Campbell Barton <ideasman42@gmail.com>
24 * ***** END GPL LICENSE BLOCK *****
31 #include <sys/types.h>
33 #include "MEM_guardedalloc.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"
44 #include "BLI_blenlib.h"
45 #include "BLI_threads.h"
52 #include "BKE_blender.h"
53 #include "BKE_cloth.h"
54 #include "BKE_depsgraph.h"
55 #include "BKE_global.h"
56 #include "BKE_library.h"
58 #include "BKE_object.h"
59 #include "BKE_particle.h"
60 #include "BKE_pointcache.h"
61 #include "BKE_scene.h"
62 #include "BKE_smoke.h"
63 #include "BKE_softbody.h"
64 #include "BKE_utildefines.h"
68 #include "smoke_API.h"
73 /* used for non-lzo cases */
74 #define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
81 /* needed for directory lookup */
82 /* untitled blend's need getpid for a unique name */
88 #include "BLI_winstuff.h"
91 #define PTCACHE_DATA_FROM(data, type, from) if(data[type]) { memcpy(data[type], from, ptcache_data_size[type]); }
92 #define PTCACHE_DATA_TO(data, type, index, to) if(data[type]) { memcpy(to, (char*)data[type] + (index ? index * ptcache_data_size[type] : 0), ptcache_data_size[type]); }
94 /* could be made into a pointcache option */
95 #define DURIAN_POINTCACHE_LIB_OK 1
97 int ptcache_data_size[] = {
98 sizeof(int), // BPHYS_DATA_INDEX
99 3 * sizeof(float), // BPHYS_DATA_LOCATION:
100 3 * sizeof(float), // BPHYS_DATA_VELOCITY:
101 4 * sizeof(float), // BPHYS_DATA_ROTATION:
102 3 * sizeof(float), // BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */
103 sizeof(float), // BPHYS_DATA_SIZE:
104 3 * sizeof(float), // BPHYS_DATA_TIMES:
105 sizeof(BoidData) // case BPHYS_DATA_BOIDS:
108 /* Common functions */
109 static int ptcache_read_basic_header(PTCacheFile *pf)
113 /* Custom functions should read these basic elements too! */
114 if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp))
117 if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp))
122 static int ptcache_write_basic_header(PTCacheFile *pf)
124 /* Custom functions should write these basic elements too! */
125 if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp))
128 if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp))
133 /* Softbody functions */
134 static int ptcache_write_softbody(int index, void *soft_v, void **data, int cfra)
136 SoftBody *soft= soft_v;
137 BodyPoint *bp = soft->bpoint + index;
139 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos);
140 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec);
144 static void ptcache_read_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float *old_data)
146 SoftBody *soft= soft_v;
147 BodyPoint *bp = soft->bpoint + index;
150 memcpy(bp->pos, data, 3 * sizeof(float));
151 memcpy(bp->vec, data + 3, 3 * sizeof(float));
154 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos);
155 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
158 static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
160 SoftBody *soft= soft_v;
161 BodyPoint *bp = soft->bpoint + index;
168 VECCOPY(keys[1].co, bp->pos);
169 VECCOPY(keys[1].vel, bp->vec);
172 memcpy(keys[2].co, old_data, 3 * sizeof(float));
173 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
176 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
178 dfra = cfra2 - cfra1;
180 mul_v3_fl(keys[1].vel, dfra);
181 mul_v3_fl(keys[2].vel, dfra);
183 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
185 mul_v3_fl(keys->vel, 1.0f / dfra);
187 VECCOPY(bp->pos, keys->co);
188 VECCOPY(bp->vec, keys->vel);
190 static int ptcache_totpoint_softbody(void *soft_v, int cfra)
192 SoftBody *soft= soft_v;
193 return soft->totpoint;
195 /* Particle functions */
196 static int ptcache_write_particle(int index, void *psys_v, void **data, int cfra)
198 ParticleSystem *psys= psys_v;
199 ParticleData *pa = psys->particles + index;
200 BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
201 float times[3] = {pa->time, pa->dietime, pa->lifetime};
202 int step = psys->pointcache->step;
204 /* No need to store unborn or died particles outside cache step bounds */
205 if(data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step))
208 PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
209 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
210 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
211 PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
212 PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
213 PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
214 PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
217 PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
219 /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */
220 return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
222 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
224 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
225 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
226 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
227 PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
230 static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data)
232 ParticleSystem *psys= psys_v;
236 if(index >= psys->totpart)
239 pa = psys->particles + index;
240 boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
242 if(cfra > pa->state.time)
243 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
246 /* old format cache */
247 memcpy(&pa->state, old_data, sizeof(ParticleKey));
251 BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
253 /* set frames cached before birth to birth time */
255 pa->state.time = pa->time;
257 if(data[BPHYS_DATA_SIZE])
258 PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
260 if(data[BPHYS_DATA_TIMES]) {
262 PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×);
264 pa->dietime = times[1];
265 pa->lifetime = times[2];
269 PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
271 /* determine velocity from previous location */
272 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
273 if(cfra > pa->prev_state.time) {
274 sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
275 mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
278 sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
279 mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
283 /* determine rotation from velocity */
284 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
285 vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ);
288 static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
290 ParticleSystem *psys= psys_v;
295 if(index >= psys->totpart)
298 pa = psys->particles + index;
300 /* particle wasn't read from first cache so can't interpolate */
301 if((int)cfra1 < pa->time - psys->pointcache->step || (int)cfra1 > pa->dietime + psys->pointcache->step)
304 cfra = MIN2(cfra, pa->dietime);
305 cfra1 = MIN2(cfra1, pa->dietime);
306 cfra2 = MIN2(cfra2, pa->dietime);
311 memcpy(keys+1, &pa->state, sizeof(ParticleKey));
313 memcpy(keys+2, old_data, sizeof(ParticleKey));
315 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
317 /* determine velocity from previous location */
318 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
319 if(keys[1].time > keys[2].time) {
320 sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
321 mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec);
324 sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
325 mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec);
329 /* determine rotation from velocity */
330 if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
331 vec_to_quat( keys[2].rot,keys[2].vel, OB_NEGX, OB_POSZ);
335 cfra1 = MAX2(cfra1, pa->time);
337 dfra = cfra2 - cfra1;
339 mul_v3_fl(keys[1].vel, dfra / frs_sec);
340 mul_v3_fl(keys[2].vel, dfra / frs_sec);
342 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
343 interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
345 mul_v3_fl(pa->state.vel, frs_sec / dfra);
347 pa->state.time = cfra;
350 static int ptcache_totpoint_particle(void *psys_v, int cfra)
352 ParticleSystem *psys = psys_v;
353 return psys->totpart;
355 static int ptcache_totwrite_particle(void *psys_v, int cfra)
357 ParticleSystem *psys = psys_v;
358 ParticleData *pa= psys->particles;
359 int p, step = psys->pointcache->step;
362 for(p=0; p<psys->totpart; p++,pa++)
363 totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step);
368 //static int ptcache_write_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v)
370 // ParticleSystem *psys= psys_v;
371 // ParticleData *pa = psys->particles;
372 // BoidParticle *boid = NULL;
379 // for(i=0; i<psys->totpart; i++, pa++) {
381 // if(data[BPHYS_DATA_INDEX]) {
382 // int step = psys->pointcache->step;
383 // /* No need to store unborn or died particles */
384 // if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time)
388 // times[0] = pa->time;
389 // times[1] = pa->dietime;
390 // times[2] = pa->lifetime;
392 // PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
393 // PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
394 // PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
395 // PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
396 // PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
397 // PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
398 // PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
400 // boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
402 // PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
404 // if(pf && !ptcache_file_write_data(pf))
408 // BKE_ptcache_mem_incr_pointers(pm);
413 //static void ptcache_read_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v, void **data, float frs_sec, float cfra, float *old_data)
415 // ParticleSystem *psys= psys_v;
416 // ParticleData *pa = psys->particles + index;
417 // BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
419 // if(cfra > pa->state.time)
420 // memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
423 // /* old format cache */
424 // memcpy(&pa->state, old_data, sizeof(ParticleKey));
428 // BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
430 // if(data[BPHYS_DATA_SIZE])
431 // PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
433 // if(data[BPHYS_DATA_TIMES]) {
435 // PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×);
436 // pa->time = times[0];
437 // pa->dietime = times[1];
438 // pa->lifetime = times[2];
442 // PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
444 // /* determine velocity from previous location */
445 // if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
446 // if(cfra > pa->prev_state.time) {
447 // sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
448 // mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec);
451 // sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
452 // mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec);
456 // /* determine rotation from velocity */
457 // if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
458 // vec_to_quat( pa->state.rot,pa->state.vel, OB_POSX, OB_POSZ);
461 //static void ptcache_interpolate_particle_stream(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
463 // ParticleSystem *psys= psys_v;
464 // ParticleData *pa = psys->particles + index;
465 // ParticleKey keys[4];
468 // cfra = MIN2(cfra, pa->dietime);
469 // cfra1 = MIN2(cfra1, pa->dietime);
470 // cfra2 = MIN2(cfra2, pa->dietime);
472 // if(cfra1 == cfra2)
475 // memcpy(keys+1, &pa->state, sizeof(ParticleKey));
477 // memcpy(keys+2, old_data, sizeof(ParticleKey));
479 // BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
481 // dfra = cfra2 - cfra1;
483 // mul_v3_fl(keys[1].vel, dfra / frs_sec);
484 // mul_v3_fl(keys[2].vel, dfra / frs_sec);
486 // psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
487 // interp_qt_qtqt(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
489 // mul_v3_fl(pa->state.vel, frs_sec / dfra);
491 // pa->state.time = cfra;
494 /* Cloth functions */
495 static int ptcache_write_cloth(int index, void *cloth_v, void **data, int cfra)
497 ClothModifierData *clmd= cloth_v;
498 Cloth *cloth= clmd->clothObject;
499 ClothVertex *vert = cloth->verts + index;
501 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x);
502 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v);
503 PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst);
507 static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float *old_data)
509 ClothModifierData *clmd= cloth_v;
510 Cloth *cloth= clmd->clothObject;
511 ClothVertex *vert = cloth->verts + index;
514 memcpy(vert->x, data, 3 * sizeof(float));
515 memcpy(vert->xconst, data + 3, 3 * sizeof(float));
516 memcpy(vert->v, data + 6, 3 * sizeof(float));
519 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x);
520 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v);
521 PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst);
524 static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
526 ClothModifierData *clmd= cloth_v;
527 Cloth *cloth= clmd->clothObject;
528 ClothVertex *vert = cloth->verts + index;
535 VECCOPY(keys[1].co, vert->x);
536 VECCOPY(keys[1].vel, vert->v);
539 memcpy(keys[2].co, old_data, 3 * sizeof(float));
540 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
543 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
545 dfra = cfra2 - cfra1;
547 mul_v3_fl(keys[1].vel, dfra);
548 mul_v3_fl(keys[2].vel, dfra);
550 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
552 mul_v3_fl(keys->vel, 1.0f / dfra);
554 VECCOPY(vert->x, keys->co);
555 VECCOPY(vert->v, keys->vel);
557 /* should vert->xconst be interpolated somehow too? - jahka */
560 static int ptcache_totpoint_cloth(void *cloth_v, int cfra)
562 ClothModifierData *clmd= cloth_v;
563 return clmd->clothObject ? clmd->clothObject->numverts : 0;
567 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
569 memset(pid, 0, sizeof(PTCacheID));
573 pid->type= PTCACHE_TYPE_SOFTBODY;
574 pid->cache= sb->pointcache;
575 pid->cache_ptr= &sb->pointcache;
576 pid->ptcaches= &sb->ptcaches;
577 pid->totpoint= pid->totwrite= ptcache_totpoint_softbody;
579 pid->write_elem= ptcache_write_softbody;
580 pid->write_stream = NULL;
581 pid->read_stream = NULL;
582 pid->read_elem= ptcache_read_softbody;
583 pid->interpolate_elem= ptcache_interpolate_softbody;
585 pid->write_header= ptcache_write_basic_header;
586 pid->read_header= ptcache_read_basic_header;
588 pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
591 pid->stack_index = pid->cache->index;
594 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
596 memset(pid, 0, sizeof(PTCacheID));
600 pid->type= PTCACHE_TYPE_PARTICLES;
601 pid->stack_index= psys->pointcache->index;
602 pid->cache= psys->pointcache;
603 pid->cache_ptr= &psys->pointcache;
604 pid->ptcaches= &psys->ptcaches;
606 if(psys->part->type != PART_HAIR)
607 pid->flag |= PTCACHE_VEL_PER_SEC;
609 pid->write_elem= ptcache_write_particle;
610 pid->write_stream = NULL;
611 pid->read_stream = NULL;
612 pid->read_elem= ptcache_read_particle;
613 pid->interpolate_elem= ptcache_interpolate_particle;
615 pid->totpoint= ptcache_totpoint_particle;
616 pid->totwrite= ptcache_totwrite_particle;
618 pid->write_header= ptcache_write_basic_header;
619 pid->read_header= ptcache_read_basic_header;
621 pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
623 if(psys->part->phystype == PART_PHYS_BOIDS)
624 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
626 if(psys->part->rotmode!=PART_ROT_VEL
627 || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f)
628 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
630 if(psys->part->flag & PART_ROT_DYN)
631 pid->data_types|= (1<<BPHYS_DATA_ROTATION);
633 pid->info_types= (1<<BPHYS_DATA_TIMES);
636 /* Smoke functions */
637 static int ptcache_totpoint_smoke(void *smoke_v, int cfra)
639 SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
640 SmokeDomainSettings *sds = smd->domain;
643 return sds->res[0]*sds->res[1]*sds->res[2];
649 /* Smoke functions */
650 static int ptcache_totpoint_smoke_turbulence(void *smoke_v, int cfra)
652 SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
653 SmokeDomainSettings *sds = smd->domain;
656 return sds->res_wt[0]*sds->res_wt[1]*sds->res_wt[2];
662 // forward decleration
663 static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size);
665 static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
668 unsigned char compressed = 0;
669 unsigned int out_len= 0;
670 unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
674 out_len= LZO_OUT_LEN(in_len);
676 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
678 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
679 if (!(r == LZO_E_OK) || (out_len >= in_len))
688 r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1....
689 props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
691 if(!(r == SZ_OK) || (out_len >= in_len))
698 ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
700 ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int));
701 ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
704 ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
708 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
709 ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char));
717 static int ptcache_write_smoke(PTCacheFile *pf, void *smoke_v)
719 SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
720 SmokeDomainSettings *sds = smd->domain;
723 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
724 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
725 unsigned char *obstacles;
726 unsigned int in_len = sizeof(float)*(unsigned int)res;
727 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
728 //int mode = res >= 1000000 ? 2 : 1;
730 if (sds->cache_comp == SM_CACHE_HEAVY) mode=2; // heavy
732 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
734 ptcache_compress_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
735 ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode);
736 ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode);
737 ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode);
738 ptcache_compress_write(pf, (unsigned char *)heatold, in_len, out, mode);
739 ptcache_compress_write(pf, (unsigned char *)vx, in_len, out, mode);
740 ptcache_compress_write(pf, (unsigned char *)vy, in_len, out, mode);
741 ptcache_compress_write(pf, (unsigned char *)vz, in_len, out, mode);
742 ptcache_compress_write(pf, (unsigned char *)vxold, in_len, out, mode);
743 ptcache_compress_write(pf, (unsigned char *)vyold, in_len, out, mode);
744 ptcache_compress_write(pf, (unsigned char *)vzold, in_len, out, mode);
745 ptcache_compress_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
746 ptcache_file_write(pf, &dt, 1, sizeof(float));
747 ptcache_file_write(pf, &dx, 1, sizeof(float));
756 static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v)
758 SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
759 SmokeDomainSettings *sds = smd->domain;
762 int res_big_array[3];
764 int res = sds->res[0]*sds->res[1]*sds->res[2];
765 float *dens, *densold, *tcu, *tcv, *tcw;
766 unsigned int in_len = sizeof(float)*(unsigned int)res;
767 unsigned int in_len_big;
771 smoke_turbulence_get_res(sds->wt, res_big_array);
772 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
773 //mode = res_big >= 1000000 ? 2 : 1;
775 if (sds->cache_high_comp == SM_CACHE_HEAVY) mode=2; // heavy
777 in_len_big = sizeof(float) * (unsigned int)res_big;
779 smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
781 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
782 ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode);
783 ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode);
786 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
787 ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode);
788 ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode);
789 ptcache_compress_write(pf, (unsigned char *)tcw, in_len, out, mode);
797 // forward decleration
798 static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size);
800 static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
803 unsigned char compressed = 0;
805 unsigned int out_len = len;
807 unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
810 ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
812 ptcache_file_read(pf, &in_len, 1, sizeof(unsigned int));
813 in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
814 ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
818 r = lzo1x_decompress(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
823 size_t leni = in_len, leno = out_len;
824 ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int));
825 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
826 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
832 ptcache_file_read(pf, result, len, sizeof(unsigned char));
840 static void ptcache_read_smoke(PTCacheFile *pf, void *smoke_v)
842 SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
843 SmokeDomainSettings *sds = smd->domain;
846 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
847 float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold;
848 unsigned char *obstacles;
849 unsigned int out_len = (unsigned int)res * sizeof(float);
851 smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles);
853 ptcache_compress_read(pf, (unsigned char *)sds->shadow, out_len);
854 ptcache_compress_read(pf, (unsigned char*)dens, out_len);
855 ptcache_compress_read(pf, (unsigned char*)densold, out_len);
856 ptcache_compress_read(pf, (unsigned char*)heat, out_len);
857 ptcache_compress_read(pf, (unsigned char*)heatold, out_len);
858 ptcache_compress_read(pf, (unsigned char*)vx, out_len);
859 ptcache_compress_read(pf, (unsigned char*)vy, out_len);
860 ptcache_compress_read(pf, (unsigned char*)vz, out_len);
861 ptcache_compress_read(pf, (unsigned char*)vxold, out_len);
862 ptcache_compress_read(pf, (unsigned char*)vyold, out_len);
863 ptcache_compress_read(pf, (unsigned char*)vzold, out_len);
864 ptcache_compress_read(pf, (unsigned char*)obstacles, (unsigned int)res);
865 ptcache_file_read(pf, &dt, 1, sizeof(float));
866 ptcache_file_read(pf, &dx, 1, sizeof(float));
870 static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v)
872 SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
873 SmokeDomainSettings *sds = smd->domain;
876 int res = sds->res[0]*sds->res[1]*sds->res[2];
877 int res_big, res_big_array[3];
878 float *dens, *densold, *tcu, *tcv, *tcw;
879 unsigned int out_len = sizeof(float)*(unsigned int)res;
880 unsigned int out_len_big;
882 smoke_turbulence_get_res(sds->wt, res_big_array);
883 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
884 out_len_big = sizeof(float) * (unsigned int)res_big;
886 smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw);
888 ptcache_compress_read(pf, (unsigned char*)dens, out_len_big);
889 ptcache_compress_read(pf, (unsigned char*)densold, out_len_big);
891 ptcache_compress_read(pf, (unsigned char*)tcu, out_len);
892 ptcache_compress_read(pf, (unsigned char*)tcv, out_len);
893 ptcache_compress_read(pf, (unsigned char*)tcw, out_len);
897 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
899 SmokeDomainSettings *sds = smd->domain;
901 memset(pid, 0, sizeof(PTCacheID));
906 pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
907 pid->stack_index= sds->point_cache[0]->index;
909 pid->cache= sds->point_cache[0];
910 pid->cache_ptr= &(sds->point_cache[0]);
911 pid->ptcaches= &(sds->ptcaches[0]);
913 pid->totpoint= pid->totwrite= ptcache_totpoint_smoke;
915 pid->write_elem= NULL;
916 pid->read_elem= NULL;
918 pid->read_stream = ptcache_read_smoke;
919 pid->write_stream = ptcache_write_smoke;
921 pid->interpolate_elem= NULL;
923 pid->write_header= ptcache_write_basic_header;
924 pid->read_header= ptcache_read_basic_header;
926 pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values to make pointcache happy
930 void BKE_ptcache_id_from_smoke_turbulence(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
932 SmokeDomainSettings *sds = smd->domain;
934 memset(pid, 0, sizeof(PTCacheID));
939 pid->type= PTCACHE_TYPE_SMOKE_HIGHRES;
940 pid->stack_index= sds->point_cache[1]->index;
942 pid->cache= sds->point_cache[1];
943 pid->cache_ptr= &sds->point_cache[1];
944 pid->ptcaches= &sds->ptcaches[1];
946 pid->totpoint= pid->totwrite= ptcache_totpoint_smoke_turbulence;
948 pid->write_elem= NULL;
949 pid->read_elem= NULL;
951 pid->read_stream = ptcache_read_smoke_turbulence;
952 pid->write_stream = ptcache_write_smoke_turbulence;
954 pid->interpolate_elem= NULL;
956 pid->write_header= ptcache_write_basic_header;
957 pid->read_header= ptcache_read_basic_header;
959 pid->data_types= (1<<BPHYS_DATA_LOCATION); // bogus values tot make pointcache happy
963 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
965 memset(pid, 0, sizeof(PTCacheID));
969 pid->type= PTCACHE_TYPE_CLOTH;
970 pid->stack_index= clmd->point_cache->index;
971 pid->cache= clmd->point_cache;
972 pid->cache_ptr= &clmd->point_cache;
973 pid->ptcaches= &clmd->ptcaches;
974 pid->totpoint= pid->totwrite= ptcache_totpoint_cloth;
976 pid->write_elem= ptcache_write_cloth;
977 pid->write_stream = NULL;
978 pid->read_stream = NULL;
979 pid->read_elem= ptcache_read_cloth;
980 pid->interpolate_elem= ptcache_interpolate_cloth;
982 pid->write_header= ptcache_write_basic_header;
983 pid->read_header= ptcache_read_basic_header;
985 pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
989 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
992 ParticleSystem *psys;
995 lb->first= lb->last= NULL;
998 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
999 BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
1000 BLI_addtail(lb, pid);
1003 for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1005 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1006 BKE_ptcache_id_from_particles(pid, ob, psys);
1007 BLI_addtail(lb, pid);
1011 for(md=ob->modifiers.first; md; md=md->next) {
1012 if(md->type == eModifierType_Cloth) {
1013 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1014 BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
1015 BLI_addtail(lb, pid);
1017 if(md->type == eModifierType_Smoke) {
1018 SmokeModifierData *smd = (SmokeModifierData *)md;
1019 if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
1021 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1022 BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md);
1023 BLI_addtail(lb, pid);
1025 pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
1026 BKE_ptcache_id_from_smoke_turbulence(pid, ob, (SmokeModifierData*)md);
1027 BLI_addtail(lb, pid);
1032 if(scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
1033 ListBase *lb_dupli_ob;
1035 if((lb_dupli_ob=object_duplilist(scene, ob))) {
1037 for(dob= lb_dupli_ob->first; dob; dob= dob->next) {
1038 ListBase lb_dupli_pid;
1039 BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
1040 addlisttolist(lb, &lb_dupli_pid);
1041 if(lb_dupli_pid.first)
1042 printf("Adding Dupli\n");
1045 free_object_duplilist(lb_dupli_ob); /* does restore */
1053 /* Takes an Object ID and returns a unique name
1055 - cfra: frame for the cache, can be negative
1056 - stack_index: index in the modifier stack. we can have cache for more then one stack_index
1059 #define MAX_PTCACHE_PATH FILE_MAX
1060 #define MAX_PTCACHE_FILE ((FILE_MAXDIR+FILE_MAXFILE)*2)
1062 static int ptcache_path(PTCacheID *pid, char *filename)
1067 lib= (pid)? pid->ob->id.lib: NULL;
1069 if(pid->cache->flag & PTCACHE_EXTERNAL) {
1070 strcpy(filename, pid->cache->path);
1071 return BLI_add_slash(filename); /* new strlen() */
1073 else if (G.relbase_valid || lib) {
1074 char file[MAX_PTCACHE_PATH]; /* we dont want the dir, only the file */
1075 char *blendfilename;
1077 blendfilename= (lib)? lib->filename: G.sce;
1079 BLI_split_dirfile(blendfilename, NULL, file);
1086 snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
1087 BLI_path_abs(filename, blendfilename);
1088 return BLI_add_slash(filename); /* new strlen() */
1091 /* use the temp path. this is weak but better then not using point cache at all */
1092 /* btempdir is assumed to exist and ALWAYS has a trailing slash */
1093 snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH"%d", btempdir, abs(getpid()));
1095 return BLI_add_slash(filename); /* new strlen() */
1098 static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
1106 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
1108 /* start with temp dir */
1110 len = ptcache_path(pid, filename);
1113 if(strcmp(pid->cache->name, "")==0 && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
1114 idname = (pid->ob->id.name+2);
1115 /* convert chars to hex so they are always a valid filename */
1116 while('\0' != *idname) {
1117 snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
1123 int temp = (int)strlen(pid->cache->name);
1124 strcpy(newname, pid->cache->name);
1131 if(pid->cache->index < 0)
1132 pid->cache->index = pid->stack_index = object_insert_ptcache(pid->ob);
1134 if(pid->cache->flag & PTCACHE_EXTERNAL) {
1135 if(pid->cache->index >= 0)
1136 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1138 snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
1141 snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
1146 return len; /* make sure the above string is always 16 chars */
1149 /* youll need to close yourself after! */
1150 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
1154 char filename[(FILE_MAXDIR+FILE_MAXFILE)*2];
1156 #ifndef DURIAN_POINTCACHE_LIB_OK
1157 /* don't allow writing for linked objects */
1158 if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
1161 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
1163 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
1165 if (mode==PTCACHE_FILE_READ) {
1166 if (!BLI_exists(filename)) {
1169 fp = fopen(filename, "rb");
1170 } else if (mode==PTCACHE_FILE_WRITE) {
1171 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
1172 fp = fopen(filename, "wb");
1173 } else if (mode==PTCACHE_FILE_UPDATE) {
1174 BLI_make_existing_file(filename);
1175 fp = fopen(filename, "rb+");
1181 pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
1187 static void ptcache_file_close(PTCacheFile *pf)
1193 static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size)
1195 return (fread(f, size, tot, pf->fp) == tot);
1197 static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size)
1199 return (fwrite(f, size, tot, pf->fp) == tot);
1201 static int ptcache_file_read_data(PTCacheFile *pf)
1205 for(i=0; i<BPHYS_TOT_DATA; i++) {
1206 if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
1212 static int ptcache_file_write_data(PTCacheFile *pf)
1216 for(i=0; i<BPHYS_TOT_DATA; i++) {
1217 if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
1223 static int ptcache_file_read_header_begin(PTCacheFile *pf)
1230 if(fread(bphysics, sizeof(char), 8, pf->fp) != 8)
1233 if(!error && strncmp(bphysics, "BPHYSICS", 8))
1236 if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp))
1239 /* if there was an error set file as it was */
1241 fseek(pf->fp, 0, SEEK_SET);
1247 static int ptcache_file_write_header_begin(PTCacheFile *pf)
1249 char *bphysics = "BPHYSICS";
1251 if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
1254 if(!fwrite(&pf->type, sizeof(int), 1, pf->fp))
1261 /* Data pointer handling */
1262 int BKE_ptcache_data_size(int data_type)
1264 return ptcache_data_size[data_type];
1267 static void ptcache_file_init_pointers(PTCacheFile *pf)
1269 int data_types = pf->data_types;
1271 pf->cur[BPHYS_DATA_INDEX] = data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : NULL;
1272 pf->cur[BPHYS_DATA_LOCATION] = data_types & (1<<BPHYS_DATA_LOCATION) ? &pf->data.loc : NULL;
1273 pf->cur[BPHYS_DATA_VELOCITY] = data_types & (1<<BPHYS_DATA_VELOCITY) ? &pf->data.vel : NULL;
1274 pf->cur[BPHYS_DATA_ROTATION] = data_types & (1<<BPHYS_DATA_ROTATION) ? &pf->data.rot : NULL;
1275 pf->cur[BPHYS_DATA_AVELOCITY] = data_types & (1<<BPHYS_DATA_AVELOCITY) ? &pf->data.ave : NULL;
1276 pf->cur[BPHYS_DATA_SIZE] = data_types & (1<<BPHYS_DATA_SIZE) ? &pf->data.size : NULL;
1277 pf->cur[BPHYS_DATA_TIMES] = data_types & (1<<BPHYS_DATA_TIMES) ? &pf->data.times : NULL;
1278 pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<<BPHYS_DATA_BOIDS) ? &pf->data.boids : NULL;
1281 static void ptcache_file_seek_pointers(int index, PTCacheFile *pf)
1284 int data_types = pf->data_types;
1286 if(data_types & (1<<BPHYS_DATA_INDEX)) {
1288 /* The simplest solution is to just write to the very end. This may cause
1289 * some data duplication, but since it's on disk it's not so bad. The correct
1290 * thing would be to search through the file for the correct index and only
1291 * write to the end if it's not found, but this could be quite slow.
1293 fseek(pf->fp, 8 + sizeof(int), SEEK_SET);
1294 fread(&totpoint, sizeof(int), 1, pf->fp);
1298 fseek(pf->fp, 8 + sizeof(int), SEEK_SET);
1299 fwrite(&totpoint, sizeof(int), 1, pf->fp);
1301 fseek(pf->fp, 0, SEEK_END);
1304 for(i=0; i<BPHYS_TOT_DATA; i++)
1305 size += pf->data_types & (1<<i) ? ptcache_data_size[i] : 0;
1307 /* size of default header + data up to index */
1308 fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET);
1311 ptcache_file_init_pointers(pf);
1313 void BKE_ptcache_mem_init_pointers(PTCacheMem *pm)
1315 int data_types = pm->data_types;
1318 for(i=0; i<BPHYS_TOT_DATA; i++)
1319 pm->cur[i] = data_types & (1<<i) ? pm->data[i] : NULL;
1322 void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm)
1326 for(i=0; i<BPHYS_TOT_DATA; i++) {
1328 pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i];
1331 static int BKE_ptcache_mem_seek_pointers(int point_index, PTCacheMem *pm)
1333 int data_types = pm->data_types;
1334 int i, index = pm->index_array ? pm->index_array[point_index] - 1 : point_index;
1337 /* Can't give proper location without reallocation, so don't give any location.
1338 * Some points will be cached improperly, but this only happens with simulation
1339 * steps bigger than cache->step, so the cache has to be recalculated anyways
1345 for(i=0; i<BPHYS_TOT_DATA; i++)
1346 pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL;
1350 static void ptcache_alloc_data(PTCacheMem *pm)
1352 int data_types = pm->data_types;
1353 int totpoint = pm->totpoint;
1356 for(i=0; i<BPHYS_TOT_DATA; i++) {
1357 if(data_types & (1<<i))
1358 pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
1361 static void ptcache_free_data(PTCacheMem *pm)
1363 void **data = pm->data;
1366 for(i=0; i<BPHYS_TOT_DATA; i++) {
1371 if(pm->index_array) {
1372 MEM_freeN(pm->index_array);
1373 pm->index_array = NULL;
1376 static void ptcache_copy_data(void *from[], void *to[])
1379 for(i=0; i<BPHYS_TOT_DATA; i++) {
1381 memcpy(to[i], from[i], ptcache_data_size[i]);
1387 static int ptcache_pid_old_elemsize(PTCacheID *pid)
1389 if(pid->type==PTCACHE_TYPE_SOFTBODY)
1390 return 6 * sizeof(float);
1391 else if(pid->type==PTCACHE_TYPE_PARTICLES)
1392 return sizeof(ParticleKey);
1393 else if(pid->type==PTCACHE_TYPE_CLOTH)
1394 return 9 * sizeof(float);
1399 /* reads cache from disk or memory */
1400 /* possible to get old or interpolated result */
1401 int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec)
1403 PTCacheFile *pf=NULL, *pf2=NULL;
1404 PTCacheMem *pm=NULL, *pm2=NULL;
1405 float old_data1[14], old_data2[14];
1406 int cfrai = (int)cfra;
1407 int old_elemsize = ptcache_pid_old_elemsize(pid);
1410 int cfra1 = 0, cfra2 = 0;
1411 int totpoint = 0, totpoint2 = 0;
1412 int *index = &i, *index2 = &i;
1413 int use_old = 0, old_frame = 0;
1415 int ret = 0, error = 0;
1417 /* nothing to read to */
1418 if(pid->totpoint(pid->calldata, (int)cfra) == 0)
1421 if(pid->cache->flag & PTCACHE_READ_INFO) {
1422 pid->cache->flag &= ~PTCACHE_READ_INFO;
1423 BKE_ptcache_read_cache(pid, 0, frs_sec);
1427 /* first check if we have the actual frame cached */
1428 if(cfra == (float)cfrai) {
1429 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1430 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1433 pm = pid->cache->mem_cache.first;
1435 for(; pm; pm=pm->next) {
1436 if(pm->frame == cfrai)
1442 /* no exact cache frame found so try to find cached frames around cfra */
1444 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1446 while(cfrai > pid->cache->startframe && !pf) {
1448 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1455 while(cfrai < pid->cache->endframe && !pf2) {
1457 pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
1466 else if(pid->cache->mem_cache.first){
1467 pm = pid->cache->mem_cache.first;
1469 while(pm->next && pm->next->frame < cfra)
1473 old_frame = pm->frame;
1477 pm2 = pid->cache->mem_cache.last;
1479 if(pm2 && pm2->frame < cfra)
1482 while(pm2->prev && pm2->prev->frame > cfra)
1496 if(!pm && !pm2 && !pf && !pf2)
1500 BKE_ptcache_mem_init_pointers(pm);
1501 totpoint = pm->totpoint;
1502 index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
1505 BKE_ptcache_mem_init_pointers(pm2);
1506 totpoint2 = pm2->totpoint;
1507 index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
1510 if(ptcache_file_read_header_begin(pf)) {
1511 if(pf->type != pid->type) {
1512 /* todo report error */
1513 ptcache_file_close(pf);
1516 else if(pid->read_header(pf)) {
1517 ptcache_file_init_pointers(pf);
1518 totpoint = pf->totpoint;
1519 index = pf->data_types & (1<<BPHYS_DATA_INDEX) ? &pf->data.index : &i;
1523 /* fall back to old cache file format */
1525 totpoint = pid->totpoint(pid->calldata, (int) cfra);
1529 if(ptcache_file_read_header_begin(pf2)) {
1530 if(pf2->type != pid->type) {
1531 /* todo report error */
1532 ptcache_file_close(pf2);
1535 else if(pid->read_header(pf2)) {
1536 ptcache_file_init_pointers(pf2);
1537 totpoint2 = pf2->totpoint;
1538 index2 = pf2->data_types & (1<<BPHYS_DATA_INDEX) ? &pf2->data.index : &i;
1542 /* fall back to old cache file format */
1544 totpoint2 = pid->totpoint(pid->calldata, (int) cfra);
1548 /* don't read old cache if already simulated past cached frame */
1549 if(!pm && !pf && cfra1 && cfra1 <= pid->cache->simframe)
1551 if(cfra1 && cfra1==cfra2)
1556 if(pf && pid->read_stream) {
1557 if(totpoint != pid->totpoint(pid->calldata, (int) cfra))
1561 // we have stream writing here
1562 pid->read_stream(pf, pid->calldata);
1567 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
1568 totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int) cfra));
1572 for(i=0; i<totpoint; i++) {
1573 /* read old cache file format */
1575 if(pid->read_elem && ptcache_file_read(pf, (void*)old_data1, 1, old_elemsize))
1576 pid->read_elem(i, pid->calldata, NULL, frs_sec, cfra, old_data1);
1577 else if(pid->read_elem)
1578 { error = 1; break; }
1581 if(pid->read_elem && (pm || ptcache_file_read_data(pf)))
1582 pid->read_elem(*index, pid->calldata, pm ? pm->cur : pf->cur, frs_sec, cfra1 ? (float)cfra1 : (float)cfrai, NULL);
1583 else if(pid->read_elem)
1584 { error = 1; break; }
1588 BKE_ptcache_mem_incr_pointers(pm);
1589 index = pm->data_types & (1<<BPHYS_DATA_INDEX) ? pm->cur[BPHYS_DATA_INDEX] : &i;
1596 if(pf2 && pid->read_stream) {
1597 if(totpoint2 != pid->totpoint(pid->calldata, (int) cfra))
1601 // we have stream writing here
1602 pid->read_stream(pf2, pid->calldata);
1607 if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
1608 totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata, (int) cfra));
1612 for(i=0; i<totpoint2; i++) {
1613 /* read old cache file format */
1615 if(pid->read_elem && ptcache_file_read(pf2, (void*)old_data2, 1, old_elemsize)) {
1617 pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)cfra2, old_data2);
1618 else if(pid->interpolate_elem)
1619 pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)cfra1, (float)cfra2, old_data2);
1621 { error = 1; break; }
1623 else if(pid->read_elem)
1624 { error = 1; break; }
1627 if(pid->read_elem && (pm2 || ptcache_file_read_data(pf2))) {
1628 if((!pf && pf2) || (!pm && pm2))
1629 pid->read_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, (float)cfra2, NULL);
1630 else if(pid->interpolate_elem)
1631 pid->interpolate_elem(*index2, pid->calldata, pm2 ? pm2->cur : pf2->cur, frs_sec, cfra, (float)cfra1, (float)cfra2, NULL);
1633 { error = 1; break; }
1635 else if(pid->read_elem)
1636 { error = 1; break; }
1640 BKE_ptcache_mem_incr_pointers(pm2);
1641 index2 = pm2->data_types & (1<<BPHYS_DATA_INDEX) ? pm2->cur[BPHYS_DATA_INDEX] : &i;
1647 ret = (pm2 || pf2) ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT;
1648 else if(pm2 || pf2) {
1649 ret = PTCACHE_READ_OLD;
1650 pid->cache->simframe = old_frame;
1654 ptcache_file_close(pf);
1659 ptcache_file_close(pf2);
1663 if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
1665 /* clear invalid cache frames so that better stuff can be simulated */
1666 if(pid->cache->flag & PTCACHE_OUTDATED) {
1667 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
1669 else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
1670 if(cfra <= pid->cache->last_exact)
1671 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1673 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact));
1677 return (error ? 0 : ret);
1679 /* TODO for later */
1680 static void ptcache_make_index_array(PTCacheMem *pm, int totpoint)
1684 if(pm->index_array) {
1685 MEM_freeN(pm->index_array);
1686 pm->index_array = NULL;
1689 if(!pm->data[BPHYS_DATA_INDEX])
1692 pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array");
1693 index = pm->data[BPHYS_DATA_INDEX];
1695 for(i=0; i<pm->totpoint; i++, index++)
1696 pm->index_array[*index] = i + 1;
1698 /* writes cache to disk or memory */
1699 int BKE_ptcache_write_cache(PTCacheID *pid, int cfra)
1701 PointCache *cache = pid->cache;
1702 PTCacheFile *pf= NULL, *pf2= NULL;
1704 int totpoint = pid->totpoint(pid->calldata, cfra);
1705 int add = 0, overwrite = 0;
1707 if(totpoint == 0 || cfra < 0
1708 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
1711 if(cache->flag & PTCACHE_DISK_CACHE) {
1712 int ofra=0, efra = cache->endframe;
1716 /* allways start from scratch on the first frame */
1717 else if(cfra == cache->startframe) {
1718 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1719 cache->flag &= ~PTCACHE_REDO_NEEDED;
1723 /* find last cached frame */
1724 while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
1727 /* find second last cached frame */
1729 while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
1732 if(efra >= cache->startframe && cfra > efra) {
1733 if(ofra >= cache->startframe && efra - ofra < cache->step)
1740 if(add || overwrite) {
1742 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
1744 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
1748 pf->type = pid->type;
1749 pf->totpoint = cfra ? pid->totwrite(pid->calldata, cfra) : totpoint;
1750 pf->data_types = cfra ? pid->data_types : pid->info_types;
1752 if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
1753 ptcache_file_close(pf);
1757 ptcache_file_init_pointers(pf);
1759 if(pf && pid->write_stream) {
1760 // we have stream writing here
1761 pid->write_stream(pf, pid->calldata);
1764 for(i=0; i<totpoint; i++) {
1765 if(pid->write_elem) {
1766 int write = pid->write_elem(i, pid->calldata, pf->cur, cfra);
1768 if(!ptcache_file_write_data(pf)) {
1769 ptcache_file_close(pf);
1770 if(pf2) ptcache_file_close(pf2);
1773 /* newly born particles have to be copied to previous cached frame */
1774 else if(overwrite && write == 2) {
1776 pf2 = ptcache_file_open(pid, PTCACHE_FILE_UPDATE, ofra);
1778 ptcache_file_close(pf);
1781 pf2->type = pid->type;
1782 pf2->totpoint = totpoint;
1783 pf2->data_types = pid->data_types;
1785 ptcache_file_seek_pointers(i, pf2);
1786 pid->write_elem(i, pid->calldata, pf2->cur, cfra);
1787 if(!ptcache_file_write_data(pf2)) {
1788 ptcache_file_close(pf);
1789 ptcache_file_close(pf2);
1802 pm2 = cache->mem_cache.first;
1804 /* don't write info file in memory */
1807 /* allways start from scratch on the first frame */
1808 if(cfra == cache->startframe) {
1809 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
1810 cache->flag &= ~PTCACHE_REDO_NEEDED;
1813 else if (cache->mem_cache.last) {
1814 pm2 = cache->mem_cache.last;
1816 if(pm2 && cfra > pm2->frame) {
1817 if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
1826 if(add || overwrite) {
1828 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm2->frame);
1830 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1832 pm->totpoint = pid->totwrite(pid->calldata, cfra);
1833 pm->data_types = cfra ? pid->data_types : pid->info_types;
1835 ptcache_alloc_data(pm);
1836 BKE_ptcache_mem_init_pointers(pm);
1838 for(i=0; i<totpoint; i++) {
1839 if(pid->write_elem) {
1840 int write = pid->write_elem(i, pid->calldata, pm->cur, cfra);
1842 BKE_ptcache_mem_incr_pointers(pm);
1844 /* newly born particles have to be copied to previous cached frame */
1845 if(overwrite && write == 2) {
1846 pm2 = cache->mem_cache.last;
1847 if(BKE_ptcache_mem_seek_pointers(i, pm2))
1848 pid->write_elem(i, pid->calldata, pm2->cur, cfra);
1853 ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra));
1856 BLI_addtail(&cache->mem_cache, pm);
1860 if(add || overwrite) {
1861 if(cfra - cache->last_exact == 1
1862 || cfra == cache->startframe) {
1863 cache->last_exact = cfra;
1864 cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
1867 cache->flag |= PTCACHE_FRAMES_SKIPPED;
1870 if(pf) ptcache_file_close(pf);
1872 if(pf2) ptcache_file_close(pf2);
1874 BKE_ptcache_update_info(pid);
1878 /* youll need to close yourself after!
1879 * mode - PTCACHE_CLEAR_ALL,
1882 /* Clears & resets */
1883 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
1885 int len; /* store the length of the string */
1887 /* mode is same as fopen's modes */
1890 char path[MAX_PTCACHE_PATH];
1891 char filename[MAX_PTCACHE_FILE];
1892 char path_full[MAX_PTCACHE_FILE];
1893 char ext[MAX_PTCACHE_PATH];
1895 if(!pid->cache || pid->cache->flag & PTCACHE_BAKED)
1898 #ifndef DURIAN_POINTCACHE_LIB_OK
1899 /* don't allow clearing for linked objects */
1904 /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
1906 /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
1908 case PTCACHE_CLEAR_ALL:
1909 case PTCACHE_CLEAR_BEFORE:
1910 case PTCACHE_CLEAR_AFTER:
1911 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1912 ptcache_path(pid, path);
1914 len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
1916 dir = opendir(path);
1920 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
1922 while ((de = readdir(dir)) != NULL) {
1923 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
1924 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
1925 if (mode == PTCACHE_CLEAR_ALL) {
1926 pid->cache->last_exact = 0;
1927 BLI_join_dirfile(path_full, path, de->d_name);
1928 BLI_delete(path_full, 0, 0);
1930 /* read the number of the file */
1931 int frame, len2 = (int)strlen(de->d_name);
1934 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
1935 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
1938 if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra) ||
1939 (mode==PTCACHE_CLEAR_AFTER && frame > cfra) ) {
1941 BLI_join_dirfile(path_full, path, de->d_name);
1942 BLI_delete(path_full, 0, 0);
1952 PTCacheMem *pm= pid->cache->mem_cache.first;
1953 PTCacheMem *link= NULL;
1955 pm= pid->cache->mem_cache.first;
1957 if(mode == PTCACHE_CLEAR_ALL) {
1958 pid->cache->last_exact = 0;
1959 for(; pm; pm=pm->next)
1960 ptcache_free_data(pm);
1961 BLI_freelistN(&pid->cache->mem_cache);
1964 if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
1965 (mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra) ) {
1967 ptcache_free_data(pm);
1969 BLI_freelinkN(&pid->cache->mem_cache, link);
1978 case PTCACHE_CLEAR_FRAME:
1979 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
1980 if(BKE_ptcache_id_exist(pid, cfra)) {
1981 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
1982 BLI_delete(filename, 0, 0);
1986 PTCacheMem *pm = pid->cache->mem_cache.first;
1988 for(; pm; pm=pm->next) {
1989 if(pm->frame == cfra) {
1990 ptcache_free_data(pm);
1991 BLI_freelinkN(&pid->cache->mem_cache, pm);
1999 BKE_ptcache_update_info(pid);
2002 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
2007 if(pid->cache->flag & PTCACHE_DISK_CACHE) {
2008 char filename[MAX_PTCACHE_FILE];
2010 BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
2012 return BLI_exists(filename);
2015 PTCacheMem *pm = pid->cache->mem_cache.first;
2017 for(; pm; pm=pm->next) {
2025 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
2029 float offset, time, nexttime;
2031 /* TODO: this has to be sorter out once bsystem_time gets redone, */
2032 /* now caches can handle interpolating etc. too - jahka */
2034 /* time handling for point cache:
2035 * - simulation time is scaled by result of bsystem_time
2036 * - for offsetting time only time offset is taken into account, since
2037 * that's always the same and can't be animated. a timeoffset which
2038 * varies over time is not simpe to support.
2039 * - field and motion blur offsets are currently ignored, proper solution
2040 * is probably to interpolate results from two frames for that ..
2047 time= bsystem_time(scene, ob, cfra, 0.0f);
2048 nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f);
2050 *timescale= MAX2(nexttime - time, 0.0f);
2053 if(startframe && endframe) {
2054 *startframe= cache->startframe;
2055 *endframe= cache->endframe;
2057 // XXX ipoflag is depreceated - old animation system stuff
2058 if (/*(ob->ipoflag & OB_OFFS_PARENT) &&*/ (ob->partype & PARSLOW)==0) {
2059 offset= give_timeoffset(ob);
2061 *startframe += (int)(offset+0.5f);
2062 *endframe += (int)(offset+0.5f);
2067 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
2070 int reset, clear, after;
2080 if(mode == PTCACHE_RESET_DEPSGRAPH) {
2081 if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
2082 if(cache->flag & PTCACHE_QUICK_CACHE)
2088 cache->flag |= PTCACHE_OUTDATED;
2090 else if(mode == PTCACHE_RESET_BAKED) {
2091 if(!BKE_ptcache_get_continue_physics()) {
2096 cache->flag |= PTCACHE_OUTDATED;
2098 else if(mode == PTCACHE_RESET_OUTDATED) {
2101 if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
2103 cache->flag &= ~PTCACHE_OUTDATED;
2108 BKE_ptcache_invalidate(cache);
2109 cache->flag &= ~PTCACHE_REDO_NEEDED;
2111 if(pid->type == PTCACHE_TYPE_CLOTH)
2112 cloth_free_modifier(pid->ob, pid->calldata);
2113 else if(pid->type == PTCACHE_TYPE_SOFTBODY)
2114 sbFreeSimulation(pid->calldata);
2115 else if(pid->type == PTCACHE_TYPE_PARTICLES)
2116 psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
2117 else if(pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
2118 smokeModifier_reset(pid->calldata);
2119 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
2120 smokeModifier_reset_turbulence(pid->calldata);
2123 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2125 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
2127 return (reset || clear || after);
2130 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
2133 ParticleSystem *psys;
2141 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
2142 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2145 for(psys=ob->particlesystem.first; psys; psys=psys->next) {
2146 /* Baked cloth hair has to be checked first, because we don't want to reset */
2147 /* particles or cloth in that case -jahka */
2149 BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
2150 if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED)))
2151 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2155 else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
2158 if(skip == 0 && psys->part) {
2159 BKE_ptcache_id_from_particles(&pid, ob, psys);
2160 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2164 for(md=ob->modifiers.first; md; md=md->next) {
2165 if(md->type == eModifierType_Cloth) {
2166 BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
2167 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2169 if(md->type == eModifierType_Smoke) {
2170 SmokeModifierData *smd = (SmokeModifierData *)md;
2171 if(smd->type & MOD_SMOKE_TYPE_DOMAIN)
2173 BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md);
2174 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2176 BKE_ptcache_id_from_smoke_turbulence(&pid, ob, (SmokeModifierData*)md);
2177 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2182 if (ob->type == OB_ARMATURE)
2183 BIK_clear_cache(ob->pose);
2188 /* Use this when quitting blender, with unsaved files */
2189 void BKE_ptcache_remove(void)
2191 char path[MAX_PTCACHE_PATH];
2192 char path_full[MAX_PTCACHE_PATH];
2195 ptcache_path(NULL, path);
2197 if (BLI_exist(path)) {
2198 /* The pointcache dir exists? - remove all pointcache */
2203 dir = opendir(path);
2207 while ((de = readdir(dir)) != NULL) {
2208 if( strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) {
2210 } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
2211 BLI_join_dirfile(path_full, path, de->d_name);
2212 BLI_delete(path_full, 0, 0);
2214 rmdir = 0; /* unknown file, dont remove the dir */
2220 rmdir = 0; /* path dosnt exist */
2224 BLI_delete(path, 1, 0);
2228 /* Continuous Interaction */
2230 static int CONTINUE_PHYSICS = 0;
2232 void BKE_ptcache_set_continue_physics(Scene *scene, int enable)
2236 if(CONTINUE_PHYSICS != enable) {
2237 CONTINUE_PHYSICS = enable;
2239 if(CONTINUE_PHYSICS == 0) {
2240 for(ob=G.main->object.first; ob; ob=ob->id.next)
2241 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
2242 DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
2247 int BKE_ptcache_get_continue_physics()
2249 return CONTINUE_PHYSICS;
2252 /* Point Cache handling */
2254 PointCache *BKE_ptcache_add(ListBase *ptcaches)
2258 cache= MEM_callocN(sizeof(PointCache), "PointCache");
2259 cache->startframe= 1;
2260 cache->endframe= 250;
2264 BLI_addtail(ptcaches, cache);
2269 void BKE_ptcache_free_mem(ListBase *mem_cache)
2271 PTCacheMem *pm = mem_cache->first;
2274 for(; pm; pm=pm->next)
2275 ptcache_free_data(pm);
2277 BLI_freelistN(mem_cache);
2280 void BKE_ptcache_free(PointCache *cache)
2282 BKE_ptcache_free_mem(&cache->mem_cache);
2283 if(cache->edit && cache->free_edit)
2284 cache->free_edit(cache->edit);
2287 void BKE_ptcache_free_list(ListBase *ptcaches)
2289 PointCache *cache = ptcaches->first;
2292 BLI_remlink(ptcaches, cache);
2293 BKE_ptcache_free(cache);
2294 cache = ptcaches->first;
2298 static PointCache *ptcache_copy(PointCache *cache)
2302 ncache= MEM_dupallocN(cache);
2304 /* hmm, should these be copied over instead? */
2305 ncache->mem_cache.first = NULL;
2306 ncache->mem_cache.last = NULL;
2309 ncache->simframe= 0;
2313 /* returns first point cache */
2314 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old)
2316 PointCache *cache = ptcaches_old->first;
2318 ptcaches_new->first = ptcaches_new->last = NULL;
2320 for(; cache; cache=cache->next)
2321 BLI_addtail(ptcaches_new, ptcache_copy(cache));
2323 return ptcaches_new->first;
2328 static int count_quick_cache(Scene *scene, int *quick_step)
2333 int autocache_count= 0;
2334 Scene *sce; /* for macro only */
2336 for(SETLOOPER(scene, base)) {
2338 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
2340 for(pid=pidlist.first; pid; pid=pid->next) {
2341 if((pid->cache->flag & PTCACHE_BAKED)
2342 || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
2345 if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
2346 if(!autocache_count)
2347 *quick_step = pid->cache->step;
2349 *quick_step = MIN2(*quick_step, pid->cache->step);
2355 BLI_freelistN(&pidlist);
2359 return autocache_count;
2361 void BKE_ptcache_quick_cache_all(Scene *scene)
2366 baker.break_data=NULL;
2367 baker.break_test=NULL;
2369 baker.progressbar=NULL;
2370 baker.progressend=NULL;
2371 baker.progresscontext=NULL;
2373 baker.anim_init = 0;
2376 if(count_quick_cache(scene, &baker.quick_step))
2377 BKE_ptcache_make_cache(&baker);
2380 /* Simulation thread, no need for interlocks as data written in both threads
2381 are only unitary integers (I/O assumed to be atomic for them) */
2383 int break_operation;
2389 } ptcache_make_cache_data;
2391 static void *ptcache_make_cache_thread(void *ptr) {
2392 ptcache_make_cache_data *data = (ptcache_make_cache_data*)ptr;
2394 for(; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step)
2395 scene_update_for_newframe(data->scene, data->scene->lay);
2397 data->thread_ended = TRUE;
2401 /* if bake is not given run simulations to current frame */
2402 void BKE_ptcache_make_cache(PTCacheBaker* baker)
2404 Scene *scene = baker->scene;
2405 Scene *sce; /* SETLOOPER macro only */
2408 PTCacheID *pid = baker->pid;
2409 PointCache *cache = NULL;
2410 float frameleno = scene->r.framelen;
2412 int startframe = MAXFRAME;
2413 int bake = baker->bake;
2414 int render = baker->render;
2416 ptcache_make_cache_data thread_data;
2417 int progress, old_progress;
2419 thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA;
2420 thread_data.step = baker->quick_step;
2421 thread_data.cfra_ptr = &CFRA;
2422 thread_data.scene = baker->scene;
2426 /* set caches to baking mode and figure out start frame */
2428 /* cache/bake a single object */
2430 if((cache->flag & PTCACHE_BAKED)==0) {
2431 if(pid->type==PTCACHE_TYPE_PARTICLES)
2432 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
2433 else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
2434 /* get all pids from the object and search for smoke low res */
2437 BKE_ptcache_ids_from_object(&pidlist2, pid->ob, scene, MAX_DUPLI_RECUR);
2438 for(pid2=pidlist2.first; pid2; pid2=pid2->next) {
2439 if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN)
2441 if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) {
2442 if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED)
2443 BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0);
2445 pid2->cache->flag |= PTCACHE_BAKING;
2446 pid2->cache->flag &= ~PTCACHE_BAKED;
2451 BLI_freelistN(&pidlist2);
2454 if(bake || cache->flag & PTCACHE_REDO_NEEDED)
2455 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2457 startframe = MAX2(cache->last_exact, cache->startframe);
2460 thread_data.endframe = cache->endframe;
2461 cache->flag |= PTCACHE_BAKING;
2464 thread_data.endframe = MIN2(thread_data.endframe, cache->endframe);
2467 cache->flag &= ~PTCACHE_BAKED;
2470 for(SETLOOPER(scene, base)) {
2471 /* cache/bake everything in the scene */
2472 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
2474 for(pid=pidlist.first; pid; pid=pid->next) {
2476 if((cache->flag & PTCACHE_BAKED)==0) {
2477 if(pid->type==PTCACHE_TYPE_PARTICLES) {
2478 ParticleSystem *psys = (ParticleSystem*)pid->calldata;
2479 /* skip hair & keyed particles */
2480 if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
2483 psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
2486 if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
2487 && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
2488 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2490 startframe = MIN2(startframe, cache->startframe);
2492 if(bake || render) {
2493 cache->flag |= PTCACHE_BAKING;
2496 thread_data.endframe = MAX2(thread_data.endframe, cache->endframe);
2499 cache->flag &= ~PTCACHE_BAKED;
2503 BLI_freelistN(&pidlist);
2507 scene->r.framelen = 1.0;
2508 thread_data.break_operation = FALSE;
2509 thread_data.thread_ended = FALSE;
2512 BLI_init_threads(&threads, ptcache_make_cache_thread, 1);
2513 BLI_insert_thread(&threads, (void*)&thread_data);
2515 while (thread_data.thread_ended == FALSE) {
2518 progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe));
2522 /* NOTE: baking should not redraw whole ui as this slows things down */
2523 if ((baker->progressbar) && (progress != old_progress)) {
2524 baker->progressbar(baker->progresscontext, progress);
2525 old_progress = progress;
2528 /* Delay to lessen CPU load from UI thread */
2531 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
2532 if(blender_test_break() && !thread_data.break_operation) {
2533 thread_data.break_operation = TRUE;
2534 if (baker->progressend)
2535 baker->progressend(baker->progresscontext);
2540 BLI_end_threads(&threads);
2542 /* clear baking flag */
2544 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
2545 cache->flag |= PTCACHE_SIMULATION_VALID;
2547 cache->flag |= PTCACHE_BAKED;
2548 /* write info file */
2549 if(cache->flag & PTCACHE_DISK_CACHE)
2550 BKE_ptcache_write_cache(pid, 0);
2553 else for(SETLOOPER(scene, base)) {
2554 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
2556 for(pid=pidlist.first; pid; pid=pid->next) {
2557 /* skip hair particles */
2558 if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
2563 if(thread_data.step > 1)
2564 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
2566 cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
2568 cache->flag |= PTCACHE_SIMULATION_VALID;
2571 cache->flag |= PTCACHE_BAKED;
2572 if(cache->flag & PTCACHE_DISK_CACHE)
2573 BKE_ptcache_write_cache(pid, 0);
2576 BLI_freelistN(&pidlist);
2579 scene->r.framelen = frameleno;
2582 if(bake) /* already on cfra unless baking */
2583 scene_update_for_newframe(scene, scene->lay);
2585 if (thread_data.break_operation)
2587 else if (baker->progressend)
2588 baker->progressend(baker->progresscontext);
2590 /* TODO: call redraw all windows somehow */
2593 void BKE_ptcache_disk_to_mem(PTCacheID *pid)
2595 PointCache *cache = pid->cache;
2599 int cfra, sfra = cache->startframe, efra = cache->endframe;
2602 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2604 for(cfra=sfra; cfra <= efra; cfra++) {
2605 pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
2608 if(!ptcache_file_read_header_begin(pf)) {
2609 printf("Can't yet convert old cache format\n");
2610 cache->flag |= PTCACHE_DISK_CACHE;
2611 ptcache_file_close(pf);
2615 if(pf->type != pid->type || !pid->read_header(pf)) {
2616 cache->flag |= PTCACHE_DISK_CACHE;
2617 ptcache_file_close(pf);
2621 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2623 pm->totpoint = pf->totpoint;
2624 pm->data_types = pf->data_types;
2627 ptcache_alloc_data(pm);
2628 BKE_ptcache_mem_init_pointers(pm);
2629 ptcache_file_init_pointers(pf);
2631 for(i=0; i<pm->totpoint; i++) {
2632 if(!ptcache_file_read_data(pf)) {
2633 printf("Error reading from disk cache\n");
2635 cache->flag |= PTCACHE_DISK_CACHE;
2637 ptcache_free_data(pm);
2639 ptcache_file_close(pf);
2643 ptcache_copy_data(pf->cur, pm->cur);
2644 BKE_ptcache_mem_incr_pointers(pm);
2647 ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra));
2649 BLI_addtail(&pid->cache->mem_cache, pm);
2651 ptcache_file_close(pf);
2656 void BKE_ptcache_mem_to_disk(PTCacheID *pid)
2658 PointCache *cache = pid->cache;
2663 pm = cache->mem_cache.first;
2665 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2667 for(; pm; pm=pm->next) {
2668 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
2671 pf->data_types = pm->data_types;
2672 pf->totpoint = pm->totpoint;
2673 pf->type = pid->type;
2675 BKE_ptcache_mem_init_pointers(pm);
2676 ptcache_file_init_pointers(pf);
2678 if(!ptcache_file_write_header_begin(pf) || !pid->write_header(pf)) {
2679 printf("Error writing to disk cache\n");
2680 cache->flag &= ~PTCACHE_DISK_CACHE;
2682 ptcache_file_close(pf);
2686 for(i=0; i<pm->totpoint; i++) {
2687 ptcache_copy_data(pm->cur, pf->cur);
2688 if(!ptcache_file_write_data(pf)) {
2689 printf("Error writing to disk cache\n");
2690 cache->flag &= ~PTCACHE_DISK_CACHE;
2692 ptcache_file_close(pf);
2695 BKE_ptcache_mem_incr_pointers(pm);
2698 ptcache_file_close(pf);
2700 /* write info file */
2701 if(cache->flag & PTCACHE_BAKED)
2702 BKE_ptcache_write_cache(pid, 0);
2705 printf("Error creating disk cache file\n");
2708 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
2710 PointCache *cache = pid->cache;
2711 int last_exact = cache->last_exact;
2713 if (!G.relbase_valid){
2714 cache->flag &= ~PTCACHE_DISK_CACHE;
2715 printf("File must be saved before using disk cache!\n");
2719 if(cache->flag & PTCACHE_DISK_CACHE)
2720 BKE_ptcache_mem_to_disk(pid);
2722 BKE_ptcache_disk_to_mem(pid);
2724 cache->flag ^= PTCACHE_DISK_CACHE;
2725 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2726 cache->flag ^= PTCACHE_DISK_CACHE;
2728 cache->last_exact = last_exact;
2730 BKE_ptcache_update_info(pid);
2733 void BKE_ptcache_load_external(PTCacheID *pid)
2736 PointCache *cache = pid->cache;
2737 int len; /* store the length of the string */
2740 /* mode is same as fopen's modes */
2743 char path[MAX_PTCACHE_PATH];
2744 char filename[MAX_PTCACHE_FILE];
2745 char ext[MAX_PTCACHE_PATH];
2750 cache->startframe = MAXFRAME;
2751 cache->endframe = -1;
2752 cache->totpoint = 0;
2754 ptcache_path(pid, path);
2756 len = BKE_ptcache_id_filename(pid, filename, 1, 0, 0); /* no path */
2758 dir = opendir(path);
2762 if(cache->index >= 0)
2763 snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
2765 strcpy(ext, PTCACHE_EXT);
2767 while ((de = readdir(dir)) != NULL) {
2768 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2769 if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
2770 /* read the number of the file */
2771 int frame, len2 = (int)strlen(de->d_name);
2774 if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
2775 BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
2779 cache->startframe = MIN2(cache->startframe, frame);
2780 cache->endframe = MAX2(cache->endframe, frame);
2790 if(cache->startframe != MAXFRAME) {
2793 /* read totpoint from info file (frame 0) */
2795 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
2798 if(ptcache_file_read_header_begin(pf)) {
2799 if(pf->type == pid->type && pid->read_header(pf)) {
2800 cache->totpoint = pf->totpoint;
2801 cache->flag |= PTCACHE_READ_INFO;
2804 cache->totpoint = 0;
2807 ptcache_file_close(pf);
2810 /* or from any old format cache file */
2813 int elemsize = ptcache_pid_old_elemsize(pid);
2814 pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
2817 while(ptcache_file_read(pf, old_data, 1, elemsize))
2820 ptcache_file_close(pf);
2825 cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
2827 BKE_ptcache_update_info(pid);
2830 void BKE_ptcache_update_info(PTCacheID *pid)
2832 PointCache *cache = pid->cache;
2836 if(cache->flag & PTCACHE_EXTERNAL) {
2837 int cfra = cache->startframe;
2839 for(; cfra<=cache->endframe; cfra++) {
2840 if(BKE_ptcache_id_exist(pid, cfra))
2844 if(totframes && cache->totpoint)
2845 sprintf(cache->info, "%i points found!", cache->totpoint);
2847 sprintf(cache->info, "No valid data to read!");
2851 if(cache->flag & PTCACHE_DISK_CACHE) {
2852 int cfra = cache->startframe;
2854 for(; cfra<=cache->endframe; cfra++) {
2855 if(BKE_ptcache_id_exist(pid, cfra))
2859 sprintf(mem_info, "%i frames on disk", totframes);
2862 PTCacheMem *pm = cache->mem_cache.first;
2866 for(; pm; pm=pm->next) {
2867 for(i=0; i<BPHYS_TOT_DATA; i++)
2868 bytes += pm->data[i] ? MEM_allocN_len(pm->data[i]) : 0.0f;
2872 mb = (bytes > 1024.0f * 1024.0f);
2874 sprintf(mem_info, "%i frames in memory (%.1f %s)",
2876 bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
2880 if(cache->flag & PTCACHE_OUTDATED) {
2881 sprintf(cache->info, "%s, cache is outdated!", mem_info);
2883 else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
2884 sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
2887 sprintf(cache->info, "%s.", mem_info);
2890 void BKE_ptcache_validate(PointCache *cache, int framenr)
2892 cache->flag |= PTCACHE_SIMULATION_VALID;
2893 cache->simframe = framenr;
2895 void BKE_ptcache_invalidate(PointCache *cache)
2897 cache->flag &= ~PTCACHE_SIMULATION_VALID;
2898 cache->simframe = 0;
2899 cache->last_exact = 0;