1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup bke
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29
30 #include "CLG_log.h"
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_ID.h"
35 #include "DNA_collection_types.h"
36 #include "DNA_dynamicpaint_types.h"
37 #include "DNA_fluid_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_force_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_particle_types.h"
42 #include "DNA_rigidbody_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_simulation_types.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48 #include "BLI_string.h"
49 #include "BLI_utildefines.h"
50
51 #include "BLT_translation.h"
52
53 #include "PIL_time.h"
54
55 #include "BKE_appdir.h"
56 #include "BKE_cloth.h"
57 #include "BKE_collection.h"
58 #include "BKE_dynamicpaint.h"
59 #include "BKE_fluid.h"
60 #include "BKE_global.h"
61 #include "BKE_lib_id.h"
62 #include "BKE_main.h"
63 #include "BKE_modifier.h"
64 #include "BKE_object.h"
65 #include "BKE_particle.h"
66 #include "BKE_pointcache.h"
67 #include "BKE_scene.h"
68 #include "BKE_softbody.h"
69
70 #include "BIK_api.h"
71
72 #ifdef WITH_BULLET
73 # include "RBI_api.h"
74 #endif
75
76 #ifdef WITH_LZO
77 # ifdef WITH_SYSTEM_LZO
78 # include <lzo/lzo1x.h>
79 # else
80 # include "minilzo.h"
81 # endif
82 # define LZO_HEAP_ALLOC(var, size) \
83 lzo_align_t __LZO_MMODEL var[((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)]
84 #endif
85
86 #define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
87
88 #ifdef WITH_LZMA
89 # include "LzmaLib.h"
90 #endif
91
92 /* needed for directory lookup */
93 #ifndef WIN32
94 # include <dirent.h>
95 #else
96 # include "BLI_winstuff.h"
97 #endif
98
99 #define PTCACHE_DATA_FROM(data, type, from) \
100 if (data[type]) { \
101 memcpy(data[type], from, ptcache_data_size[type]); \
102 } \
103 (void)0
104
105 #define PTCACHE_DATA_TO(data, type, index, to) \
106 if (data[type]) { \
107 memcpy(to, \
108 (char *)(data)[type] + ((index) ? (index)*ptcache_data_size[type] : 0), \
109 ptcache_data_size[type]); \
110 } \
111 (void)0
112
113 /* could be made into a pointcache option */
114 #define DURIAN_POINTCACHE_LIB_OK 1
115
116 static CLG_LogRef LOG = {"bke.pointcache"};
117
118 static int ptcache_data_size[] = {
119 sizeof(unsigned int), /* BPHYS_DATA_INDEX */
120 sizeof(float[3]), /* BPHYS_DATA_LOCATION */
121 sizeof(float[3]), /* BPHYS_DATA_VELOCITY */
122 sizeof(float[4]), /* BPHYS_DATA_ROTATION */
123 sizeof(float[3]), /* BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
124 sizeof(float), /* BPHYS_DATA_SIZE */
125 sizeof(float[3]), /* BPHYS_DATA_TIMES */
126 sizeof(BoidData), /* case BPHYS_DATA_BOIDS */
127 };
128
129 static int ptcache_extra_datasize[] = {
130 0,
131 sizeof(ParticleSpring),
132 sizeof(float[3]),
133 };
134
135 /* forward declarations */
136 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len);
137 static int ptcache_file_compressed_write(
138 PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode);
139 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size);
140 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
141
142 /* Common functions */
ptcache_basic_header_read(PTCacheFile * pf)143 static int ptcache_basic_header_read(PTCacheFile *pf)
144 {
145 int error = 0;
146
147 /* Custom functions should read these basic elements too! */
148 if (!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) {
149 error = 1;
150 }
151
152 if (!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) {
153 error = 1;
154 }
155
156 return !error;
157 }
ptcache_basic_header_write(PTCacheFile * pf)158 static int ptcache_basic_header_write(PTCacheFile *pf)
159 {
160 /* Custom functions should write these basic elements too! */
161 if (!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp)) {
162 return 0;
163 }
164
165 if (!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp)) {
166 return 0;
167 }
168
169 return 1;
170 }
ptcache_add_extra_data(PTCacheMem * pm,unsigned int type,unsigned int count,void * data)171 static void ptcache_add_extra_data(PTCacheMem *pm,
172 unsigned int type,
173 unsigned int count,
174 void *data)
175 {
176 PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: extra data descriptor");
177
178 extra->type = type;
179 extra->totdata = count;
180
181 size_t size = extra->totdata * ptcache_extra_datasize[extra->type];
182
183 extra->data = MEM_mallocN(size, "Point cache: extra data");
184 memcpy(extra->data, data, size);
185
186 BLI_addtail(&pm->extradata, extra);
187 }
188 /* Softbody functions */
ptcache_softbody_write(int index,void * soft_v,void ** data,int UNUSED (cfra))189 static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
190 {
191 SoftBody *soft = soft_v;
192 BodyPoint *bp = soft->bpoint + index;
193
194 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos);
195 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec);
196
197 return 1;
198 }
ptcache_softbody_read(int index,void * soft_v,void ** data,float UNUSED (cfra),const float * old_data)199 static void ptcache_softbody_read(
200 int index, void *soft_v, void **data, float UNUSED(cfra), const float *old_data)
201 {
202 SoftBody *soft = soft_v;
203 BodyPoint *bp = soft->bpoint + index;
204
205 if (old_data) {
206 memcpy(bp->pos, data, sizeof(float[3]));
207 memcpy(bp->vec, data + 3, sizeof(float[3]));
208 }
209 else {
210 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos);
211 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
212 }
213 }
ptcache_softbody_interpolate(int index,void * soft_v,void ** data,float cfra,float cfra1,float cfra2,const float * old_data)214 static void ptcache_softbody_interpolate(int index,
215 void *soft_v,
216 void **data,
217 float cfra,
218 float cfra1,
219 float cfra2,
220 const float *old_data)
221 {
222 SoftBody *soft = soft_v;
223 BodyPoint *bp = soft->bpoint + index;
224 ParticleKey keys[4];
225 float dfra;
226
227 if (cfra1 == cfra2) {
228 return;
229 }
230
231 copy_v3_v3(keys[1].co, bp->pos);
232 copy_v3_v3(keys[1].vel, bp->vec);
233
234 if (old_data) {
235 memcpy(keys[2].co, old_data, sizeof(float[3]));
236 memcpy(keys[2].vel, old_data + 3, sizeof(float[3]));
237 }
238 else {
239 BKE_ptcache_make_particle_key(keys + 2, 0, data, cfra2);
240 }
241
242 dfra = cfra2 - cfra1;
243
244 mul_v3_fl(keys[1].vel, dfra);
245 mul_v3_fl(keys[2].vel, dfra);
246
247 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
248
249 mul_v3_fl(keys->vel, 1.0f / dfra);
250
251 copy_v3_v3(bp->pos, keys->co);
252 copy_v3_v3(bp->vec, keys->vel);
253 }
ptcache_softbody_totpoint(void * soft_v,int UNUSED (cfra))254 static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
255 {
256 SoftBody *soft = soft_v;
257 return soft->totpoint;
258 }
ptcache_softbody_error(void * UNUSED (soft_v),const char * UNUSED (message))259 static void ptcache_softbody_error(void *UNUSED(soft_v), const char *UNUSED(message))
260 {
261 /* ignored for now */
262 }
263
264 /* Particle functions */
BKE_ptcache_make_particle_key(ParticleKey * key,int index,void ** data,float time)265 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
266 {
267 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
268 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
269
270 /* no rotation info, so make something nice up */
271 if (data[BPHYS_DATA_ROTATION] == NULL) {
272 vec_to_quat(key->rot, key->vel, OB_NEGX, OB_POSZ);
273 }
274 else {
275 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
276 }
277
278 PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
279 key->time = time;
280 }
ptcache_particle_write(int index,void * psys_v,void ** data,int cfra)281 static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
282 {
283 ParticleSystem *psys = psys_v;
284 ParticleData *pa = psys->particles + index;
285 BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
286 float times[3];
287 int step = psys->pointcache->step;
288
289 /* Skip some particles that are not stored in the cache. */
290 if (data[BPHYS_DATA_INDEX]) {
291 if (psys->part->flag & PART_DIED) {
292 /* Dead particles are stored when they are displayed. */
293 if (cfra < pa->time - step) {
294 return 0;
295 }
296 }
297 else {
298 /* Particles are only stored in their lifetime. */
299 if (cfra < pa->time - step || cfra > pa->dietime + step) {
300 return 0;
301 }
302 }
303 }
304
305 times[0] = pa->time;
306 times[1] = pa->dietime;
307 times[2] = pa->lifetime;
308
309 PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
310 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
311 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
312 PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
313 PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
314 PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
315 PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
316
317 if (boid) {
318 PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
319 }
320
321 /* Return flag 1+1=2 for newly born particles
322 * to copy exact birth location to previously cached frame. */
323 return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
324 }
ptcache_particle_read(int index,void * psys_v,void ** data,float cfra,const float * old_data)325 static void ptcache_particle_read(
326 int index, void *psys_v, void **data, float cfra, const float *old_data)
327 {
328 ParticleSystem *psys = psys_v;
329 ParticleData *pa;
330 BoidParticle *boid;
331 float timestep = 0.04f * psys->part->timetweak;
332
333 if (index >= psys->totpart) {
334 return;
335 }
336
337 pa = psys->particles + index;
338 boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
339
340 if (cfra > pa->state.time) {
341 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
342 }
343
344 if (old_data) {
345 /* old format cache */
346 memcpy(&pa->state, old_data, sizeof(ParticleKey));
347 return;
348 }
349
350 BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
351
352 /* set frames cached before birth to birth time */
353 if (cfra < pa->time) {
354 pa->state.time = pa->time;
355 }
356 else if (cfra > pa->dietime) {
357 pa->state.time = pa->dietime;
358 }
359
360 if (data[BPHYS_DATA_SIZE]) {
361 PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
362 }
363
364 if (data[BPHYS_DATA_TIMES]) {
365 float times[3];
366 PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×);
367 pa->time = times[0];
368 pa->dietime = times[1];
369 pa->lifetime = times[2];
370 }
371
372 if (boid) {
373 PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
374 }
375
376 /* determine velocity from previous location */
377 if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
378 if (cfra > pa->prev_state.time) {
379 sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
380 mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep);
381 }
382 else {
383 sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
384 mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep);
385 }
386 }
387
388 /* default to no rotation */
389 if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
390 unit_qt(pa->state.rot);
391 }
392 }
ptcache_particle_interpolate(int index,void * psys_v,void ** data,float cfra,float cfra1,float cfra2,const float * old_data)393 static void ptcache_particle_interpolate(int index,
394 void *psys_v,
395 void **data,
396 float cfra,
397 float cfra1,
398 float cfra2,
399 const float *old_data)
400 {
401 ParticleSystem *psys = psys_v;
402 ParticleData *pa;
403 ParticleKey keys[4];
404 float dfra, timestep = 0.04f * psys->part->timetweak;
405
406 if (index >= psys->totpart) {
407 return;
408 }
409
410 pa = psys->particles + index;
411
412 /* particle wasn't read from first cache so can't interpolate */
413 if ((int)cfra1 < pa->time - psys->pointcache->step ||
414 (int)cfra1 > pa->dietime + psys->pointcache->step) {
415 return;
416 }
417
418 cfra = MIN2(cfra, pa->dietime);
419 cfra1 = MIN2(cfra1, pa->dietime);
420 cfra2 = MIN2(cfra2, pa->dietime);
421
422 if (cfra1 == cfra2) {
423 return;
424 }
425
426 memcpy(keys + 1, &pa->state, sizeof(ParticleKey));
427 if (old_data) {
428 memcpy(keys + 2, old_data, sizeof(ParticleKey));
429 }
430 else {
431 BKE_ptcache_make_particle_key(keys + 2, 0, data, cfra2);
432 }
433
434 /* determine velocity from previous location */
435 if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
436 if (keys[1].time > keys[2].time) {
437 sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
438 mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep);
439 }
440 else {
441 sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
442 mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep);
443 }
444 }
445
446 /* default to no rotation */
447 if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
448 unit_qt(keys[2].rot);
449 }
450
451 if (cfra > pa->time) {
452 cfra1 = MAX2(cfra1, pa->time);
453 }
454
455 dfra = cfra2 - cfra1;
456
457 mul_v3_fl(keys[1].vel, dfra * timestep);
458 mul_v3_fl(keys[2].vel, dfra * timestep);
459
460 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
461 interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
462
463 mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep));
464
465 pa->state.time = cfra;
466 }
467
ptcache_particle_totpoint(void * psys_v,int UNUSED (cfra))468 static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
469 {
470 ParticleSystem *psys = psys_v;
471 return psys->totpart;
472 }
473
ptcache_particle_error(void * UNUSED (psys_v),const char * UNUSED (message))474 static void ptcache_particle_error(void *UNUSED(psys_v), const char *UNUSED(message))
475 {
476 /* ignored for now */
477 }
478
ptcache_particle_totwrite(void * psys_v,int cfra)479 static int ptcache_particle_totwrite(void *psys_v, int cfra)
480 {
481 ParticleSystem *psys = psys_v;
482 ParticleData *pa = psys->particles;
483 int p, step = psys->pointcache->step;
484 int totwrite = 0;
485
486 if (cfra == 0) {
487 return psys->totpart;
488 }
489
490 if (psys->part->flag & PART_DIED) {
491 /* Also store dead particles when they are displayed. */
492 for (p = 0; p < psys->totpart; p++, pa++) {
493 totwrite += (cfra >= pa->time - step);
494 }
495 }
496 else {
497 for (p = 0; p < psys->totpart; p++, pa++) {
498 totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step);
499 }
500 }
501
502 return totwrite;
503 }
504
ptcache_particle_extra_write(void * psys_v,PTCacheMem * pm,int UNUSED (cfra))505 static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
506 {
507 ParticleSystem *psys = psys_v;
508
509 if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid &&
510 psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS && psys->tot_fluidsprings &&
511 psys->fluid_springs) {
512 ptcache_add_extra_data(
513 pm, BPHYS_EXTRA_FLUID_SPRINGS, psys->tot_fluidsprings, psys->fluid_springs);
514 }
515 }
516
ptcache_particle_extra_read(void * psys_v,PTCacheMem * pm,float UNUSED (cfra))517 static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
518 {
519 ParticleSystem *psys = psys_v;
520 PTCacheExtra *extra = pm->extradata.first;
521
522 for (; extra; extra = extra->next) {
523 switch (extra->type) {
524 case BPHYS_EXTRA_FLUID_SPRINGS: {
525 if (psys->fluid_springs) {
526 MEM_freeN(psys->fluid_springs);
527 }
528
529 psys->fluid_springs = MEM_dupallocN(extra->data);
530 psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata;
531 break;
532 }
533 }
534 }
535 }
536
537 /* Cloth functions */
ptcache_cloth_write(int index,void * cloth_v,void ** data,int UNUSED (cfra))538 static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
539 {
540 ClothModifierData *clmd = cloth_v;
541 Cloth *cloth = clmd->clothObject;
542 ClothVertex *vert = cloth->verts + index;
543
544 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x);
545 PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v);
546 PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst);
547
548 return 1;
549 }
ptcache_cloth_read(int index,void * cloth_v,void ** data,float UNUSED (cfra),const float * old_data)550 static void ptcache_cloth_read(
551 int index, void *cloth_v, void **data, float UNUSED(cfra), const float *old_data)
552 {
553 ClothModifierData *clmd = cloth_v;
554 Cloth *cloth = clmd->clothObject;
555 ClothVertex *vert = cloth->verts + index;
556
557 if (old_data) {
558 memcpy(vert->x, data, sizeof(float[3]));
559 memcpy(vert->xconst, data + 3, sizeof(float[3]));
560 memcpy(vert->v, data + 6, sizeof(float[3]));
561 }
562 else {
563 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x);
564 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v);
565 PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst);
566 }
567 }
ptcache_cloth_interpolate(int index,void * cloth_v,void ** data,float cfra,float cfra1,float cfra2,const float * old_data)568 static void ptcache_cloth_interpolate(int index,
569 void *cloth_v,
570 void **data,
571 float cfra,
572 float cfra1,
573 float cfra2,
574 const float *old_data)
575 {
576 ClothModifierData *clmd = cloth_v;
577 Cloth *cloth = clmd->clothObject;
578 ClothVertex *vert = cloth->verts + index;
579 ParticleKey keys[4];
580 float dfra;
581
582 if (cfra1 == cfra2) {
583 return;
584 }
585
586 copy_v3_v3(keys[1].co, vert->x);
587 copy_v3_v3(keys[1].vel, vert->v);
588
589 if (old_data) {
590 memcpy(keys[2].co, old_data, sizeof(float[3]));
591 memcpy(keys[2].vel, old_data + 6, sizeof(float[3]));
592 }
593 else {
594 BKE_ptcache_make_particle_key(keys + 2, 0, data, cfra2);
595 }
596
597 dfra = cfra2 - cfra1;
598
599 mul_v3_fl(keys[1].vel, dfra);
600 mul_v3_fl(keys[2].vel, dfra);
601
602 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
603
604 mul_v3_fl(keys->vel, 1.0f / dfra);
605
606 copy_v3_v3(vert->x, keys->co);
607 copy_v3_v3(vert->v, keys->vel);
608
609 /* should vert->xconst be interpolated somehow too? - jahka */
610 }
611
ptcache_cloth_extra_write(void * cloth_v,PTCacheMem * pm,int UNUSED (cfra))612 static void ptcache_cloth_extra_write(void *cloth_v, PTCacheMem *pm, int UNUSED(cfra))
613 {
614 ClothModifierData *clmd = cloth_v;
615 Cloth *cloth = clmd->clothObject;
616
617 if (!is_zero_v3(cloth->average_acceleration)) {
618 ptcache_add_extra_data(pm, BPHYS_EXTRA_CLOTH_ACCELERATION, 1, cloth->average_acceleration);
619 }
620 }
ptcache_cloth_extra_read(void * cloth_v,PTCacheMem * pm,float UNUSED (cfra))621 static void ptcache_cloth_extra_read(void *cloth_v, PTCacheMem *pm, float UNUSED(cfra))
622 {
623 ClothModifierData *clmd = cloth_v;
624 Cloth *cloth = clmd->clothObject;
625 PTCacheExtra *extra = pm->extradata.first;
626
627 zero_v3(cloth->average_acceleration);
628
629 for (; extra; extra = extra->next) {
630 switch (extra->type) {
631 case BPHYS_EXTRA_CLOTH_ACCELERATION: {
632 copy_v3_v3(cloth->average_acceleration, extra->data);
633 break;
634 }
635 }
636 }
637 }
638
ptcache_cloth_totpoint(void * cloth_v,int UNUSED (cfra))639 static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
640 {
641 ClothModifierData *clmd = cloth_v;
642 return clmd->clothObject ? clmd->clothObject->mvert_num : 0;
643 }
644
ptcache_cloth_error(void * cloth_v,const char * message)645 static void ptcache_cloth_error(void *cloth_v, const char *message)
646 {
647 ClothModifierData *clmd = cloth_v;
648 BKE_modifier_set_error(&clmd->modifier, "%s", message);
649 }
650
ptcache_dynamicpaint_totpoint(void * sd,int UNUSED (cfra))651 static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
652 {
653 DynamicPaintSurface *surface = (DynamicPaintSurface *)sd;
654
655 if (!surface->data) {
656 return 0;
657 }
658
659 return surface->data->total_points;
660 }
661
ptcache_dynamicpaint_error(void * UNUSED (sd),const char * UNUSED (message))662 static void ptcache_dynamicpaint_error(void *UNUSED(sd), const char *UNUSED(message))
663 {
664 /* ignored for now */
665 }
666
667 #define DPAINT_CACHE_VERSION "1.01"
668
ptcache_dynamicpaint_write(PTCacheFile * pf,void * dp_v)669 static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
670 {
671 DynamicPaintSurface *surface = (DynamicPaintSurface *)dp_v;
672 int cache_compress = 1;
673
674 /* version header */
675 ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char[4]));
676
677 if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
678 int total_points = surface->data->total_points;
679 unsigned int in_len;
680 unsigned char *out;
681
682 /* cache type */
683 ptcache_file_write(pf, &surface->type, 1, sizeof(int));
684
685 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
686 in_len = sizeof(PaintPoint) * total_points;
687 }
688 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
689 surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
690 in_len = sizeof(float) * total_points;
691 }
692 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
693 in_len = sizeof(PaintWavePoint) * total_points;
694 }
695 else {
696 return 0;
697 }
698
699 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
700
701 ptcache_file_compressed_write(
702 pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress);
703 MEM_freeN(out);
704 }
705 return 1;
706 }
ptcache_dynamicpaint_read(PTCacheFile * pf,void * dp_v)707 static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
708 {
709 DynamicPaintSurface *surface = (DynamicPaintSurface *)dp_v;
710 char version[4];
711
712 /* version header */
713 ptcache_file_read(pf, version, 1, sizeof(char[4]));
714 if (!STREQLEN(version, DPAINT_CACHE_VERSION, 4)) {
715 CLOG_ERROR(&LOG, "Dynamic Paint: Invalid cache version: '%c%c%c%c'!", UNPACK4(version));
716 return 0;
717 }
718
719 if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
720 unsigned int data_len;
721 int surface_type;
722
723 /* cache type */
724 ptcache_file_read(pf, &surface_type, 1, sizeof(int));
725
726 if (surface_type != surface->type) {
727 return 0;
728 }
729
730 /* read surface data */
731 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
732 data_len = sizeof(PaintPoint);
733 }
734 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
735 surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
736 data_len = sizeof(float);
737 }
738 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
739 data_len = sizeof(PaintWavePoint);
740 }
741 else {
742 return 0;
743 }
744
745 ptcache_file_compressed_read(
746 pf, (unsigned char *)surface->data->type_data, data_len * surface->data->total_points);
747 }
748 return 1;
749 }
750
751 /* Rigid Body functions */
ptcache_rigidbody_write(int index,void * rb_v,void ** data,int UNUSED (cfra))752 static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
753 {
754 RigidBodyWorld *rbw = rb_v;
755 Object *ob = NULL;
756
757 if (rbw->objects) {
758 ob = rbw->objects[index];
759 }
760
761 if (ob && ob->rigidbody_object) {
762 RigidBodyOb *rbo = ob->rigidbody_object;
763
764 if (rbo->type == RBO_TYPE_ACTIVE && rbo->shared->physics_object != NULL) {
765 #ifdef WITH_BULLET
766 RB_body_get_position(rbo->shared->physics_object, rbo->pos);
767 RB_body_get_orientation(rbo->shared->physics_object, rbo->orn);
768 #endif
769 PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
770 PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
771 }
772 }
773
774 return 1;
775 }
ptcache_rigidbody_read(int index,void * rb_v,void ** data,float UNUSED (cfra),const float * old_data)776 static void ptcache_rigidbody_read(
777 int index, void *rb_v, void **data, float UNUSED(cfra), const float *old_data)
778 {
779 RigidBodyWorld *rbw = rb_v;
780 Object *ob = NULL;
781
782 if (rbw->objects) {
783 ob = rbw->objects[index];
784 }
785
786 if (ob && ob->rigidbody_object) {
787 RigidBodyOb *rbo = ob->rigidbody_object;
788
789 if (rbo->type == RBO_TYPE_ACTIVE) {
790
791 if (old_data) {
792 memcpy(rbo->pos, data, sizeof(float[3]));
793 memcpy(rbo->orn, data + 3, sizeof(float[4]));
794 }
795 else {
796 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos);
797 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn);
798 }
799 }
800 }
801 }
ptcache_rigidbody_interpolate(int index,void * rb_v,void ** data,float cfra,float cfra1,float cfra2,const float * old_data)802 static void ptcache_rigidbody_interpolate(int index,
803 void *rb_v,
804 void **data,
805 float cfra,
806 float cfra1,
807 float cfra2,
808 const float *old_data)
809 {
810 RigidBodyWorld *rbw = rb_v;
811 Object *ob = NULL;
812
813 if (rbw->objects) {
814 ob = rbw->objects[index];
815 }
816
817 if (ob && ob->rigidbody_object) {
818 RigidBodyOb *rbo = ob->rigidbody_object;
819
820 if (rbo->type == RBO_TYPE_ACTIVE) {
821 ParticleKey keys[4];
822 ParticleKey result;
823 float dfra;
824
825 memset(keys, 0, sizeof(keys));
826
827 copy_v3_v3(keys[1].co, rbo->pos);
828 copy_qt_qt(keys[1].rot, rbo->orn);
829
830 if (old_data) {
831 memcpy(keys[2].co, data, sizeof(float[3]));
832 memcpy(keys[2].rot, data + 3, sizeof(float[4]));
833 }
834 else {
835 BKE_ptcache_make_particle_key(&keys[2], 0, data, cfra2);
836 }
837
838 dfra = cfra2 - cfra1;
839
840 /* note: keys[0] and keys[3] unused for type < 1 (crappy) */
841 psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true);
842 interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
843
844 copy_v3_v3(rbo->pos, result.co);
845 copy_qt_qt(rbo->orn, result.rot);
846 }
847 }
848 }
ptcache_rigidbody_totpoint(void * rb_v,int UNUSED (cfra))849 static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
850 {
851 RigidBodyWorld *rbw = rb_v;
852
853 return rbw->numbodies;
854 }
855
ptcache_rigidbody_error(void * UNUSED (rb_v),const char * UNUSED (message))856 static void ptcache_rigidbody_error(void *UNUSED(rb_v), const char *UNUSED(message))
857 {
858 /* ignored for now */
859 }
860
861 /* Creating ID's */
BKE_ptcache_id_from_softbody(PTCacheID * pid,Object * ob,SoftBody * sb)862 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
863 {
864 memset(pid, 0, sizeof(PTCacheID));
865
866 pid->owner_id = &ob->id;
867 pid->calldata = sb;
868 pid->type = PTCACHE_TYPE_SOFTBODY;
869 pid->cache = sb->shared->pointcache;
870 pid->cache_ptr = &sb->shared->pointcache;
871 pid->ptcaches = &sb->shared->ptcaches;
872 pid->totpoint = pid->totwrite = ptcache_softbody_totpoint;
873 pid->error = ptcache_softbody_error;
874
875 pid->write_point = ptcache_softbody_write;
876 pid->read_point = ptcache_softbody_read;
877 pid->interpolate_point = ptcache_softbody_interpolate;
878
879 pid->write_stream = NULL;
880 pid->read_stream = NULL;
881
882 pid->write_extra_data = NULL;
883 pid->read_extra_data = NULL;
884 pid->interpolate_extra_data = NULL;
885
886 pid->write_header = ptcache_basic_header_write;
887 pid->read_header = ptcache_basic_header_read;
888
889 pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_VELOCITY);
890 pid->info_types = 0;
891
892 pid->stack_index = pid->cache->index;
893
894 pid->default_step = 1;
895 pid->max_step = 20;
896 pid->file_type = PTCACHE_FILE_PTCACHE;
897 }
BKE_ptcache_id_from_particles(PTCacheID * pid,Object * ob,ParticleSystem * psys)898 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
899 {
900 memset(pid, 0, sizeof(PTCacheID));
901
902 pid->owner_id = &ob->id;
903 pid->calldata = psys;
904 pid->type = PTCACHE_TYPE_PARTICLES;
905 pid->stack_index = psys->pointcache->index;
906 pid->cache = psys->pointcache;
907 pid->cache_ptr = &psys->pointcache;
908 pid->ptcaches = &psys->ptcaches;
909
910 if (psys->part->type != PART_HAIR) {
911 pid->flag |= PTCACHE_VEL_PER_SEC;
912 }
913
914 pid->totpoint = ptcache_particle_totpoint;
915 pid->totwrite = ptcache_particle_totwrite;
916 pid->error = ptcache_particle_error;
917
918 pid->write_point = ptcache_particle_write;
919 pid->read_point = ptcache_particle_read;
920 pid->interpolate_point = ptcache_particle_interpolate;
921
922 pid->write_stream = NULL;
923 pid->read_stream = NULL;
924
925 pid->write_extra_data = NULL;
926 pid->read_extra_data = NULL;
927 pid->interpolate_extra_data = NULL;
928
929 pid->write_header = ptcache_basic_header_write;
930 pid->read_header = ptcache_basic_header_read;
931
932 pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_VELOCITY) |
933 (1 << BPHYS_DATA_INDEX);
934
935 if (psys->part->phystype == PART_PHYS_BOIDS) {
936 pid->data_types |= (1 << BPHYS_DATA_AVELOCITY) | (1 << BPHYS_DATA_ROTATION) |
937 (1 << BPHYS_DATA_BOIDS);
938 }
939 else if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid &&
940 psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) {
941 pid->write_extra_data = ptcache_particle_extra_write;
942 pid->read_extra_data = ptcache_particle_extra_read;
943 }
944
945 if (psys->part->flag & PART_ROTATIONS) {
946 pid->data_types |= (1 << BPHYS_DATA_ROTATION);
947
948 if (psys->part->rotmode != PART_ROT_VEL || psys->part->avemode == PART_AVE_RAND ||
949 psys->part->avefac != 0.0f) {
950 pid->data_types |= (1 << BPHYS_DATA_AVELOCITY);
951 }
952 }
953
954 pid->info_types = (1 << BPHYS_DATA_TIMES);
955
956 pid->default_step = 1;
957 pid->max_step = 20;
958 pid->file_type = PTCACHE_FILE_PTCACHE;
959 }
BKE_ptcache_id_from_cloth(PTCacheID * pid,Object * ob,ClothModifierData * clmd)960 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
961 {
962 memset(pid, 0, sizeof(PTCacheID));
963
964 pid->owner_id = &ob->id;
965 pid->calldata = clmd;
966 pid->type = PTCACHE_TYPE_CLOTH;
967 pid->stack_index = clmd->point_cache->index;
968 pid->cache = clmd->point_cache;
969 pid->cache_ptr = &clmd->point_cache;
970 pid->ptcaches = &clmd->ptcaches;
971 pid->totpoint = pid->totwrite = ptcache_cloth_totpoint;
972 pid->error = ptcache_cloth_error;
973
974 pid->write_point = ptcache_cloth_write;
975 pid->read_point = ptcache_cloth_read;
976 pid->interpolate_point = ptcache_cloth_interpolate;
977
978 pid->write_stream = NULL;
979 pid->read_stream = NULL;
980
981 pid->write_extra_data = ptcache_cloth_extra_write;
982 pid->read_extra_data = ptcache_cloth_extra_read;
983 pid->interpolate_extra_data = NULL;
984
985 pid->write_header = ptcache_basic_header_write;
986 pid->read_header = ptcache_basic_header_read;
987
988 pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_VELOCITY) |
989 (1 << BPHYS_DATA_XCONST);
990 pid->info_types = 0;
991
992 pid->default_step = 1;
993 pid->max_step = 1;
994 pid->file_type = PTCACHE_FILE_PTCACHE;
995 }
996
997 /* The fluid modifier does not actually use this anymore, but some parts of Blender expect that it
998 * still has a point cache currently. */
BKE_ptcache_id_from_smoke(PTCacheID * pid,struct Object * ob,struct FluidModifierData * fmd)999 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct FluidModifierData *fmd)
1000 {
1001 FluidDomainSettings *fds = fmd->domain;
1002
1003 memset(pid, 0, sizeof(PTCacheID));
1004
1005 pid->owner_id = &ob->id;
1006 pid->calldata = fmd;
1007
1008 pid->type = PTCACHE_TYPE_SMOKE_DOMAIN;
1009 pid->stack_index = fds->point_cache[0]->index;
1010
1011 pid->cache = fds->point_cache[0];
1012 pid->cache_ptr = &(fds->point_cache[0]);
1013 pid->ptcaches = &(fds->ptcaches[0]);
1014 }
1015
BKE_ptcache_id_from_dynamicpaint(PTCacheID * pid,Object * ob,DynamicPaintSurface * surface)1016 void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
1017 {
1018
1019 memset(pid, 0, sizeof(PTCacheID));
1020
1021 pid->owner_id = &ob->id;
1022 pid->calldata = surface;
1023 pid->type = PTCACHE_TYPE_DYNAMICPAINT;
1024 pid->cache = surface->pointcache;
1025 pid->cache_ptr = &surface->pointcache;
1026 pid->ptcaches = &surface->ptcaches;
1027 pid->totpoint = pid->totwrite = ptcache_dynamicpaint_totpoint;
1028 pid->error = ptcache_dynamicpaint_error;
1029
1030 pid->write_point = NULL;
1031 pid->read_point = NULL;
1032 pid->interpolate_point = NULL;
1033
1034 pid->write_stream = ptcache_dynamicpaint_write;
1035 pid->read_stream = ptcache_dynamicpaint_read;
1036
1037 pid->write_extra_data = NULL;
1038 pid->read_extra_data = NULL;
1039 pid->interpolate_extra_data = NULL;
1040
1041 pid->write_header = ptcache_basic_header_write;
1042 pid->read_header = ptcache_basic_header_read;
1043
1044 pid->data_types = BPHYS_DATA_DYNAMICPAINT;
1045 pid->info_types = 0;
1046
1047 pid->stack_index = pid->cache->index;
1048
1049 pid->default_step = 1;
1050 pid->max_step = 1;
1051 pid->file_type = PTCACHE_FILE_PTCACHE;
1052 }
1053
BKE_ptcache_id_from_rigidbody(PTCacheID * pid,Object * ob,RigidBodyWorld * rbw)1054 void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
1055 {
1056
1057 memset(pid, 0, sizeof(PTCacheID));
1058
1059 pid->owner_id = ob != NULL ? &ob->id : NULL;
1060 pid->calldata = rbw;
1061 pid->type = PTCACHE_TYPE_RIGIDBODY;
1062 pid->cache = rbw->shared->pointcache;
1063 pid->cache_ptr = &rbw->shared->pointcache;
1064 pid->ptcaches = &rbw->shared->ptcaches;
1065 pid->totpoint = pid->totwrite = ptcache_rigidbody_totpoint;
1066 pid->error = ptcache_rigidbody_error;
1067
1068 pid->write_point = ptcache_rigidbody_write;
1069 pid->read_point = ptcache_rigidbody_read;
1070 pid->interpolate_point = ptcache_rigidbody_interpolate;
1071
1072 pid->write_stream = NULL;
1073 pid->read_stream = NULL;
1074
1075 pid->write_extra_data = NULL;
1076 pid->read_extra_data = NULL;
1077 pid->interpolate_extra_data = NULL;
1078
1079 pid->write_header = ptcache_basic_header_write;
1080 pid->read_header = ptcache_basic_header_read;
1081
1082 pid->data_types = (1 << BPHYS_DATA_LOCATION) | (1 << BPHYS_DATA_ROTATION);
1083 pid->info_types = 0;
1084
1085 pid->stack_index = pid->cache->index;
1086
1087 pid->default_step = 1;
1088 pid->max_step = 1;
1089 pid->file_type = PTCACHE_FILE_PTCACHE;
1090 }
1091
1092 /**
1093 * \param ob: Optional, may be NULL.
1094 * \param scene: Optional may be NULL.
1095 */
BKE_ptcache_id_find(Object * ob,Scene * scene,PointCache * cache)1096 PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
1097 {
1098 PTCacheID result = {0};
1099
1100 ListBase pidlist;
1101 BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
1102
1103 LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
1104 if (pid->cache == cache) {
1105 result = *pid;
1106 break;
1107 }
1108 }
1109
1110 BLI_freelistN(&pidlist);
1111
1112 return result;
1113 }
1114
1115 /* Callback which is used by point cache foreach() family of functions.
1116 *
1117 * Receives ID of the point cache.
1118 *
1119 * NOTE: This ID is owned by foreach() routines and can not be used outside of
1120 * the foreach loop. This means that if one wants to store them those are to be
1121 * malloced and copied over.
1122 *
1123 * If the function returns false, then foreach() loop aborts.
1124 */
1125 typedef bool (*ForeachPtcacheCb)(PTCacheID *pid, void *userdata);
1126
foreach_object_particle_ptcache(Object * object,ForeachPtcacheCb callback,void * callback_user_data)1127 static bool foreach_object_particle_ptcache(Object *object,
1128 ForeachPtcacheCb callback,
1129 void *callback_user_data)
1130 {
1131 PTCacheID pid;
1132 for (ParticleSystem *psys = object->particlesystem.first; psys != NULL; psys = psys->next) {
1133 if (psys->part == NULL) {
1134 continue;
1135 }
1136 /* Check to make sure point cache is actually used by the particles. */
1137 if (ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
1138 continue;
1139 }
1140 /* Hair needs to be included in id-list for cache edit mode to work. */
1141 #if 0
1142 if ((psys->part->type == PART_HAIR) && (psys->flag & PSYS_HAIR_DYNAMICS) == 0) {
1143 continue;
1144 }
1145 #endif
1146 if (psys->part->type == PART_FLUID) {
1147 continue;
1148 }
1149 BKE_ptcache_id_from_particles(&pid, object, psys);
1150 if (!callback(&pid, callback_user_data)) {
1151 return false;
1152 }
1153 }
1154 return true;
1155 }
1156
foreach_object_modifier_ptcache(Object * object,ForeachPtcacheCb callback,void * callback_user_data)1157 static bool foreach_object_modifier_ptcache(Object *object,
1158 ForeachPtcacheCb callback,
1159 void *callback_user_data)
1160 {
1161 PTCacheID pid;
1162 for (ModifierData *md = object->modifiers.first; md != NULL; md = md->next) {
1163 if (md->type == eModifierType_Cloth) {
1164 BKE_ptcache_id_from_cloth(&pid, object, (ClothModifierData *)md);
1165 if (!callback(&pid, callback_user_data)) {
1166 return false;
1167 }
1168 }
1169 else if (md->type == eModifierType_Fluid) {
1170 FluidModifierData *fmd = (FluidModifierData *)md;
1171 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
1172 BKE_ptcache_id_from_smoke(&pid, object, (FluidModifierData *)md);
1173 if (!callback(&pid, callback_user_data)) {
1174 return false;
1175 }
1176 }
1177 }
1178 else if (md->type == eModifierType_DynamicPaint) {
1179 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
1180 if (pmd->canvas) {
1181 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
1182 for (; surface; surface = surface->next) {
1183 BKE_ptcache_id_from_dynamicpaint(&pid, object, surface);
1184 if (!callback(&pid, callback_user_data)) {
1185 return false;
1186 }
1187 }
1188 }
1189 }
1190 else if (md->type == eModifierType_Simulation) {
1191 /* TODO(jacques): */
1192 }
1193 }
1194 return true;
1195 }
1196
1197 /* Return false if any of callbacks returned false. */
foreach_object_ptcache(Scene * scene,Object * object,int duplis,ForeachPtcacheCb callback,void * callback_user_data)1198 static bool foreach_object_ptcache(
1199 Scene *scene, Object *object, int duplis, ForeachPtcacheCb callback, void *callback_user_data)
1200 {
1201 PTCacheID pid;
1202
1203 if (object != NULL) {
1204 /* Soft body. */
1205 if (object->soft != NULL) {
1206 BKE_ptcache_id_from_softbody(&pid, object, object->soft);
1207 if (!callback(&pid, callback_user_data)) {
1208 return false;
1209 }
1210 }
1211 /* Particle systems. */
1212 if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) {
1213 return false;
1214 }
1215 /* Modifiers. */
1216 if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) {
1217 return false;
1218 }
1219 /* Consider all object in dupli-groups to be part of the same object,
1220 * for baking with linking dupli-groups. Once we have better overrides
1221 * this can be revisited so users select the local objects directly. */
1222 if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) {
1223 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (object->instance_collection, current_object) {
1224 if (current_object == object) {
1225 continue;
1226 }
1227 foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data);
1228 }
1229 FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
1230 }
1231 }
1232
1233 /* Rigid body. */
1234 if (scene != NULL && (object == NULL || object->rigidbody_object != NULL) &&
1235 scene->rigidbody_world != NULL) {
1236 BKE_ptcache_id_from_rigidbody(&pid, object, scene->rigidbody_world);
1237 if (!callback(&pid, callback_user_data)) {
1238 return false;
1239 }
1240 }
1241 return true;
1242 }
1243
1244 typedef struct PTCacheIDsFromObjectData {
1245 ListBase *list_base;
1246 } PTCacheIDsFromObjectData;
1247
ptcache_ids_from_object_cb(PTCacheID * pid,void * userdata)1248 static bool ptcache_ids_from_object_cb(PTCacheID *pid, void *userdata)
1249 {
1250 PTCacheIDsFromObjectData *data = userdata;
1251 PTCacheID *own_pid = MEM_mallocN(sizeof(PTCacheID), "PTCacheID");
1252 *own_pid = *pid;
1253 BLI_addtail(data->list_base, own_pid);
1254 return true;
1255 }
1256
BKE_ptcache_ids_from_object(ListBase * lb,Object * ob,Scene * scene,int duplis)1257 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
1258 {
1259 PTCacheIDsFromObjectData data;
1260 lb->first = lb->last = NULL;
1261 data.list_base = lb;
1262 foreach_object_ptcache(scene, ob, duplis, ptcache_ids_from_object_cb, &data);
1263 }
1264
ptcache_object_has_cb(PTCacheID * UNUSED (pid),void * UNUSED (userdata))1265 static bool ptcache_object_has_cb(PTCacheID *UNUSED(pid), void *UNUSED(userdata))
1266 {
1267 return false;
1268 }
1269
BKE_ptcache_object_has(struct Scene * scene,struct Object * ob,int duplis)1270 bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis)
1271 {
1272 return !foreach_object_ptcache(scene, ob, duplis, ptcache_object_has_cb, NULL);
1273 }
1274
1275 /* File handling */
1276
ptcache_file_extension(const PTCacheID * pid)1277 static const char *ptcache_file_extension(const PTCacheID *pid)
1278 {
1279 switch (pid->file_type) {
1280 default:
1281 case PTCACHE_FILE_PTCACHE:
1282 return PTCACHE_EXT;
1283 }
1284 }
1285
1286 /**
1287 * Similar to #BLI_path_frame_get, but takes into account the stack-index which is after the frame.
1288 */
ptcache_frame_from_filename(const char * filename,const char * ext)1289 static int ptcache_frame_from_filename(const char *filename, const char *ext)
1290 {
1291 const int frame_len = 6;
1292 const int ext_len = frame_len + strlen(ext);
1293 const int len = strlen(filename);
1294
1295 /* could crash if trying to copy a string out of this range */
1296 if (len > ext_len) {
1297 /* using frame_len here gives compile error (vla) */
1298 char num[/* frame_len */ 6 + 1];
1299 BLI_strncpy(num, filename + len - ext_len, sizeof(num));
1300
1301 return atoi(num);
1302 }
1303
1304 return -1;
1305 }
1306
1307 /* Takes an Object ID and returns a unique name
1308 * - id: object id
1309 * - cfra: frame for the cache, can be negative
1310 * - stack_index: index in the modifier stack. we can have cache for more than one stack_index
1311 */
1312
1313 #define MAX_PTCACHE_PATH FILE_MAX
1314 #define MAX_PTCACHE_FILE (FILE_MAX * 2)
1315
ptcache_path(PTCacheID * pid,char * filename)1316 static int ptcache_path(PTCacheID *pid, char *filename)
1317 {
1318 Library *lib = (pid->owner_id) ? pid->owner_id->lib : NULL;
1319 const char *blendfilename = (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH) == 0) ?
1320 lib->filepath_abs :
1321 BKE_main_blendfile_path_from_global();
1322 size_t i;
1323
1324 if (pid->cache->flag & PTCACHE_EXTERNAL) {
1325 strcpy(filename, pid->cache->path);
1326
1327 if (BLI_path_is_rel(filename)) {
1328 BLI_path_abs(filename, blendfilename);
1329 }
1330
1331 return BLI_path_slash_ensure(filename); /* new strlen() */
1332 }
1333 if (G.relbase_valid || lib) {
1334 char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
1335
1336 BLI_split_file_part(blendfilename, file, sizeof(file));
1337 i = strlen(file);
1338
1339 /* remove .blend */
1340 if (i > 6) {
1341 file[i - 6] = '\0';
1342 }
1343
1344 /* Add blend file name to pointcache dir. */
1345 BLI_snprintf(filename, MAX_PTCACHE_PATH, "//" PTCACHE_PATH "%s", file);
1346
1347 BLI_path_abs(filename, blendfilename);
1348 return BLI_path_slash_ensure(filename); /* new strlen() */
1349 }
1350
1351 /* use the temp path. this is weak but better than not using point cache at all */
1352 /* temporary directory is assumed to exist and ALWAYS has a trailing slash */
1353 BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s" PTCACHE_PATH, BKE_tempdir_session());
1354
1355 return BLI_path_slash_ensure(filename); /* new strlen() */
1356 }
1357
ptcache_filename(PTCacheID * pid,char * filename,int cfra,short do_path,short do_ext)1358 static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
1359 {
1360 int len = 0;
1361 char *idname;
1362 char *newname;
1363 filename[0] = '\0';
1364 newname = filename;
1365
1366 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
1367 return 0; /* save blend file before using disk pointcache */
1368 }
1369
1370 /* start with temp dir */
1371 if (do_path) {
1372 len = ptcache_path(pid, filename);
1373 newname += len;
1374 }
1375 if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
1376 idname = (pid->owner_id->name + 2);
1377 /* convert chars to hex so they are always a valid filename */
1378 while ('\0' != *idname) {
1379 BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (unsigned int)(*idname++));
1380 newname += 2;
1381 len += 2;
1382 }
1383 }
1384 else {
1385 int temp = (int)strlen(pid->cache->name);
1386 strcpy(newname, pid->cache->name);
1387 newname += temp;
1388 len += temp;
1389 }
1390
1391 if (do_ext) {
1392 if (pid->cache->index < 0) {
1393 BLI_assert(GS(pid->owner_id->name) == ID_OB);
1394 pid->cache->index = pid->stack_index = BKE_object_insert_ptcache((Object *)pid->owner_id);
1395 }
1396
1397 const char *ext = ptcache_file_extension(pid);
1398
1399 if (pid->cache->flag & PTCACHE_EXTERNAL) {
1400 if (pid->cache->index >= 0) {
1401 /* Always 6 chars. */
1402 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext);
1403 }
1404 else {
1405 /* Always 6 chars. */
1406 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d%s", cfra, ext);
1407 }
1408 }
1409 else {
1410 /* Always 6 chars. */
1411 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext);
1412 }
1413 len += 16;
1414 }
1415
1416 return len; /* make sure the above string is always 16 chars */
1417 }
1418
1419 /**
1420 * Caller must close after!
1421 */
ptcache_file_open(PTCacheID * pid,int mode,int cfra)1422 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
1423 {
1424 PTCacheFile *pf;
1425 FILE *fp = NULL;
1426 char filename[FILE_MAX * 2];
1427
1428 #ifndef DURIAN_POINTCACHE_LIB_OK
1429 /* don't allow writing for linked objects */
1430 if (pid->owner_id->lib && mode == PTCACHE_FILE_WRITE) {
1431 return NULL;
1432 }
1433 #endif
1434 if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0) {
1435 return NULL; /* save blend file before using disk pointcache */
1436 }
1437
1438 ptcache_filename(pid, filename, cfra, 1, 1);
1439
1440 if (mode == PTCACHE_FILE_READ) {
1441 fp = BLI_fopen(filename, "rb");
1442 }
1443 else if (mode == PTCACHE_FILE_WRITE) {
1444 /* Will create the dir if needs be, same as "//textures" is created. */
1445 BLI_make_existing_file(filename);
1446
1447 fp = BLI_fopen(filename, "wb");
1448 }
1449 else if (mode == PTCACHE_FILE_UPDATE) {
1450 BLI_make_existing_file(filename);
1451 fp = BLI_fopen(filename, "rb+");
1452 }
1453
1454 if (!fp) {
1455 return NULL;
1456 }
1457
1458 pf = MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
1459 pf->fp = fp;
1460 pf->old_format = 0;
1461 pf->frame = cfra;
1462
1463 return pf;
1464 }
ptcache_file_close(PTCacheFile * pf)1465 static void ptcache_file_close(PTCacheFile *pf)
1466 {
1467 if (pf) {
1468 fclose(pf->fp);
1469 MEM_freeN(pf);
1470 }
1471 }
1472
ptcache_file_compressed_read(PTCacheFile * pf,unsigned char * result,unsigned int len)1473 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
1474 {
1475 int r = 0;
1476 unsigned char compressed = 0;
1477 size_t in_len;
1478 #ifdef WITH_LZO
1479 size_t out_len = len;
1480 #endif
1481 unsigned char *in;
1482 unsigned char *props = MEM_callocN(sizeof(char[16]), "tmp");
1483
1484 ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
1485 if (compressed) {
1486 unsigned int size;
1487 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1488 in_len = (size_t)size;
1489 if (in_len == 0) {
1490 /* do nothing */
1491 }
1492 else {
1493 in = (unsigned char *)MEM_callocN(sizeof(unsigned char) * in_len,
1494 "pointcache_compressed_buffer");
1495 ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
1496 #ifdef WITH_LZO
1497 if (compressed == 1) {
1498 r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
1499 }
1500 #endif
1501 #ifdef WITH_LZMA
1502 if (compressed == 2) {
1503 size_t sizeOfIt;
1504 size_t leni = in_len, leno = len;
1505 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
1506 sizeOfIt = (size_t)size;
1507 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
1508 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
1509 }
1510 #endif
1511 MEM_freeN(in);
1512 }
1513 }
1514 else {
1515 ptcache_file_read(pf, result, len, sizeof(unsigned char));
1516 }
1517
1518 MEM_freeN(props);
1519
1520 return r;
1521 }
ptcache_file_compressed_write(PTCacheFile * pf,unsigned char * in,unsigned int in_len,unsigned char * out,int mode)1522 static int ptcache_file_compressed_write(
1523 PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
1524 {
1525 int r = 0;
1526 unsigned char compressed = 0;
1527 size_t out_len = 0;
1528 unsigned char *props = MEM_callocN(sizeof(char[16]), "tmp");
1529 size_t sizeOfIt = 5;
1530
1531 (void)mode; /* unused when building w/o compression */
1532
1533 #ifdef WITH_LZO
1534 out_len = LZO_OUT_LEN(in_len);
1535 if (mode == 1) {
1536 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
1537
1538 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
1539 if (!(r == LZO_E_OK) || (out_len >= in_len)) {
1540 compressed = 0;
1541 }
1542 else {
1543 compressed = 1;
1544 }
1545 }
1546 #endif
1547 #ifdef WITH_LZMA
1548 if (mode == 2) {
1549
1550 r = LzmaCompress(out,
1551 &out_len,
1552 in,
1553 in_len, /* assume sizeof(char)==1.... */
1554 props,
1555 &sizeOfIt,
1556 5,
1557 1 << 24,
1558 3,
1559 0,
1560 2,
1561 32,
1562 2);
1563
1564 if (!(r == SZ_OK) || (out_len >= in_len)) {
1565 compressed = 0;
1566 }
1567 else {
1568 compressed = 2;
1569 }
1570 }
1571 #endif
1572
1573 ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
1574 if (compressed) {
1575 unsigned int size = out_len;
1576 ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
1577 ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
1578 }
1579 else {
1580 ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
1581 }
1582
1583 if (compressed == 2) {
1584 unsigned int size = sizeOfIt;
1585 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
1586 ptcache_file_write(pf, props, size, sizeof(unsigned char));
1587 }
1588
1589 MEM_freeN(props);
1590
1591 return r;
1592 }
ptcache_file_read(PTCacheFile * pf,void * f,unsigned int tot,unsigned int size)1593 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
1594 {
1595 return (fread(f, size, tot, pf->fp) == tot);
1596 }
ptcache_file_write(PTCacheFile * pf,const void * f,unsigned int tot,unsigned int size)1597 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size)
1598 {
1599 return (fwrite(f, size, tot, pf->fp) == tot);
1600 }
ptcache_file_data_read(PTCacheFile * pf)1601 static int ptcache_file_data_read(PTCacheFile *pf)
1602 {
1603 int i;
1604
1605 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1606 if ((pf->data_types & (1 << i)) &&
1607 !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) {
1608 return 0;
1609 }
1610 }
1611
1612 return 1;
1613 }
ptcache_file_data_write(PTCacheFile * pf)1614 static int ptcache_file_data_write(PTCacheFile *pf)
1615 {
1616 int i;
1617
1618 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1619 if ((pf->data_types & (1 << i)) &&
1620 !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) {
1621 return 0;
1622 }
1623 }
1624
1625 return 1;
1626 }
ptcache_file_header_begin_read(PTCacheFile * pf)1627 static int ptcache_file_header_begin_read(PTCacheFile *pf)
1628 {
1629 unsigned int typeflag = 0;
1630 int error = 0;
1631 char bphysics[8];
1632
1633 pf->data_types = 0;
1634
1635 if (fread(bphysics, sizeof(char), 8, pf->fp) != 8) {
1636 error = 1;
1637 }
1638
1639 if (!error && !STREQLEN(bphysics, "BPHYSICS", 8)) {
1640 error = 1;
1641 }
1642
1643 if (!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp)) {
1644 error = 1;
1645 }
1646
1647 pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
1648 pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
1649
1650 /* if there was an error set file as it was */
1651 if (error) {
1652 BLI_fseek(pf->fp, 0, SEEK_SET);
1653 }
1654
1655 return !error;
1656 }
ptcache_file_header_begin_write(PTCacheFile * pf)1657 static int ptcache_file_header_begin_write(PTCacheFile *pf)
1658 {
1659 const char *bphysics = "BPHYSICS";
1660 unsigned int typeflag = pf->type + pf->flag;
1661
1662 if (fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) {
1663 return 0;
1664 }
1665
1666 if (!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp)) {
1667 return 0;
1668 }
1669
1670 return 1;
1671 }
1672
1673 /* Data pointer handling */
BKE_ptcache_data_size(int data_type)1674 int BKE_ptcache_data_size(int data_type)
1675 {
1676 return ptcache_data_size[data_type];
1677 }
1678
ptcache_file_pointers_init(PTCacheFile * pf)1679 static void ptcache_file_pointers_init(PTCacheFile *pf)
1680 {
1681 int data_types = pf->data_types;
1682
1683 pf->cur[BPHYS_DATA_INDEX] = (data_types & (1 << BPHYS_DATA_INDEX)) ? &pf->data.index : NULL;
1684 pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1 << BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL;
1685 pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1 << BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL;
1686 pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1 << BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL;
1687 pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1 << BPHYS_DATA_AVELOCITY)) ? &pf->data.ave :
1688 NULL;
1689 pf->cur[BPHYS_DATA_SIZE] = (data_types & (1 << BPHYS_DATA_SIZE)) ? &pf->data.size : NULL;
1690 pf->cur[BPHYS_DATA_TIMES] = (data_types & (1 << BPHYS_DATA_TIMES)) ? &pf->data.times : NULL;
1691 pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1 << BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL;
1692 }
1693
1694 /* Check to see if point number "index" is in pm, uses binary search for index data. */
BKE_ptcache_mem_index_find(PTCacheMem * pm,unsigned int index)1695 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
1696 {
1697 if (pm->totpoint > 0 && pm->data[BPHYS_DATA_INDEX]) {
1698 unsigned int *data = pm->data[BPHYS_DATA_INDEX];
1699 unsigned int mid, low = 0, high = pm->totpoint - 1;
1700
1701 if (index < *data || index > *(data + high)) {
1702 return -1;
1703 }
1704
1705 /* check simple case for continuous indexes first */
1706 if (index - *data < high && data[index - *data] == index) {
1707 return index - *data;
1708 }
1709
1710 while (low <= high) {
1711 mid = (low + high) / 2;
1712
1713 if (data[mid] > index) {
1714 high = mid - 1;
1715 }
1716 else if (data[mid] < index) {
1717 low = mid + 1;
1718 }
1719 else {
1720 return mid;
1721 }
1722 }
1723
1724 return -1;
1725 }
1726
1727 return (index < pm->totpoint ? index : -1);
1728 }
1729
BKE_ptcache_mem_pointers_init(PTCacheMem * pm,void * cur[BPHYS_TOT_DATA])1730 void BKE_ptcache_mem_pointers_init(PTCacheMem *pm, void *cur[BPHYS_TOT_DATA])
1731 {
1732 int data_types = pm->data_types;
1733 int i;
1734
1735 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1736 cur[i] = ((data_types & (1 << i)) ? pm->data[i] : NULL);
1737 }
1738 }
1739
BKE_ptcache_mem_pointers_incr(void * cur[BPHYS_TOT_DATA])1740 void BKE_ptcache_mem_pointers_incr(void *cur[BPHYS_TOT_DATA])
1741 {
1742 int i;
1743
1744 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1745 if (cur[i]) {
1746 cur[i] = (char *)cur[i] + ptcache_data_size[i];
1747 }
1748 }
1749 }
BKE_ptcache_mem_pointers_seek(int point_index,PTCacheMem * pm,void * cur[BPHYS_TOT_DATA])1750 int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm, void *cur[BPHYS_TOT_DATA])
1751 {
1752 int data_types = pm->data_types;
1753 int i, index = BKE_ptcache_mem_index_find(pm, point_index);
1754
1755 if (index < 0) {
1756 /* Can't give proper location without reallocation, so don't give any location.
1757 * Some points will be cached improperly, but this only happens with simulation
1758 * steps bigger than cache->step, so the cache has to be recalculated anyways
1759 * at some point.
1760 */
1761 return 0;
1762 }
1763
1764 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1765 cur[i] = data_types & (1 << i) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL;
1766 }
1767
1768 return 1;
1769 }
ptcache_data_alloc(PTCacheMem * pm)1770 static void ptcache_data_alloc(PTCacheMem *pm)
1771 {
1772 int data_types = pm->data_types;
1773 int totpoint = pm->totpoint;
1774 int i;
1775
1776 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1777 if (data_types & (1 << i)) {
1778 pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
1779 }
1780 }
1781 }
ptcache_data_free(PTCacheMem * pm)1782 static void ptcache_data_free(PTCacheMem *pm)
1783 {
1784 void **data = pm->data;
1785 int i;
1786
1787 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1788 if (data[i]) {
1789 MEM_freeN(data[i]);
1790 }
1791 }
1792 }
ptcache_data_copy(void * from[],void * to[])1793 static void ptcache_data_copy(void *from[], void *to[])
1794 {
1795 int i;
1796 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1797 /* note, durian file 03.4b_comp crashes if to[i] is not tested
1798 * its NULL, not sure if this should be fixed elsewhere but for now its needed */
1799 if (from[i] && to[i]) {
1800 memcpy(to[i], from[i], ptcache_data_size[i]);
1801 }
1802 }
1803 }
1804
ptcache_extra_free(PTCacheMem * pm)1805 static void ptcache_extra_free(PTCacheMem *pm)
1806 {
1807 PTCacheExtra *extra = pm->extradata.first;
1808
1809 if (extra) {
1810 for (; extra; extra = extra->next) {
1811 if (extra->data) {
1812 MEM_freeN(extra->data);
1813 }
1814 }
1815
1816 BLI_freelistN(&pm->extradata);
1817 }
1818 }
1819
ptcache_mem_clear(PTCacheMem * pm)1820 static void ptcache_mem_clear(PTCacheMem *pm)
1821 {
1822 ptcache_data_free(pm);
1823 ptcache_extra_free(pm);
1824 }
1825
ptcache_old_elemsize(PTCacheID * pid)1826 static int ptcache_old_elemsize(PTCacheID *pid)
1827 {
1828 if (pid->type == PTCACHE_TYPE_SOFTBODY) {
1829 return sizeof(float[6]);
1830 }
1831 if (pid->type == PTCACHE_TYPE_PARTICLES) {
1832 return sizeof(ParticleKey);
1833 }
1834 if (pid->type == PTCACHE_TYPE_CLOTH) {
1835 return sizeof(float[9]);
1836 }
1837
1838 return 0;
1839 }
1840
ptcache_find_frames_around(PTCacheID * pid,unsigned int frame,int * fra1,int * fra2)1841 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
1842 {
1843 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
1844 int cfra1 = frame, cfra2 = frame + 1;
1845
1846 while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) {
1847 cfra1--;
1848 }
1849
1850 if (cfra1 < pid->cache->startframe) {
1851 cfra1 = 0;
1852 }
1853
1854 while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) {
1855 cfra2++;
1856 }
1857
1858 if (cfra2 > pid->cache->endframe) {
1859 cfra2 = 0;
1860 }
1861
1862 if (cfra1 && !cfra2) {
1863 *fra1 = 0;
1864 *fra2 = cfra1;
1865 }
1866 else {
1867 *fra1 = cfra1;
1868 *fra2 = cfra2;
1869 }
1870 }
1871 else if (pid->cache->mem_cache.first) {
1872 PTCacheMem *pm = pid->cache->mem_cache.first;
1873 PTCacheMem *pm2 = pid->cache->mem_cache.last;
1874
1875 while (pm->next && pm->next->frame <= frame) {
1876 pm = pm->next;
1877 }
1878
1879 if (pm2->frame < frame) {
1880 pm2 = NULL;
1881 }
1882 else {
1883 while (pm2->prev && pm2->prev->frame > frame) {
1884 pm2 = pm2->prev;
1885 }
1886 }
1887
1888 if (!pm2) {
1889 *fra1 = 0;
1890 *fra2 = pm->frame;
1891 }
1892 else {
1893 *fra1 = pm->frame;
1894 *fra2 = pm2->frame;
1895 }
1896 }
1897 }
1898
ptcache_disk_frame_to_mem(PTCacheID * pid,int cfra)1899 static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
1900 {
1901 PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
1902 PTCacheMem *pm = NULL;
1903 unsigned int i, error = 0;
1904
1905 if (pf == NULL) {
1906 return NULL;
1907 }
1908
1909 if (!ptcache_file_header_begin_read(pf)) {
1910 error = 1;
1911 }
1912
1913 if (!error && (pf->type != pid->type || !pid->read_header(pf))) {
1914 error = 1;
1915 }
1916
1917 if (!error) {
1918 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
1919
1920 pm->totpoint = pf->totpoint;
1921 pm->data_types = pf->data_types;
1922 pm->frame = pf->frame;
1923
1924 ptcache_data_alloc(pm);
1925
1926 if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
1927 for (i = 0; i < BPHYS_TOT_DATA; i++) {
1928 unsigned int out_len = pm->totpoint * ptcache_data_size[i];
1929 if (pf->data_types & (1 << i)) {
1930 ptcache_file_compressed_read(pf, (unsigned char *)(pm->data[i]), out_len);
1931 }
1932 }
1933 }
1934 else {
1935 void *cur[BPHYS_TOT_DATA];
1936 BKE_ptcache_mem_pointers_init(pm, cur);
1937 ptcache_file_pointers_init(pf);
1938
1939 for (i = 0; i < pm->totpoint; i++) {
1940 if (!ptcache_file_data_read(pf)) {
1941 error = 1;
1942 break;
1943 }
1944 ptcache_data_copy(pf->cur, cur);
1945 BKE_ptcache_mem_pointers_incr(cur);
1946 }
1947 }
1948 }
1949
1950 if (!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) {
1951 unsigned int extratype = 0;
1952
1953 while (ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) {
1954 PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata");
1955
1956 extra->type = extratype;
1957
1958 ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int));
1959
1960 extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type],
1961 "Pointcache extradata->data");
1962
1963 if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
1964 ptcache_file_compressed_read(pf,
1965 (unsigned char *)(extra->data),
1966 extra->totdata * ptcache_extra_datasize[extra->type]);
1967 }
1968 else {
1969 ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
1970 }
1971
1972 BLI_addtail(&pm->extradata, extra);
1973 }
1974 }
1975
1976 if (error && pm) {
1977 ptcache_mem_clear(pm);
1978 MEM_freeN(pm);
1979 pm = NULL;
1980 }
1981
1982 ptcache_file_close(pf);
1983
1984 if (error && G.debug & G_DEBUG) {
1985 printf("Error reading from disk cache\n");
1986 }
1987
1988 return pm;
1989 }
ptcache_mem_frame_to_disk(PTCacheID * pid,PTCacheMem * pm)1990 static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
1991 {
1992 PTCacheFile *pf = NULL;
1993 unsigned int i, error = 0;
1994
1995 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame);
1996
1997 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
1998
1999 if (pf == NULL) {
2000 if (G.debug & G_DEBUG) {
2001 printf("Error opening disk cache file for writing\n");
2002 }
2003 return 0;
2004 }
2005
2006 pf->data_types = pm->data_types;
2007 pf->totpoint = pm->totpoint;
2008 pf->type = pid->type;
2009 pf->flag = 0;
2010
2011 if (pm->extradata.first) {
2012 pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
2013 }
2014
2015 if (pid->cache->compression) {
2016 pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
2017 }
2018
2019 if (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) {
2020 error = 1;
2021 }
2022
2023 if (!error) {
2024 if (pid->cache->compression) {
2025 for (i = 0; i < BPHYS_TOT_DATA; i++) {
2026 if (pm->data[i]) {
2027 unsigned int in_len = pm->totpoint * ptcache_data_size[i];
2028 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4,
2029 "pointcache_lzo_buffer");
2030 ptcache_file_compressed_write(
2031 pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression);
2032 MEM_freeN(out);
2033 }
2034 }
2035 }
2036 else {
2037 void *cur[BPHYS_TOT_DATA];
2038 BKE_ptcache_mem_pointers_init(pm, cur);
2039 ptcache_file_pointers_init(pf);
2040
2041 for (i = 0; i < pm->totpoint; i++) {
2042 ptcache_data_copy(cur, pf->cur);
2043 if (!ptcache_file_data_write(pf)) {
2044 error = 1;
2045 break;
2046 }
2047 BKE_ptcache_mem_pointers_incr(cur);
2048 }
2049 }
2050 }
2051
2052 if (!error && pm->extradata.first) {
2053 PTCacheExtra *extra = pm->extradata.first;
2054
2055 for (; extra; extra = extra->next) {
2056 if (extra->data == NULL || extra->totdata == 0) {
2057 continue;
2058 }
2059
2060 ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
2061 ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
2062
2063 if (pid->cache->compression) {
2064 unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
2065 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4,
2066 "pointcache_lzo_buffer");
2067 ptcache_file_compressed_write(
2068 pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression);
2069 MEM_freeN(out);
2070 }
2071 else {
2072 ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
2073 }
2074 }
2075 }
2076
2077 ptcache_file_close(pf);
2078
2079 if (error && G.debug & G_DEBUG) {
2080 printf("Error writing to disk cache\n");
2081 }
2082
2083 return error == 0;
2084 }
2085
ptcache_read_stream(PTCacheID * pid,int cfra)2086 static int ptcache_read_stream(PTCacheID *pid, int cfra)
2087 {
2088 PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
2089 int error = 0;
2090
2091 if (pid->read_stream == NULL) {
2092 return 0;
2093 }
2094
2095 if (pf == NULL) {
2096 if (G.debug & G_DEBUG) {
2097 printf("Error opening disk cache file for reading\n");
2098 }
2099 return 0;
2100 }
2101
2102 if (!ptcache_file_header_begin_read(pf)) {
2103 pid->error(pid->calldata, "Failed to read point cache file");
2104 error = 1;
2105 }
2106 else if (pf->type != pid->type) {
2107 pid->error(pid->calldata, "Point cache file has wrong type");
2108 error = 1;
2109 }
2110 else if (!pid->read_header(pf)) {
2111 pid->error(pid->calldata, "Failed to read point cache file header");
2112 error = 1;
2113 }
2114 else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) {
2115 pid->error(pid->calldata, "Number of points in cache does not match mesh");
2116 error = 1;
2117 }
2118
2119 if (!error) {
2120 ptcache_file_pointers_init(pf);
2121
2122 /* We have stream reading here. */
2123 if (!pid->read_stream(pf, pid->calldata)) {
2124 pid->error(pid->calldata, "Failed to read point cache file data");
2125 error = 1;
2126 }
2127 }
2128
2129 ptcache_file_close(pf);
2130
2131 return error == 0;
2132 }
2133
ptcache_read(PTCacheID * pid,int cfra)2134 static int ptcache_read(PTCacheID *pid, int cfra)
2135 {
2136 PTCacheMem *pm = NULL;
2137 int i;
2138 int *index = &i;
2139
2140 /* get a memory cache to read from */
2141 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2142 pm = ptcache_disk_frame_to_mem(pid, cfra);
2143 }
2144 else {
2145 pm = pid->cache->mem_cache.first;
2146
2147 while (pm && pm->frame != cfra) {
2148 pm = pm->next;
2149 }
2150 }
2151
2152 /* read the cache */
2153 if (pm) {
2154 int totpoint = pm->totpoint;
2155
2156 if ((pid->data_types & (1 << BPHYS_DATA_INDEX)) == 0) {
2157 int pid_totpoint = pid->totpoint(pid->calldata, cfra);
2158
2159 if (totpoint != pid_totpoint) {
2160 pid->error(pid->calldata, "Number of points in cache does not match mesh");
2161 totpoint = MIN2(totpoint, pid_totpoint);
2162 }
2163 }
2164
2165 void *cur[BPHYS_TOT_DATA];
2166 BKE_ptcache_mem_pointers_init(pm, cur);
2167
2168 for (i = 0; i < totpoint; i++) {
2169 if (pm->data_types & (1 << BPHYS_DATA_INDEX)) {
2170 index = cur[BPHYS_DATA_INDEX];
2171 }
2172
2173 pid->read_point(*index, pid->calldata, cur, (float)pm->frame, NULL);
2174
2175 BKE_ptcache_mem_pointers_incr(cur);
2176 }
2177
2178 if (pid->read_extra_data && pm->extradata.first) {
2179 pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
2180 }
2181
2182 /* clean up temporary memory cache */
2183 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2184 ptcache_mem_clear(pm);
2185 MEM_freeN(pm);
2186 }
2187 }
2188
2189 return 1;
2190 }
ptcache_interpolate(PTCacheID * pid,float cfra,int cfra1,int cfra2)2191 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
2192 {
2193 PTCacheMem *pm = NULL;
2194 int i;
2195 int *index = &i;
2196
2197 /* get a memory cache to read from */
2198 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2199 pm = ptcache_disk_frame_to_mem(pid, cfra2);
2200 }
2201 else {
2202 pm = pid->cache->mem_cache.first;
2203
2204 while (pm && pm->frame != cfra2) {
2205 pm = pm->next;
2206 }
2207 }
2208
2209 /* read the cache */
2210 if (pm) {
2211 int totpoint = pm->totpoint;
2212
2213 if ((pid->data_types & (1 << BPHYS_DATA_INDEX)) == 0) {
2214 int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra);
2215
2216 if (totpoint != pid_totpoint) {
2217 pid->error(pid->calldata, "Number of points in cache does not match mesh");
2218 totpoint = MIN2(totpoint, pid_totpoint);
2219 }
2220 }
2221
2222 void *cur[BPHYS_TOT_DATA];
2223 BKE_ptcache_mem_pointers_init(pm, cur);
2224
2225 for (i = 0; i < totpoint; i++) {
2226 if (pm->data_types & (1 << BPHYS_DATA_INDEX)) {
2227 index = cur[BPHYS_DATA_INDEX];
2228 }
2229
2230 pid->interpolate_point(*index, pid->calldata, cur, cfra, (float)cfra1, (float)cfra2, NULL);
2231 BKE_ptcache_mem_pointers_incr(cur);
2232 }
2233
2234 if (pid->interpolate_extra_data && pm->extradata.first) {
2235 pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
2236 }
2237
2238 /* clean up temporary memory cache */
2239 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2240 ptcache_mem_clear(pm);
2241 MEM_freeN(pm);
2242 }
2243 }
2244
2245 return 1;
2246 }
2247 /* reads cache from disk or memory */
2248 /* possible to get old or interpolated result */
BKE_ptcache_read(PTCacheID * pid,float cfra,bool no_extrapolate_old)2249 int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
2250 {
2251 int cfrai = (int)floor(cfra), cfra1 = 0, cfra2 = 0;
2252 int ret = 0;
2253
2254 /* nothing to read to */
2255 if (pid->totpoint(pid->calldata, cfrai) == 0) {
2256 return 0;
2257 }
2258
2259 if (pid->cache->flag & PTCACHE_READ_INFO) {
2260 pid->cache->flag &= ~PTCACHE_READ_INFO;
2261 ptcache_read(pid, 0);
2262 }
2263
2264 /* first check if we have the actual frame cached */
2265 if (cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai)) {
2266 cfra1 = cfrai;
2267 }
2268
2269 /* no exact cache frame found so try to find cached frames around cfra */
2270 if (cfra1 == 0) {
2271 ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
2272 }
2273
2274 if (cfra1 == 0 && cfra2 == 0) {
2275 return 0;
2276 }
2277
2278 /* don't read old cache if already simulated past cached frame */
2279 if (no_extrapolate_old) {
2280 if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) {
2281 return 0;
2282 }
2283 if (cfra1 && cfra1 == cfra2) {
2284 return 0;
2285 }
2286 }
2287 else {
2288 /* avoid calling interpolate between the same frame values */
2289 if (cfra1 && cfra1 == cfra2) {
2290 cfra1 = 0;
2291 }
2292 }
2293
2294 if (cfra1) {
2295 if (pid->read_stream) {
2296 if (!ptcache_read_stream(pid, cfra1)) {
2297 return 0;
2298 }
2299 }
2300 else if (pid->read_point) {
2301 ptcache_read(pid, cfra1);
2302 }
2303 }
2304
2305 if (cfra2) {
2306 if (pid->read_stream) {
2307 if (!ptcache_read_stream(pid, cfra2)) {
2308 return 0;
2309 }
2310 }
2311 else if (pid->read_point) {
2312 if (cfra1 && cfra2 && pid->interpolate_point) {
2313 ptcache_interpolate(pid, cfra, cfra1, cfra2);
2314 }
2315 else {
2316 ptcache_read(pid, cfra2);
2317 }
2318 }
2319 }
2320
2321 if (cfra1) {
2322 ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT);
2323 }
2324 else if (cfra2) {
2325 ret = PTCACHE_READ_OLD;
2326 pid->cache->simframe = cfra2;
2327 }
2328
2329 cfrai = (int)cfra;
2330 /* clear invalid cache frames so that better stuff can be simulated */
2331 if (pid->cache->flag & PTCACHE_OUTDATED) {
2332 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
2333 }
2334 else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
2335 if (cfra <= pid->cache->last_exact) {
2336 pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2337 }
2338
2339 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact));
2340 }
2341
2342 return ret;
2343 }
ptcache_write_stream(PTCacheID * pid,int cfra,int totpoint)2344 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
2345 {
2346 PTCacheFile *pf = NULL;
2347 int error = 0;
2348
2349 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
2350
2351 pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
2352
2353 if (pf == NULL) {
2354 if (G.debug & G_DEBUG) {
2355 printf("Error opening disk cache file for writing\n");
2356 }
2357 return 0;
2358 }
2359
2360 pf->data_types = pid->data_types;
2361 pf->totpoint = totpoint;
2362 pf->type = pid->type;
2363 pf->flag = 0;
2364
2365 if (!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))) {
2366 error = 1;
2367 }
2368
2369 if (!error && pid->write_stream) {
2370 pid->write_stream(pf, pid->calldata);
2371 }
2372
2373 ptcache_file_close(pf);
2374
2375 if (error && G.debug & G_DEBUG) {
2376 printf("Error writing to disk cache\n");
2377 }
2378
2379 return error == 0;
2380 }
2381
ptcache_write(PTCacheID * pid,int cfra,int overwrite)2382 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
2383 {
2384 PointCache *cache = pid->cache;
2385 PTCacheMem *pm = NULL, *pm2 = NULL;
2386 int totpoint = pid->totpoint(pid->calldata, cfra);
2387 int i, error = 0;
2388
2389 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2390
2391 pm->totpoint = pid->totwrite(pid->calldata, cfra);
2392 pm->data_types = cfra ? pid->data_types : pid->info_types;
2393
2394 ptcache_data_alloc(pm);
2395 void *cur[BPHYS_TOT_DATA];
2396 BKE_ptcache_mem_pointers_init(pm, cur);
2397
2398 if (overwrite) {
2399 if (cache->flag & PTCACHE_DISK_CACHE) {
2400 int fra = cfra - 1;
2401
2402 while (fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) {
2403 fra--;
2404 }
2405
2406 pm2 = ptcache_disk_frame_to_mem(pid, fra);
2407 }
2408 else {
2409 pm2 = cache->mem_cache.last;
2410 }
2411 }
2412
2413 if (pid->write_point) {
2414 for (i = 0; i < totpoint; i++) {
2415 int write = pid->write_point(i, pid->calldata, cur, cfra);
2416 if (write) {
2417 BKE_ptcache_mem_pointers_incr(cur);
2418
2419 void *cur2[BPHYS_TOT_DATA];
2420 /* newly born particles have to be copied to previous cached frame */
2421 if (overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2, cur2)) {
2422 pid->write_point(i, pid->calldata, cur2, cfra);
2423 }
2424 }
2425 }
2426 }
2427
2428 if (pid->write_extra_data) {
2429 pid->write_extra_data(pid->calldata, pm, cfra);
2430 }
2431
2432 pm->frame = cfra;
2433
2434 if (cache->flag & PTCACHE_DISK_CACHE) {
2435 error += !ptcache_mem_frame_to_disk(pid, pm);
2436
2437 // if (pm) /* pm is always set */
2438 {
2439 ptcache_mem_clear(pm);
2440 MEM_freeN(pm);
2441 }
2442
2443 if (pm2) {
2444 error += !ptcache_mem_frame_to_disk(pid, pm2);
2445 ptcache_mem_clear(pm2);
2446 MEM_freeN(pm2);
2447 }
2448 }
2449 else {
2450 BLI_addtail(&cache->mem_cache, pm);
2451 }
2452
2453 return error;
2454 }
ptcache_write_needed(PTCacheID * pid,int cfra,int * overwrite)2455 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
2456 {
2457 PointCache *cache = pid->cache;
2458 int ofra = 0, efra = cache->endframe;
2459
2460 /* always start from scratch on the first frame */
2461 if (cfra && cfra == cache->startframe) {
2462 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
2463 cache->flag &= ~PTCACHE_REDO_NEEDED;
2464 return 1;
2465 }
2466
2467 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2468 if (cfra == 0 && cache->startframe > 0) {
2469 return 1;
2470 }
2471
2472 /* find last cached frame */
2473 while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) {
2474 efra--;
2475 }
2476
2477 /* find second last cached frame */
2478 ofra = efra - 1;
2479 while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) {
2480 ofra--;
2481 }
2482 }
2483 else {
2484 PTCacheMem *pm = cache->mem_cache.last;
2485 /* don't write info file in memory */
2486 if (cfra == 0) {
2487 return 0;
2488 }
2489
2490 if (pm == NULL) {
2491 return 1;
2492 }
2493
2494 efra = pm->frame;
2495 ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
2496 }
2497
2498 if (efra >= cache->startframe && cfra > efra) {
2499 if (ofra >= cache->startframe && efra - ofra < cache->step) {
2500 /* overwrite previous frame */
2501 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
2502 *overwrite = 1;
2503 }
2504 return 1;
2505 }
2506
2507 return 0;
2508 }
2509 /* writes cache to disk or memory */
BKE_ptcache_write(PTCacheID * pid,unsigned int cfra)2510 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
2511 {
2512 PointCache *cache = pid->cache;
2513 int totpoint = pid->totpoint(pid->calldata, cfra);
2514 int overwrite = 0, error = 0;
2515
2516 if (totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) {
2517 return 0;
2518 }
2519
2520 if (ptcache_write_needed(pid, cfra, &overwrite) == 0) {
2521 return 0;
2522 }
2523
2524 if (pid->write_stream) {
2525 ptcache_write_stream(pid, cfra, totpoint);
2526 }
2527 else if (pid->write_point) {
2528 error += ptcache_write(pid, cfra, overwrite);
2529 }
2530
2531 /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
2532 if (cfra - cache->last_exact == 1 || cfra == cache->startframe) {
2533 cache->last_exact = cfra;
2534 cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2535 }
2536 /* Don't mark skipped when writing info file (frame 0) */
2537 else if (cfra) {
2538 cache->flag |= PTCACHE_FRAMES_SKIPPED;
2539 }
2540
2541 /* Update timeline cache display */
2542 if (cfra && cache->cached_frames) {
2543 cache->cached_frames[cfra - cache->startframe] = 1;
2544 }
2545
2546 cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
2547
2548 return !error;
2549 }
2550 /* you'll need to close yourself after!
2551 * mode - PTCACHE_CLEAR_ALL,
2552 */
2553
2554 /* Clears & resets */
BKE_ptcache_id_clear(PTCacheID * pid,int mode,unsigned int cfra)2555 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
2556 {
2557 unsigned int len; /* store the length of the string */
2558 unsigned int sta, end;
2559
2560 /* mode is same as fopen's modes */
2561 DIR *dir;
2562 struct dirent *de;
2563 char path[MAX_PTCACHE_PATH];
2564 char filename[MAX_PTCACHE_FILE];
2565 char path_full[MAX_PTCACHE_FILE];
2566 char ext[MAX_PTCACHE_PATH];
2567
2568 if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) {
2569 return;
2570 }
2571
2572 if (pid->cache->flag & PTCACHE_IGNORE_CLEAR) {
2573 return;
2574 }
2575
2576 sta = pid->cache->startframe;
2577 end = pid->cache->endframe;
2578
2579 #ifndef DURIAN_POINTCACHE_LIB_OK
2580 /* don't allow clearing for linked objects */
2581 if (pid->owner_id->lib) {
2582 return;
2583 }
2584 #endif
2585
2586 /*if (!G.relbase_valid) return; */ /* save blend file before using pointcache */
2587
2588 const char *fext = ptcache_file_extension(pid);
2589
2590 /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
2591 switch (mode) {
2592 case PTCACHE_CLEAR_ALL:
2593 case PTCACHE_CLEAR_BEFORE:
2594 case PTCACHE_CLEAR_AFTER:
2595 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2596 ptcache_path(pid, path);
2597
2598 dir = opendir(path);
2599 if (dir == NULL) {
2600 return;
2601 }
2602
2603 len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
2604 /* append underscore terminator to ensure we don't match similar names
2605 * from objects whose names start with the same prefix
2606 */
2607 if (len < sizeof(filename) - 2) {
2608 BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len);
2609 len += 1;
2610 }
2611
2612 BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
2613
2614 while ((de = readdir(dir)) != NULL) {
2615 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2616 if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
2617 if (mode == PTCACHE_CLEAR_ALL) {
2618 pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2619 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2620 BLI_delete(path_full, false, false);
2621 }
2622 else {
2623 /* read the number of the file */
2624 const int frame = ptcache_frame_from_filename(de->d_name, ext);
2625
2626 if (frame != -1) {
2627 if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
2628 (mode == PTCACHE_CLEAR_AFTER && frame > cfra)) {
2629 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2630 BLI_delete(path_full, false, false);
2631 if (pid->cache->cached_frames && frame >= sta && frame <= end) {
2632 pid->cache->cached_frames[frame - sta] = 0;
2633 }
2634 }
2635 }
2636 }
2637 }
2638 }
2639 }
2640 closedir(dir);
2641
2642 if (mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames) {
2643 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2644 }
2645 }
2646 else {
2647 PTCacheMem *pm = pid->cache->mem_cache.first;
2648 PTCacheMem *link = NULL;
2649
2650 if (mode == PTCACHE_CLEAR_ALL) {
2651 /*we want startframe if the cache starts before zero*/
2652 pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
2653 for (; pm; pm = pm->next) {
2654 ptcache_mem_clear(pm);
2655 }
2656 BLI_freelistN(&pid->cache->mem_cache);
2657
2658 if (pid->cache->cached_frames) {
2659 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
2660 }
2661 }
2662 else {
2663 while (pm) {
2664 if ((mode == PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
2665 (mode == PTCACHE_CLEAR_AFTER && pm->frame > cfra)) {
2666 link = pm;
2667 if (pid->cache->cached_frames && pm->frame >= sta && pm->frame <= end) {
2668 pid->cache->cached_frames[pm->frame - sta] = 0;
2669 }
2670 ptcache_mem_clear(pm);
2671 pm = pm->next;
2672 BLI_freelinkN(&pid->cache->mem_cache, link);
2673 }
2674 else {
2675 pm = pm->next;
2676 }
2677 }
2678 }
2679 }
2680 break;
2681
2682 case PTCACHE_CLEAR_FRAME:
2683 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2684 if (BKE_ptcache_id_exist(pid, cfra)) {
2685 ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
2686 BLI_delete(filename, false, false);
2687 }
2688 }
2689 else {
2690 PTCacheMem *pm = pid->cache->mem_cache.first;
2691
2692 for (; pm; pm = pm->next) {
2693 if (pm->frame == cfra) {
2694 ptcache_mem_clear(pm);
2695 BLI_freelinkN(&pid->cache->mem_cache, pm);
2696 break;
2697 }
2698 }
2699 }
2700 if (pid->cache->cached_frames && cfra >= sta && cfra <= end) {
2701 pid->cache->cached_frames[cfra - sta] = 0;
2702 }
2703 break;
2704 }
2705
2706 pid->cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
2707 }
2708
BKE_ptcache_id_exist(PTCacheID * pid,int cfra)2709 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
2710 {
2711 if (!pid->cache) {
2712 return 0;
2713 }
2714
2715 if (cfra < pid->cache->startframe || cfra > pid->cache->endframe) {
2716 return 0;
2717 }
2718
2719 if (pid->cache->cached_frames && pid->cache->cached_frames[cfra - pid->cache->startframe] == 0) {
2720 return 0;
2721 }
2722
2723 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2724 char filename[MAX_PTCACHE_FILE];
2725
2726 ptcache_filename(pid, filename, cfra, 1, 1);
2727
2728 return BLI_exists(filename);
2729 }
2730
2731 PTCacheMem *pm = pid->cache->mem_cache.first;
2732
2733 for (; pm; pm = pm->next) {
2734 if (pm->frame == cfra) {
2735 return 1;
2736 }
2737 }
2738 return 0;
2739 }
BKE_ptcache_id_time(PTCacheID * pid,Scene * scene,float cfra,int * startframe,int * endframe,float * timescale)2740 void BKE_ptcache_id_time(
2741 PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
2742 {
2743 /* Object *ob; */ /* UNUSED */
2744 PointCache *cache;
2745 /* float offset; unused for now */
2746 float time, nexttime;
2747
2748 /* TODO: this has to be sorted out once bsystem_time gets redone, */
2749 /* now caches can handle interpolating etc. too - jahka */
2750
2751 /* time handling for point cache:
2752 * - simulation time is scaled by result of bsystem_time
2753 * - for offsetting time only time offset is taken into account, since
2754 * that's always the same and can't be animated. a timeoffset which
2755 * varies over time is not simple to support.
2756 * - field and motion blur offsets are currently ignored, proper solution
2757 * is probably to interpolate results from two frames for that ..
2758 */
2759
2760 cache = pid->cache;
2761
2762 if (timescale) {
2763 time = BKE_scene_frame_get(scene);
2764 nexttime = BKE_scene_frame_to_ctime(scene, CFRA + 1.0f);
2765
2766 *timescale = MAX2(nexttime - time, 0.0f);
2767 }
2768
2769 if (startframe && endframe) {
2770 *startframe = cache->startframe;
2771 *endframe = cache->endframe;
2772 }
2773
2774 /* verify cached_frames array is up to date */
2775 if (cache->cached_frames) {
2776 if (cache->cached_frames_len != (cache->endframe - cache->startframe + 1)) {
2777 MEM_freeN(cache->cached_frames);
2778 cache->cached_frames = NULL;
2779 cache->cached_frames_len = 0;
2780 }
2781 }
2782
2783 if (cache->cached_frames == NULL && cache->endframe > cache->startframe) {
2784 unsigned int sta = cache->startframe;
2785 unsigned int end = cache->endframe;
2786
2787 cache->cached_frames_len = cache->endframe - cache->startframe + 1;
2788 cache->cached_frames = MEM_callocN(sizeof(char) * cache->cached_frames_len,
2789 "cached frames array");
2790
2791 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2792 /* mode is same as fopen's modes */
2793 DIR *dir;
2794 struct dirent *de;
2795 char path[MAX_PTCACHE_PATH];
2796 char filename[MAX_PTCACHE_FILE];
2797 char ext[MAX_PTCACHE_PATH];
2798 unsigned int len; /* store the length of the string */
2799
2800 ptcache_path(pid, path);
2801
2802 len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */
2803
2804 dir = opendir(path);
2805 if (dir == NULL) {
2806 return;
2807 }
2808
2809 const char *fext = ptcache_file_extension(pid);
2810
2811 BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
2812
2813 while ((de = readdir(dir)) != NULL) {
2814 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
2815 if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
2816 /* read the number of the file */
2817 const int frame = ptcache_frame_from_filename(de->d_name, ext);
2818
2819 if ((frame != -1) && (frame >= sta && frame <= end)) {
2820 cache->cached_frames[frame - sta] = 1;
2821 }
2822 }
2823 }
2824 }
2825 closedir(dir);
2826 }
2827 else {
2828 PTCacheMem *pm = pid->cache->mem_cache.first;
2829
2830 while (pm) {
2831 if (pm->frame >= sta && pm->frame <= end) {
2832 cache->cached_frames[pm->frame - sta] = 1;
2833 }
2834 pm = pm->next;
2835 }
2836 }
2837 }
2838 }
BKE_ptcache_id_reset(Scene * scene,PTCacheID * pid,int mode)2839 int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
2840 {
2841 PointCache *cache;
2842 int reset, clear, after;
2843
2844 if (!pid->cache) {
2845 return 0;
2846 }
2847
2848 cache = pid->cache;
2849 reset = 0;
2850 clear = 0;
2851 after = 0;
2852
2853 if (mode == PTCACHE_RESET_DEPSGRAPH) {
2854 if (!(cache->flag & PTCACHE_BAKED)) {
2855
2856 after = 1;
2857 }
2858
2859 cache->flag |= PTCACHE_OUTDATED;
2860 }
2861 else if (mode == PTCACHE_RESET_BAKED) {
2862 cache->flag |= PTCACHE_OUTDATED;
2863 }
2864 else if (mode == PTCACHE_RESET_OUTDATED) {
2865 reset = 1;
2866
2867 if (cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
2868 clear = 1;
2869 cache->flag &= ~PTCACHE_OUTDATED;
2870 }
2871 }
2872
2873 if (reset) {
2874 BKE_ptcache_invalidate(cache);
2875 cache->flag &= ~PTCACHE_REDO_NEEDED;
2876
2877 if (pid->type == PTCACHE_TYPE_CLOTH) {
2878 cloth_free_modifier(pid->calldata);
2879 }
2880 else if (pid->type == PTCACHE_TYPE_SOFTBODY) {
2881 sbFreeSimulation(pid->calldata);
2882 }
2883 else if (pid->type == PTCACHE_TYPE_PARTICLES) {
2884 psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
2885 }
2886 else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) {
2887 dynamicPaint_clearSurface(scene, (DynamicPaintSurface *)pid->calldata);
2888 }
2889 }
2890 if (clear) {
2891 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
2892 }
2893 else if (after) {
2894 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
2895 }
2896
2897 return (reset || clear || after);
2898 }
BKE_ptcache_object_reset(Scene * scene,Object * ob,int mode)2899 int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
2900 {
2901 PTCacheID pid;
2902 ParticleSystem *psys;
2903 ModifierData *md;
2904 int reset, skip;
2905
2906 reset = 0;
2907 skip = 0;
2908
2909 if (ob->soft) {
2910 BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
2911 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2912 }
2913
2914 for (psys = ob->particlesystem.first; psys; psys = psys->next) {
2915 /* children or just redo can be calculated without resetting anything */
2916 if (psys->recalc & ID_RECALC_PSYS_REDO || psys->recalc & ID_RECALC_PSYS_CHILD) {
2917 skip = 1;
2918 /* Baked cloth hair has to be checked too, because we don't want to reset */
2919 /* particles or cloth in that case -jahka */
2920 }
2921 else if (psys->clmd) {
2922 BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
2923 if (mode == PSYS_RESET_ALL ||
2924 !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) {
2925 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2926 }
2927 else {
2928 skip = 1;
2929 }
2930 }
2931
2932 if (skip == 0 && psys->part) {
2933 BKE_ptcache_id_from_particles(&pid, ob, psys);
2934 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2935 }
2936 }
2937
2938 for (md = ob->modifiers.first; md; md = md->next) {
2939 if (md->type == eModifierType_Cloth) {
2940 BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData *)md);
2941 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2942 }
2943 if (md->type == eModifierType_DynamicPaint) {
2944 DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
2945 if (pmd->canvas) {
2946 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
2947
2948 for (; surface; surface = surface->next) {
2949 BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
2950 reset |= BKE_ptcache_id_reset(scene, &pid, mode);
2951 }
2952 }
2953 }
2954 }
2955
2956 if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) {
2957 if (ob->rigidbody_object) {
2958 ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE;
2959 }
2960 BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world);
2961 /* only flag as outdated, resetting should happen on start frame */
2962 pid.cache->flag |= PTCACHE_OUTDATED;
2963 }
2964
2965 if (ob->type == OB_ARMATURE) {
2966 BIK_clear_cache(ob->pose);
2967 }
2968
2969 return reset;
2970 }
2971
2972 /* Use this when quitting blender, with unsaved files */
BKE_ptcache_remove(void)2973 void BKE_ptcache_remove(void)
2974 {
2975 char path[MAX_PTCACHE_PATH];
2976 char path_full[MAX_PTCACHE_PATH];
2977 int rmdir = 1;
2978
2979 ptcache_path(NULL, path);
2980
2981 if (BLI_exists(path)) {
2982 /* The pointcache dir exists? - remove all pointcache */
2983
2984 DIR *dir;
2985 struct dirent *de;
2986
2987 dir = opendir(path);
2988 if (dir == NULL) {
2989 return;
2990 }
2991
2992 while ((de = readdir(dir)) != NULL) {
2993 if (FILENAME_IS_CURRPAR(de->d_name)) {
2994 /* do nothing */
2995 }
2996 else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
2997 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
2998 BLI_delete(path_full, false, false);
2999 }
3000 else {
3001 rmdir = 0; /* unknown file, don't remove the dir */
3002 }
3003 }
3004
3005 closedir(dir);
3006 }
3007 else {
3008 rmdir = 0; /* path doesn't exist */
3009 }
3010
3011 if (rmdir) {
3012 BLI_delete(path, true, false);
3013 }
3014 }
3015
3016 /* Point Cache handling */
3017
BKE_ptcache_add(ListBase * ptcaches)3018 PointCache *BKE_ptcache_add(ListBase *ptcaches)
3019 {
3020 PointCache *cache;
3021
3022 cache = MEM_callocN(sizeof(PointCache), "PointCache");
3023 cache->startframe = 1;
3024 cache->endframe = 250;
3025 cache->step = 1;
3026 cache->index = -1;
3027
3028 BLI_addtail(ptcaches, cache);
3029
3030 return cache;
3031 }
3032
BKE_ptcache_free_mem(ListBase * mem_cache)3033 void BKE_ptcache_free_mem(ListBase *mem_cache)
3034 {
3035 PTCacheMem *pm = mem_cache->first;
3036
3037 if (pm) {
3038 for (; pm; pm = pm->next) {
3039 ptcache_mem_clear(pm);
3040 }
3041
3042 BLI_freelistN(mem_cache);
3043 }
3044 }
BKE_ptcache_free(PointCache * cache)3045 void BKE_ptcache_free(PointCache *cache)
3046 {
3047 BKE_ptcache_free_mem(&cache->mem_cache);
3048 if (cache->edit && cache->free_edit) {
3049 cache->free_edit(cache->edit);
3050 }
3051 if (cache->cached_frames) {
3052 MEM_freeN(cache->cached_frames);
3053 }
3054 MEM_freeN(cache);
3055 }
BKE_ptcache_free_list(ListBase * ptcaches)3056 void BKE_ptcache_free_list(ListBase *ptcaches)
3057 {
3058 PointCache *cache;
3059
3060 while ((cache = BLI_pophead(ptcaches))) {
3061 BKE_ptcache_free(cache);
3062 }
3063 }
3064
ptcache_copy(PointCache * cache,const bool copy_data)3065 static PointCache *ptcache_copy(PointCache *cache, const bool copy_data)
3066 {
3067 PointCache *ncache;
3068
3069 ncache = MEM_dupallocN(cache);
3070
3071 BLI_listbase_clear(&ncache->mem_cache);
3072
3073 if (copy_data == false) {
3074 ncache->cached_frames = NULL;
3075 ncache->cached_frames_len = 0;
3076
3077 /* flag is a mix of user settings and simulator/baking state */
3078 ncache->flag = ncache->flag & (PTCACHE_DISK_CACHE | PTCACHE_EXTERNAL | PTCACHE_IGNORE_LIBPATH);
3079 ncache->simframe = 0;
3080 }
3081 else {
3082 PTCacheMem *pm;
3083
3084 for (pm = cache->mem_cache.first; pm; pm = pm->next) {
3085 PTCacheMem *pmn = MEM_dupallocN(pm);
3086 int i;
3087
3088 for (i = 0; i < BPHYS_TOT_DATA; i++) {
3089 if (pmn->data[i]) {
3090 pmn->data[i] = MEM_dupallocN(pm->data[i]);
3091 }
3092 }
3093
3094 BLI_addtail(&ncache->mem_cache, pmn);
3095 }
3096
3097 if (ncache->cached_frames) {
3098 ncache->cached_frames = MEM_dupallocN(cache->cached_frames);
3099 }
3100 }
3101
3102 /* hmm, should these be copied over instead? */
3103 ncache->edit = NULL;
3104
3105 return ncache;
3106 }
3107
3108 /* returns first point cache */
BKE_ptcache_copy_list(ListBase * ptcaches_new,const ListBase * ptcaches_old,const int flag)3109 PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new,
3110 const ListBase *ptcaches_old,
3111 const int flag)
3112 {
3113 PointCache *cache = ptcaches_old->first;
3114
3115 BLI_listbase_clear(ptcaches_new);
3116
3117 for (; cache; cache = cache->next) {
3118 BLI_addtail(ptcaches_new, ptcache_copy(cache, (flag & LIB_ID_COPY_CACHES) != 0));
3119 }
3120
3121 return ptcaches_new->first;
3122 }
3123
3124 /* Disabled this code; this is being called on scene_update_tagged, and that in turn gets called on
3125 * every user action changing stuff, and then it runs a complete bake??? (ton) */
3126
3127 /* Baking */
BKE_ptcache_quick_cache_all(Main * bmain,Scene * scene,ViewLayer * view_layer)3128 void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_layer)
3129 {
3130 PTCacheBaker baker;
3131
3132 memset(&baker, 0, sizeof(baker));
3133 baker.bmain = bmain;
3134 baker.scene = scene;
3135 baker.view_layer = view_layer;
3136 baker.bake = 0;
3137 baker.render = 0;
3138 baker.anim_init = 0;
3139 baker.quick_step = scene->physics_settings.quick_cache_step;
3140
3141 BKE_ptcache_bake(&baker);
3142 }
3143
ptcache_dt_to_str(char * str,double dtime)3144 static void ptcache_dt_to_str(char *str, double dtime)
3145 {
3146 if (dtime > 60.0) {
3147 if (dtime > 3600.0) {
3148 sprintf(
3149 str, "%ih %im %is", (int)(dtime / 3600), ((int)(dtime / 60)) % 60, ((int)dtime) % 60);
3150 }
3151 else {
3152 sprintf(str, "%im %is", ((int)(dtime / 60)) % 60, ((int)dtime) % 60);
3153 }
3154 }
3155 else {
3156 sprintf(str, "%is", ((int)dtime) % 60);
3157 }
3158 }
3159
3160 /* if bake is not given run simulations to current frame */
BKE_ptcache_bake(PTCacheBaker * baker)3161 void BKE_ptcache_bake(PTCacheBaker *baker)
3162 {
3163 Scene *scene = baker->scene;
3164 ViewLayer *view_layer = baker->view_layer;
3165 struct Depsgraph *depsgraph = baker->depsgraph;
3166 Scene *sce_iter; /* SETLOOPER macro only */
3167 Base *base;
3168 ListBase pidlist;
3169 PTCacheID *pid = &baker->pid;
3170 PointCache *cache = NULL;
3171 float frameleno = scene->r.framelen;
3172 int cfrao = CFRA;
3173 int startframe = MAXFRAME, endframe = baker->anim_init ? scene->r.sfra : CFRA;
3174 int bake = baker->bake;
3175 int render = baker->render;
3176
3177 G.is_break = false;
3178
3179 /* set caches to baking mode and figure out start frame */
3180 if (pid->owner_id) {
3181 /* cache/bake a single object */
3182 cache = pid->cache;
3183 if ((cache->flag & PTCACHE_BAKED) == 0) {
3184 if (pid->type == PTCACHE_TYPE_PARTICLES) {
3185 ParticleSystem *psys = pid->calldata;
3186
3187 /* a bit confusing, could make this work better in the UI */
3188 if (psys->part->type == PART_EMITTER) {
3189 psys_get_pointcache_start_end(
3190 scene, pid->calldata, &cache->startframe, &cache->endframe);
3191 }
3192 }
3193 else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
3194 /* get all pids from the object and search for smoke low res */
3195 ListBase pidlist2;
3196 PTCacheID *pid2;
3197 BLI_assert(GS(pid->owner_id->name) == ID_OB);
3198 BKE_ptcache_ids_from_object(&pidlist2, (Object *)pid->owner_id, scene, MAX_DUPLI_RECUR);
3199 for (pid2 = pidlist2.first; pid2; pid2 = pid2->next) {
3200 if (pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
3201 if (pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) {
3202 if (bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) {
3203 BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0);
3204 }
3205 if (bake) {
3206 pid2->cache->flag |= PTCACHE_BAKING;
3207 pid2->cache->flag &= ~PTCACHE_BAKED;
3208 }
3209 }
3210 }
3211 }
3212 BLI_freelistN(&pidlist2);
3213 }
3214
3215 if (bake || cache->flag & PTCACHE_REDO_NEEDED) {
3216 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3217 }
3218
3219 startframe = MAX2(cache->last_exact, cache->startframe);
3220
3221 if (bake) {
3222 endframe = cache->endframe;
3223 cache->flag |= PTCACHE_BAKING;
3224 }
3225 else {
3226 endframe = MIN2(endframe, cache->endframe);
3227 }
3228
3229 cache->flag &= ~PTCACHE_BAKED;
3230 }
3231 }
3232 else {
3233 for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
3234 /* cache/bake everything in the scene */
3235 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
3236
3237 for (pid = pidlist.first; pid; pid = pid->next) {
3238 cache = pid->cache;
3239 if ((cache->flag & PTCACHE_BAKED) == 0) {
3240 if (pid->type == PTCACHE_TYPE_PARTICLES) {
3241 ParticleSystem *psys = (ParticleSystem *)pid->calldata;
3242 /* skip hair & keyed particles */
3243 if (psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED) {
3244 continue;
3245 }
3246
3247 psys_get_pointcache_start_end(
3248 scene, pid->calldata, &cache->startframe, &cache->endframe);
3249 }
3250
3251 /* XXX workaround for regression inroduced in ee3fadd, needs looking into */
3252 if (pid->type == PTCACHE_TYPE_RIGIDBODY) {
3253 if ((cache->flag & PTCACHE_REDO_NEEDED ||
3254 (cache->flag & PTCACHE_SIMULATION_VALID) == 0) &&
3255 (render || bake)) {
3256 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3257 }
3258 }
3259 else if (((cache->flag & PTCACHE_BAKED) == 0) && (render || bake)) {
3260 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3261 }
3262
3263 startframe = MIN2(startframe, cache->startframe);
3264
3265 if (bake || render) {
3266 cache->flag |= PTCACHE_BAKING;
3267
3268 if (bake) {
3269 endframe = MAX2(endframe, cache->endframe);
3270 }
3271 }
3272
3273 cache->flag &= ~PTCACHE_BAKED;
3274 }
3275 }
3276 BLI_freelistN(&pidlist);
3277 }
3278 }
3279
3280 CFRA = startframe;
3281 scene->r.framelen = 1.0;
3282
3283 /* bake */
3284
3285 bool use_timer = false;
3286 double stime, ptime, ctime, fetd;
3287 char run[32], cur[32], etd[32];
3288 int cancel = 0;
3289
3290 stime = ptime = PIL_check_seconds_timer();
3291
3292 for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) {
3293 BKE_scene_graph_update_for_newframe(depsgraph);
3294
3295 if (baker->update_progress) {
3296 float progress = ((float)(CFRA - startframe) / (float)(endframe - startframe));
3297 baker->update_progress(baker->bake_job, progress, &cancel);
3298 }
3299
3300 if (G.background) {
3301 printf("bake: frame %d :: %d\n", CFRA, endframe);
3302 }
3303 else {
3304 ctime = PIL_check_seconds_timer();
3305
3306 fetd = (ctime - ptime) * (endframe - CFRA) / baker->quick_step;
3307
3308 if (use_timer || fetd > 60.0) {
3309 use_timer = true;
3310
3311 ptcache_dt_to_str(cur, ctime - ptime);
3312 ptcache_dt_to_str(run, ctime - stime);
3313 ptcache_dt_to_str(etd, fetd);
3314
3315 printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r",
3316 run,
3317 CFRA - startframe + 1,
3318 endframe - startframe + 1,
3319 ctime - ptime,
3320 etd);
3321 }
3322
3323 ptime = ctime;
3324 }
3325
3326 /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
3327 if ((cancel || G.is_break)) {
3328 break;
3329 }
3330
3331 CFRA += 1;
3332 }
3333
3334 if (use_timer) {
3335 /* start with newline because of \r above */
3336 ptcache_dt_to_str(run, PIL_check_seconds_timer() - stime);
3337 printf("\nBake %s %s (%i frames simulated).\n",
3338 (cancel ? "canceled after" : "finished in"),
3339 run,
3340 CFRA - startframe);
3341 }
3342
3343 /* clear baking flag */
3344 if (pid) {
3345 cache->flag &= ~(PTCACHE_BAKING | PTCACHE_REDO_NEEDED);
3346 cache->flag |= PTCACHE_SIMULATION_VALID;
3347 if (bake) {
3348 cache->flag |= PTCACHE_BAKED;
3349 /* write info file */
3350 if (cache->flag & PTCACHE_DISK_CACHE) {
3351 BKE_ptcache_write(pid, 0);
3352 }
3353 }
3354 }
3355 else {
3356 for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
3357 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
3358
3359 for (pid = pidlist.first; pid; pid = pid->next) {
3360 /* skip hair particles */
3361 if (pid->type == PTCACHE_TYPE_PARTICLES &&
3362 ((ParticleSystem *)pid->calldata)->part->type == PART_HAIR) {
3363 continue;
3364 }
3365
3366 cache = pid->cache;
3367
3368 if (baker->quick_step > 1) {
3369 cache->flag &= ~(PTCACHE_BAKING | PTCACHE_OUTDATED);
3370 }
3371 else {
3372 cache->flag &= ~(PTCACHE_BAKING | PTCACHE_REDO_NEEDED);
3373 }
3374
3375 cache->flag |= PTCACHE_SIMULATION_VALID;
3376
3377 if (bake) {
3378 cache->flag |= PTCACHE_BAKED;
3379 if (cache->flag & PTCACHE_DISK_CACHE) {
3380 BKE_ptcache_write(pid, 0);
3381 }
3382 }
3383 }
3384 BLI_freelistN(&pidlist);
3385 }
3386 }
3387
3388 scene->r.framelen = frameleno;
3389 CFRA = cfrao;
3390
3391 if (bake) { /* already on cfra unless baking */
3392 BKE_scene_graph_update_for_newframe(depsgraph);
3393 }
3394
3395 /* TODO: call redraw all windows somehow */
3396 }
3397 /* Helpers */
BKE_ptcache_disk_to_mem(PTCacheID * pid)3398 void BKE_ptcache_disk_to_mem(PTCacheID *pid)
3399 {
3400 PointCache *cache = pid->cache;
3401 PTCacheMem *pm = NULL;
3402 int baked = cache->flag & PTCACHE_BAKED;
3403 int cfra, sfra = cache->startframe, efra = cache->endframe;
3404
3405 /* Remove possible bake flag to allow clear */
3406 cache->flag &= ~PTCACHE_BAKED;
3407
3408 /* PTCACHE_DISK_CACHE flag was cleared already */
3409 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3410
3411 /* restore possible bake flag */
3412 cache->flag |= baked;
3413
3414 for (cfra = sfra; cfra <= efra; cfra++) {
3415 pm = ptcache_disk_frame_to_mem(pid, cfra);
3416
3417 if (pm) {
3418 BLI_addtail(&pid->cache->mem_cache, pm);
3419 }
3420 }
3421 }
BKE_ptcache_mem_to_disk(PTCacheID * pid)3422 void BKE_ptcache_mem_to_disk(PTCacheID *pid)
3423 {
3424 PointCache *cache = pid->cache;
3425 PTCacheMem *pm = cache->mem_cache.first;
3426 int baked = cache->flag & PTCACHE_BAKED;
3427
3428 /* Remove possible bake flag to allow clear */
3429 cache->flag &= ~PTCACHE_BAKED;
3430
3431 /* PTCACHE_DISK_CACHE flag was set already */
3432 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3433
3434 /* restore possible bake flag */
3435 cache->flag |= baked;
3436
3437 for (; pm; pm = pm->next) {
3438 if (ptcache_mem_frame_to_disk(pid, pm) == 0) {
3439 cache->flag &= ~PTCACHE_DISK_CACHE;
3440 break;
3441 }
3442 }
3443
3444 /* write info file */
3445 if (cache->flag & PTCACHE_BAKED) {
3446 BKE_ptcache_write(pid, 0);
3447 }
3448 }
BKE_ptcache_toggle_disk_cache(PTCacheID * pid)3449 void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
3450 {
3451 PointCache *cache = pid->cache;
3452 int last_exact = cache->last_exact;
3453
3454 if (!G.relbase_valid) {
3455 cache->flag &= ~PTCACHE_DISK_CACHE;
3456 if (G.debug & G_DEBUG) {
3457 printf("File must be saved before using disk cache!\n");
3458 }
3459 return;
3460 }
3461
3462 if (cache->cached_frames) {
3463 MEM_freeN(cache->cached_frames);
3464 cache->cached_frames = NULL;
3465 cache->cached_frames_len = 0;
3466 }
3467
3468 if (cache->flag & PTCACHE_DISK_CACHE) {
3469 BKE_ptcache_mem_to_disk(pid);
3470 }
3471 else {
3472 BKE_ptcache_disk_to_mem(pid);
3473 }
3474
3475 cache->flag ^= PTCACHE_DISK_CACHE;
3476 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
3477 cache->flag ^= PTCACHE_DISK_CACHE;
3478
3479 cache->last_exact = last_exact;
3480
3481 BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL);
3482
3483 cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
3484
3485 if ((cache->flag & PTCACHE_DISK_CACHE) == 0) {
3486 if (cache->index) {
3487 BKE_object_delete_ptcache((Object *)pid->owner_id, cache->index);
3488 cache->index = -1;
3489 }
3490 }
3491 }
3492
BKE_ptcache_disk_cache_rename(PTCacheID * pid,const char * name_src,const char * name_dst)3493 void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const char *name_dst)
3494 {
3495 char old_name[80];
3496 int len; /* store the length of the string */
3497 /* mode is same as fopen's modes */
3498 DIR *dir;
3499 struct dirent *de;
3500 char path[MAX_PTCACHE_PATH];
3501 char old_filename[MAX_PTCACHE_FILE];
3502 char new_path_full[MAX_PTCACHE_FILE];
3503 char old_path_full[MAX_PTCACHE_FILE];
3504 char ext[MAX_PTCACHE_PATH];
3505
3506 /* save old name */
3507 BLI_strncpy(old_name, pid->cache->name, sizeof(old_name));
3508
3509 /* get "from" filename */
3510 BLI_strncpy(pid->cache->name, name_src, sizeof(pid->cache->name));
3511
3512 len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */
3513
3514 ptcache_path(pid, path);
3515 dir = opendir(path);
3516 if (dir == NULL) {
3517 BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name));
3518 return;
3519 }
3520
3521 const char *fext = ptcache_file_extension(pid);
3522
3523 BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
3524
3525 /* put new name into cache */
3526 BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name));
3527
3528 while ((de = readdir(dir)) != NULL) {
3529 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
3530 if (STREQLEN(old_filename, de->d_name, len)) { /* do we have the right prefix */
3531 /* read the number of the file */
3532 const int frame = ptcache_frame_from_filename(de->d_name, ext);
3533
3534 if (frame != -1) {
3535 BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name);
3536 ptcache_filename(pid, new_path_full, frame, 1, 1);
3537 BLI_rename(old_path_full, new_path_full);
3538 }
3539 }
3540 }
3541 }
3542 closedir(dir);
3543
3544 BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name));
3545 }
3546
BKE_ptcache_load_external(PTCacheID * pid)3547 void BKE_ptcache_load_external(PTCacheID *pid)
3548 {
3549 /*todo*/
3550 PointCache *cache = pid->cache;
3551 int len; /* store the length of the string */
3552 int info = 0;
3553 int start = MAXFRAME;
3554 int end = -1;
3555
3556 /* mode is same as fopen's modes */
3557 DIR *dir;
3558 struct dirent *de;
3559 char path[MAX_PTCACHE_PATH];
3560 char filename[MAX_PTCACHE_FILE];
3561 char ext[MAX_PTCACHE_PATH];
3562
3563 if (!cache) {
3564 return;
3565 }
3566
3567 ptcache_path(pid, path);
3568
3569 len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */
3570
3571 dir = opendir(path);
3572 if (dir == NULL) {
3573 return;
3574 }
3575
3576 const char *fext = ptcache_file_extension(pid);
3577
3578 if (cache->index >= 0) {
3579 BLI_snprintf(ext, sizeof(ext), "_%02d%s", cache->index, fext);
3580 }
3581 else {
3582 BLI_strncpy(ext, fext, sizeof(ext));
3583 }
3584
3585 while ((de = readdir(dir)) != NULL) {
3586 if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
3587 if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
3588 /* read the number of the file */
3589 const int frame = ptcache_frame_from_filename(de->d_name, ext);
3590
3591 if (frame != -1) {
3592 if (frame) {
3593 start = MIN2(start, frame);
3594 end = MAX2(end, frame);
3595 }
3596 else {
3597 info = 1;
3598 }
3599 }
3600 }
3601 }
3602 }
3603 closedir(dir);
3604
3605 if (start != MAXFRAME) {
3606 PTCacheFile *pf;
3607
3608 cache->startframe = start;
3609 cache->endframe = end;
3610 cache->totpoint = 0;
3611
3612 if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
3613 /* necessary info in every file */
3614 }
3615 /* read totpoint from info file (frame 0) */
3616 else if (info) {
3617 pf = ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
3618
3619 if (pf) {
3620 if (ptcache_file_header_begin_read(pf)) {
3621 if (pf->type == pid->type && pid->read_header(pf)) {
3622 cache->totpoint = pf->totpoint;
3623 cache->flag |= PTCACHE_READ_INFO;
3624 }
3625 else {
3626 cache->totpoint = 0;
3627 }
3628 }
3629 ptcache_file_close(pf);
3630 }
3631 }
3632 /* or from any old format cache file */
3633 else {
3634 float old_data[14];
3635 int elemsize = ptcache_old_elemsize(pid);
3636 pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
3637
3638 if (pf) {
3639 while (ptcache_file_read(pf, old_data, 1, elemsize)) {
3640 cache->totpoint++;
3641 }
3642
3643 ptcache_file_close(pf);
3644 }
3645 }
3646 cache->flag |= (PTCACHE_BAKED | PTCACHE_DISK_CACHE | PTCACHE_SIMULATION_VALID);
3647 cache->flag &= ~(PTCACHE_OUTDATED | PTCACHE_FRAMES_SKIPPED);
3648 }
3649
3650 /* make sure all new frames are loaded */
3651 if (cache->cached_frames) {
3652 MEM_freeN(cache->cached_frames);
3653 cache->cached_frames = NULL;
3654 cache->cached_frames_len = 0;
3655 }
3656
3657 cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
3658 }
3659
BKE_ptcache_update_info(PTCacheID * pid)3660 void BKE_ptcache_update_info(PTCacheID *pid)
3661 {
3662 PointCache *cache = pid->cache;
3663 PTCacheExtra *extra = NULL;
3664 int totframes = 0;
3665 char mem_info[sizeof(((PointCache *)0)->info) / sizeof(*(((PointCache *)0)->info))];
3666
3667 cache->flag &= ~PTCACHE_FLAG_INFO_DIRTY;
3668
3669 if (cache->flag & PTCACHE_EXTERNAL) {
3670 int cfra = cache->startframe;
3671
3672 for (; cfra <= cache->endframe; cfra++) {
3673 if (BKE_ptcache_id_exist(pid, cfra)) {
3674 totframes++;
3675 }
3676 }
3677
3678 /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */
3679 if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) {
3680 BLI_snprintf(cache->info, sizeof(cache->info), TIP_("%i frames found!"), totframes);
3681 }
3682 else if (totframes && cache->totpoint) {
3683 BLI_snprintf(cache->info, sizeof(cache->info), TIP_("%i points found!"), cache->totpoint);
3684 }
3685 else {
3686 BLI_strncpy(cache->info, TIP_("No valid data to read!"), sizeof(cache->info));
3687 }
3688 return;
3689 }
3690
3691 if (cache->flag & PTCACHE_DISK_CACHE) {
3692 if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
3693 int totpoint = pid->totpoint(pid->calldata, 0);
3694
3695 if (cache->totpoint > totpoint) {
3696 BLI_snprintf(
3697 mem_info, sizeof(mem_info), TIP_("%i cells + High Resolution cached"), totpoint);
3698 }
3699 else {
3700 BLI_snprintf(mem_info, sizeof(mem_info), TIP_("%i cells cached"), totpoint);
3701 }
3702 }
3703 else {
3704 int cfra = cache->startframe;
3705
3706 for (; cfra <= cache->endframe; cfra++) {
3707 if (BKE_ptcache_id_exist(pid, cfra)) {
3708 totframes++;
3709 }
3710 }
3711
3712 BLI_snprintf(mem_info, sizeof(mem_info), TIP_("%i frames on disk"), totframes);
3713 }
3714 }
3715 else {
3716 PTCacheMem *pm = cache->mem_cache.first;
3717 char formatted_tot[16];
3718 char formatted_mem[15];
3719 long long int bytes = 0.0f;
3720 int i;
3721
3722 for (; pm; pm = pm->next) {
3723 for (i = 0; i < BPHYS_TOT_DATA; i++) {
3724 bytes += MEM_allocN_len(pm->data[i]);
3725 }
3726
3727 for (extra = pm->extradata.first; extra; extra = extra->next) {
3728 bytes += MEM_allocN_len(extra->data);
3729 bytes += sizeof(PTCacheExtra);
3730 }
3731
3732 bytes += sizeof(PTCacheMem);
3733
3734 totframes++;
3735 }
3736
3737 BLI_str_format_int_grouped(formatted_tot, totframes);
3738 BLI_str_format_byte_unit(formatted_mem, bytes, false);
3739
3740 BLI_snprintf(mem_info,
3741 sizeof(mem_info),
3742 TIP_("%s frames in memory (%s)"),
3743 formatted_tot,
3744 formatted_mem);
3745 }
3746
3747 if (cache->flag & PTCACHE_OUTDATED) {
3748 BLI_snprintf(cache->info, sizeof(cache->info), TIP_("%s, cache is outdated!"), mem_info);
3749 }
3750 else if (cache->flag & PTCACHE_FRAMES_SKIPPED) {
3751 BLI_snprintf(cache->info,
3752 sizeof(cache->info),
3753 TIP_("%s, not exact since frame %i"),
3754 mem_info,
3755 cache->last_exact);
3756 }
3757 else {
3758 BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info);
3759 }
3760 }
3761
BKE_ptcache_validate(PointCache * cache,int framenr)3762 void BKE_ptcache_validate(PointCache *cache, int framenr)
3763 {
3764 if (cache) {
3765 cache->flag |= PTCACHE_SIMULATION_VALID;
3766 cache->simframe = framenr;
3767 }
3768 }
BKE_ptcache_invalidate(PointCache * cache)3769 void BKE_ptcache_invalidate(PointCache *cache)
3770 {
3771 if (cache) {
3772 cache->flag &= ~PTCACHE_SIMULATION_VALID;
3773 cache->simframe = 0;
3774 cache->last_exact = MIN2(cache->startframe, 0);
3775 }
3776 }
3777