Cleanup: Naming, BKE prefix
[blender.git] / source / blender / blenkernel / intern / pointcache.c
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 \ingroup bke
21  */
22
23
24 #include <stdlib.h>
25 #include <stdio.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_modifier_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_object_force_types.h"
40 #include "DNA_particle_types.h"
41 #include "DNA_rigidbody_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_smoke_types.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_math.h"
47 #include "BLI_string.h"
48 #include "BLI_utildefines.h"
49
50 #include "BLT_translation.h"
51
52 #include "PIL_time.h"
53
54 #include "BKE_appdir.h"
55 #include "BKE_anim.h"
56 #include "BKE_cloth.h"
57 #include "BKE_collection.h"
58 #include "BKE_dynamicpaint.h"
59 #include "BKE_global.h"
60 #include "BKE_library.h"
61 #include "BKE_main.h"
62 #include "BKE_modifier.h"
63 #include "BKE_object.h"
64 #include "BKE_particle.h"
65 #include "BKE_pointcache.h"
66 #include "BKE_scene.h"
67 #include "BKE_smoke.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 /* both in intern */
77 #ifdef WITH_SMOKE
78 #include "smoke_API.h"
79 #endif
80
81 #ifdef WITH_OPENVDB
82 #include "openvdb_capi.h"
83 #endif
84
85 #ifdef WITH_LZO
86 #  ifdef WITH_SYSTEM_LZO
87 #    include <lzo/lzo1x.h>
88 #  else
89 #    include "minilzo.h"
90 #  endif
91 #  define LZO_HEAP_ALLOC(var,size) \
92         lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
93 #endif
94
95 #define LZO_OUT_LEN(size)     ((size) + (size) / 16 + 64 + 3)
96
97 #ifdef WITH_LZMA
98 #include "LzmaLib.h"
99 #endif
100
101 /* needed for directory lookup */
102 #ifndef WIN32
103 #  include <dirent.h>
104 #else
105 #  include "BLI_winstuff.h"
106 #endif
107
108 #define PTCACHE_DATA_FROM(data, type, from)  \
109         if (data[type]) { \
110                 memcpy(data[type], from, ptcache_data_size[type]); \
111         } (void)0
112
113 #define PTCACHE_DATA_TO(data, type, index, to)  \
114         if (data[type]) { \
115                 memcpy(to, (char *)(data)[type] + ((index) ? (index) * ptcache_data_size[type] : 0), ptcache_data_size[type]); \
116         } (void)0
117
118 /* could be made into a pointcache option */
119 #define DURIAN_POINTCACHE_LIB_OK 1
120
121 static CLG_LogRef LOG = {"bke.pointcache"};
122
123 static int ptcache_data_size[] = {
124                 sizeof(unsigned int), // BPHYS_DATA_INDEX
125                 3 * sizeof(float), // BPHYS_DATA_LOCATION
126                 3 * sizeof(float), // BPHYS_DATA_VELOCITY
127                 4 * sizeof(float), // BPHYS_DATA_ROTATION
128                 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST
129                 sizeof(float), // BPHYS_DATA_SIZE
130                 3 * sizeof(float), // BPHYS_DATA_TIMES
131                 sizeof(BoidData), // case BPHYS_DATA_BOIDS
132 };
133
134 static int ptcache_extra_datasize[] = {
135         0,
136         sizeof(ParticleSpring),
137 };
138
139 /* forward declarations */
140 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len);
141 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode);
142 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size);
143 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
144
145 /* Common functions */
146 static int ptcache_basic_header_read(PTCacheFile *pf)
147 {
148         int error=0;
149
150         /* Custom functions should read these basic elements too! */
151         if (!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
152                 error = 1;
153
154         if (!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
155                 error = 1;
156
157         return !error;
158 }
159 static int ptcache_basic_header_write(PTCacheFile *pf)
160 {
161         /* Custom functions should write these basic elements too! */
162         if (!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
163                 return 0;
164
165         if (!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
166                 return 0;
167
168         return 1;
169 }
170 /* Softbody functions */
171 static int  ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
172 {
173         SoftBody *soft= soft_v;
174         BodyPoint *bp = soft->bpoint + index;
175
176         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos);
177         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec);
178
179         return 1;
180 }
181 static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data)
182 {
183         SoftBody *soft= soft_v;
184         BodyPoint *bp = soft->bpoint + index;
185
186         if (old_data) {
187                 memcpy(bp->pos, data, 3 * sizeof(float));
188                 memcpy(bp->vec, data + 3, 3 * sizeof(float));
189         }
190         else {
191                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos);
192                 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
193         }
194 }
195 static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
196 {
197         SoftBody *soft= soft_v;
198         BodyPoint *bp = soft->bpoint + index;
199         ParticleKey keys[4];
200         float dfra;
201
202         if (cfra1 == cfra2)
203                 return;
204
205         copy_v3_v3(keys[1].co, bp->pos);
206         copy_v3_v3(keys[1].vel, bp->vec);
207
208         if (old_data) {
209                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
210                 memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
211         }
212         else
213                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
214
215         dfra = cfra2 - cfra1;
216
217         mul_v3_fl(keys[1].vel, dfra);
218         mul_v3_fl(keys[2].vel, dfra);
219
220         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
221
222         mul_v3_fl(keys->vel, 1.0f / dfra);
223
224         copy_v3_v3(bp->pos, keys->co);
225         copy_v3_v3(bp->vec, keys->vel);
226 }
227 static int  ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
228 {
229         SoftBody *soft= soft_v;
230         return soft->totpoint;
231 }
232 static void ptcache_softbody_error(void *UNUSED(soft_v), const char *UNUSED(message))
233 {
234         /* ignored for now */
235 }
236
237 /* Particle functions */
238 void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
239 {
240         PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
241         PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
242
243         /* no rotation info, so make something nice up */
244         if (data[BPHYS_DATA_ROTATION]==NULL) {
245                 vec_to_quat(key->rot, key->vel, OB_NEGX, OB_POSZ);
246         }
247         else {
248                 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
249         }
250
251         PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
252         key->time = time;
253 }
254 static int  ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
255 {
256         ParticleSystem *psys= psys_v;
257         ParticleData *pa = psys->particles + index;
258         BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
259         float times[3];
260         int step = psys->pointcache->step;
261
262         /* No need to store unborn or died particles outside cache step bounds */
263         if (data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step))
264                 return 0;
265
266         times[0] = pa->time;
267         times[1] = pa->dietime;
268         times[2] = pa->lifetime;
269
270         PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
271         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
272         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
273         PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
274         PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
275         PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
276         PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
277
278         if (boid) {
279                 PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
280         }
281
282         /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */
283         return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
284 }
285 static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data)
286 {
287         ParticleSystem *psys= psys_v;
288         ParticleData *pa;
289         BoidParticle *boid;
290         float timestep = 0.04f * psys->part->timetweak;
291
292         if (index >= psys->totpart)
293                 return;
294
295         pa = psys->particles + index;
296         boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
297
298         if (cfra > pa->state.time)
299                 memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
300
301         if (old_data) {
302                 /* old format cache */
303                 memcpy(&pa->state, old_data, sizeof(ParticleKey));
304                 return;
305         }
306
307         BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
308
309         /* set frames cached before birth to birth time */
310         if (cfra < pa->time)
311                 pa->state.time = pa->time;
312         else if (cfra > pa->dietime)
313                 pa->state.time = pa->dietime;
314
315         if (data[BPHYS_DATA_SIZE]) {
316                 PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
317         }
318
319         if (data[BPHYS_DATA_TIMES]) {
320                 float times[3];
321                 PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, &times);
322                 pa->time = times[0];
323                 pa->dietime = times[1];
324                 pa->lifetime = times[2];
325         }
326
327         if (boid) {
328                 PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
329         }
330
331         /* determine velocity from previous location */
332         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
333                 if (cfra > pa->prev_state.time) {
334                         sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
335                         mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep);
336                 }
337                 else {
338                         sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
339                         mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep);
340                 }
341         }
342
343         /* default to no rotation */
344         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
345                 unit_qt(pa->state.rot);
346         }
347 }
348 static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
349 {
350         ParticleSystem *psys= psys_v;
351         ParticleData *pa;
352         ParticleKey keys[4];
353         float dfra, timestep = 0.04f * psys->part->timetweak;
354
355         if (index >= psys->totpart)
356                 return;
357
358         pa = psys->particles + index;
359
360         /* particle wasn't read from first cache so can't interpolate */
361         if ((int)cfra1 < pa->time - psys->pointcache->step || (int)cfra1 > pa->dietime + psys->pointcache->step)
362                 return;
363
364         cfra = MIN2(cfra, pa->dietime);
365         cfra1 = MIN2(cfra1, pa->dietime);
366         cfra2 = MIN2(cfra2, pa->dietime);
367
368         if (cfra1 == cfra2)
369                 return;
370
371         memcpy(keys+1, &pa->state, sizeof(ParticleKey));
372         if (old_data)
373                 memcpy(keys+2, old_data, sizeof(ParticleKey));
374         else
375                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
376
377         /* determine velocity from previous location */
378         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
379                 if (keys[1].time > keys[2].time) {
380                         sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
381                         mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep);
382                 }
383                 else {
384                         sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
385                         mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep);
386                 }
387         }
388
389         /* default to no rotation */
390         if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
391                 unit_qt(keys[2].rot);
392         }
393
394         if (cfra > pa->time)
395                 cfra1 = MAX2(cfra1, pa->time);
396
397         dfra = cfra2 - cfra1;
398
399         mul_v3_fl(keys[1].vel, dfra * timestep);
400         mul_v3_fl(keys[2].vel, dfra * timestep);
401
402         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
403         interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
404
405         mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep));
406
407         pa->state.time = cfra;
408 }
409
410 static int  ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
411 {
412         ParticleSystem *psys = psys_v;
413         return psys->totpart;
414 }
415
416 static void ptcache_particle_error(void *UNUSED(psys_v), const char *UNUSED(message))
417 {
418         /* ignored for now */
419 }
420
421 static int  ptcache_particle_totwrite(void *psys_v, int cfra)
422 {
423         ParticleSystem *psys = psys_v;
424         ParticleData *pa= psys->particles;
425         int p, step = psys->pointcache->step;
426         int totwrite = 0;
427
428         if (cfra == 0)
429                 return psys->totpart;
430
431         for (p=0; p<psys->totpart; p++, pa++)
432                 totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step);
433
434         return totwrite;
435 }
436
437 static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
438 {
439         ParticleSystem *psys = psys_v;
440         PTCacheExtra *extra = NULL;
441
442         if (psys->part->phystype == PART_PHYS_FLUID &&
443             psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS &&
444             psys->tot_fluidsprings && psys->fluid_springs)
445         {
446                 extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data");
447
448                 extra->type = BPHYS_EXTRA_FLUID_SPRINGS;
449                 extra->totdata = psys->tot_fluidsprings;
450
451                 extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data");
452                 memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]);
453
454                 BLI_addtail(&pm->extradata, extra);
455         }
456 }
457
458 static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
459 {
460         ParticleSystem *psys = psys_v;
461         PTCacheExtra *extra = pm->extradata.first;
462
463         for (; extra; extra=extra->next) {
464                 switch (extra->type) {
465                         case BPHYS_EXTRA_FLUID_SPRINGS:
466                         {
467                                 if (psys->fluid_springs)
468                                         MEM_freeN(psys->fluid_springs);
469
470                                 psys->fluid_springs = MEM_dupallocN(extra->data);
471                                 psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata;
472                                 break;
473                         }
474                 }
475         }
476 }
477
478 /* Cloth functions */
479 static int  ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
480 {
481         ClothModifierData *clmd= cloth_v;
482         Cloth *cloth= clmd->clothObject;
483         ClothVertex *vert = cloth->verts + index;
484
485         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x);
486         PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v);
487         PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst);
488
489         return 1;
490 }
491 static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data)
492 {
493         ClothModifierData *clmd= cloth_v;
494         Cloth *cloth= clmd->clothObject;
495         ClothVertex *vert = cloth->verts + index;
496
497         if (old_data) {
498                 memcpy(vert->x, data, 3 * sizeof(float));
499                 memcpy(vert->xconst, data + 3, 3 * sizeof(float));
500                 memcpy(vert->v, data + 6, 3 * sizeof(float));
501         }
502         else {
503                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x);
504                 PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v);
505                 PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst);
506         }
507 }
508 static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
509 {
510         ClothModifierData *clmd= cloth_v;
511         Cloth *cloth= clmd->clothObject;
512         ClothVertex *vert = cloth->verts + index;
513         ParticleKey keys[4];
514         float dfra;
515
516         if (cfra1 == cfra2)
517                 return;
518
519         copy_v3_v3(keys[1].co, vert->x);
520         copy_v3_v3(keys[1].vel, vert->v);
521
522         if (old_data) {
523                 memcpy(keys[2].co, old_data, 3 * sizeof(float));
524                 memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
525         }
526         else
527                 BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
528
529         dfra = cfra2 - cfra1;
530
531         mul_v3_fl(keys[1].vel, dfra);
532         mul_v3_fl(keys[2].vel, dfra);
533
534         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
535
536         mul_v3_fl(keys->vel, 1.0f / dfra);
537
538         copy_v3_v3(vert->x, keys->co);
539         copy_v3_v3(vert->v, keys->vel);
540
541         /* should vert->xconst be interpolated somehow too? - jahka */
542 }
543
544 static int  ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
545 {
546         ClothModifierData *clmd= cloth_v;
547         return clmd->clothObject ? clmd->clothObject->mvert_num : 0;
548 }
549
550 static void ptcache_cloth_error(void *cloth_v, const char *message)
551 {
552         ClothModifierData *clmd= cloth_v;
553         modifier_setError(&clmd->modifier, "%s", message);
554 }
555
556 #ifdef WITH_SMOKE
557 /* Smoke functions */
558 static int  ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
559 {
560         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
561         SmokeDomainSettings *sds = smd->domain;
562
563         if (sds->fluid) {
564                 return sds->base_res[0]*sds->base_res[1]*sds->base_res[2];
565         }
566         else
567                 return 0;
568 }
569
570 static void ptcache_smoke_error(void *smoke_v, const char *message)
571 {
572         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
573         modifier_setError(&smd->modifier, "%s", message);
574 }
575
576 #define SMOKE_CACHE_VERSION "1.04"
577
578 static int  ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
579 {
580         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
581         SmokeDomainSettings *sds = smd->domain;
582         int ret = 0;
583         int fluid_fields = BKE_smoke_get_data_flags(sds);
584
585         /* version header */
586         ptcache_file_write(pf, SMOKE_CACHE_VERSION, 4, sizeof(char));
587         ptcache_file_write(pf, &fluid_fields, 1, sizeof(int));
588         ptcache_file_write(pf, &sds->active_fields, 1, sizeof(int));
589         ptcache_file_write(pf, &sds->res, 3, sizeof(int));
590         ptcache_file_write(pf, &sds->dx, 1, sizeof(float));
591
592         if (sds->fluid) {
593                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
594                 float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
595                 unsigned char *obstacles;
596                 unsigned int in_len = sizeof(float)*(unsigned int)res;
597                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
598                 //int mode = res >= 1000000 ? 2 : 1;
599                 int mode=1;             // light
600                 if (sds->cache_comp == SM_CACHE_HEAVY) mode=2;  // heavy
601
602                 smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
603
604                 ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
605                 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode);
606                 if (fluid_fields & SM_ACTIVE_HEAT) {
607                         ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode);
608                         ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode);
609                 }
610                 if (fluid_fields & SM_ACTIVE_FIRE) {
611                         ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len, out, mode);
612                         ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len, out, mode);
613                         ptcache_file_compressed_write(pf, (unsigned char *)react, in_len, out, mode);
614                 }
615                 if (fluid_fields & SM_ACTIVE_COLORS) {
616                         ptcache_file_compressed_write(pf, (unsigned char *)r, in_len, out, mode);
617                         ptcache_file_compressed_write(pf, (unsigned char *)g, in_len, out, mode);
618                         ptcache_file_compressed_write(pf, (unsigned char *)b, in_len, out, mode);
619                 }
620                 ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode);
621                 ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode);
622                 ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode);
623                 ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
624                 ptcache_file_write(pf, &dt, 1, sizeof(float));
625                 ptcache_file_write(pf, &dx, 1, sizeof(float));
626                 ptcache_file_write(pf, &sds->p0, 3, sizeof(float));
627                 ptcache_file_write(pf, &sds->p1, 3, sizeof(float));
628                 ptcache_file_write(pf, &sds->dp0, 3, sizeof(float));
629                 ptcache_file_write(pf, &sds->shift, 3, sizeof(int));
630                 ptcache_file_write(pf, &sds->obj_shift_f, 3, sizeof(float));
631                 ptcache_file_write(pf, &sds->obmat, 16, sizeof(float));
632                 ptcache_file_write(pf, &sds->base_res, 3, sizeof(int));
633                 ptcache_file_write(pf, &sds->res_min, 3, sizeof(int));
634                 ptcache_file_write(pf, &sds->res_max, 3, sizeof(int));
635                 ptcache_file_write(pf, &sds->active_color, 3, sizeof(float));
636
637                 MEM_freeN(out);
638
639                 ret = 1;
640         }
641
642         if (sds->wt) {
643                 int res_big_array[3];
644                 int res_big;
645                 int res = sds->res[0]*sds->res[1]*sds->res[2];
646                 float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
647                 unsigned int in_len = sizeof(float)*(unsigned int)res;
648                 unsigned int in_len_big;
649                 unsigned char *out;
650                 int mode;
651
652                 smoke_turbulence_get_res(sds->wt, res_big_array);
653                 res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
654                 //mode =  res_big >= 1000000 ? 2 : 1;
655                 mode = 1;       // light
656                 if (sds->cache_high_comp == SM_CACHE_HEAVY) mode=2;     // heavy
657
658                 in_len_big = sizeof(float) * (unsigned int)res_big;
659
660                 smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
661
662                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
663                 ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode);
664                 if (fluid_fields & SM_ACTIVE_FIRE) {
665                         ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len_big, out, mode);
666                         ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len_big, out, mode);
667                         ptcache_file_compressed_write(pf, (unsigned char *)react, in_len_big, out, mode);
668                 }
669                 if (fluid_fields & SM_ACTIVE_COLORS) {
670                         ptcache_file_compressed_write(pf, (unsigned char *)r, in_len_big, out, mode);
671                         ptcache_file_compressed_write(pf, (unsigned char *)g, in_len_big, out, mode);
672                         ptcache_file_compressed_write(pf, (unsigned char *)b, in_len_big, out, mode);
673                 }
674                 MEM_freeN(out);
675
676                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
677                 ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode);
678                 ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode);
679                 ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode);
680                 MEM_freeN(out);
681
682                 ret = 1;
683         }
684
685         return ret;
686 }
687
688 /* read old smoke cache from 2.64 */
689 static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
690 {
691         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
692         SmokeDomainSettings *sds = smd->domain;
693
694         if (sds->fluid) {
695                 const size_t res = sds->res[0] * sds->res[1] * sds->res[2];
696                 const unsigned int out_len = (unsigned int)res * sizeof(float);
697                 float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz;
698                 unsigned char *obstacles;
699                 float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp");
700
701                 int fluid_fields = BKE_smoke_get_data_flags(sds);
702
703                 /* Part part of the new cache header */
704                 sds->active_color[0] = 0.7f;
705                 sds->active_color[1] = 0.7f;
706                 sds->active_color[2] = 0.7f;
707
708                 smoke_export(sds->fluid, &dt, &dx, &dens, NULL, NULL, NULL, &heat, &heatold, &vx, &vy, &vz, NULL, NULL, NULL, &obstacles);
709
710                 ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
711                 ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
712                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
713
714                 if (fluid_fields & SM_ACTIVE_HEAT)
715                 {
716                         ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
717                         ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
718                 }
719                 else
720                 {
721                         ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
722                         ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
723                 }
724                 ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
725                 ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
726                 ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
727                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
728                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
729                 ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
730                 ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
731                 ptcache_file_read(pf, &dt, 1, sizeof(float));
732                 ptcache_file_read(pf, &dx, 1, sizeof(float));
733
734                 MEM_freeN(tmp_array);
735
736                 if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
737                         int res_big, res_big_array[3];
738                         float *tcu, *tcv, *tcw;
739                         unsigned int out_len_big;
740                         unsigned char *tmp_array_big;
741                         smoke_turbulence_get_res(sds->wt, res_big_array);
742                         res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
743                         out_len_big = sizeof(float) * (unsigned int)res_big;
744
745                         tmp_array_big = MEM_callocN(out_len_big, "Smoke old cache tmp");
746
747                         smoke_turbulence_export(sds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw);
748
749                         ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
750                         ptcache_file_compressed_read(pf, (unsigned char*)tmp_array_big, out_len_big);
751
752                         ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
753                         ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
754                         ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
755
756                         MEM_freeN(tmp_array_big);
757                 }
758         }
759
760         return 1;
761 }
762
763 static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
764 {
765         SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
766         SmokeDomainSettings *sds = smd->domain;
767         char version[4];
768         int ch_res[3];
769         float ch_dx;
770         int fluid_fields = BKE_smoke_get_data_flags(sds);
771         int cache_fields = 0;
772         int active_fields = 0;
773         int reallocate = 0;
774
775         /* version header */
776         ptcache_file_read(pf, version, 4, sizeof(char));
777         if (!STREQLEN(version, SMOKE_CACHE_VERSION, 4))
778         {
779                 /* reset file pointer */
780                 fseek(pf->fp, -4, SEEK_CUR);
781                 return ptcache_smoke_read_old(pf, smoke_v);
782         }
783
784         /* fluid info */
785         ptcache_file_read(pf, &cache_fields, 1, sizeof(int));
786         ptcache_file_read(pf, &active_fields, 1, sizeof(int));
787         ptcache_file_read(pf, &ch_res, 3, sizeof(int));
788         ptcache_file_read(pf, &ch_dx, 1, sizeof(float));
789
790         /* check if resolution has changed */
791         if (sds->res[0] != ch_res[0] ||
792             sds->res[1] != ch_res[1] ||
793             sds->res[2] != ch_res[2])
794         {
795                 if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)
796                         reallocate = 1;
797                 else
798                         return 0;
799         }
800         /* check if active fields have changed */
801         if (fluid_fields != cache_fields ||
802                 active_fields != sds->active_fields)
803                 reallocate = 1;
804
805         /* reallocate fluid if needed*/
806         if (reallocate) {
807                 sds->active_fields = active_fields | cache_fields;
808                 BKE_smoke_reallocate_fluid(sds, ch_dx, ch_res, 1);
809                 sds->dx = ch_dx;
810                 copy_v3_v3_int(sds->res, ch_res);
811                 sds->total_cells = ch_res[0]*ch_res[1]*ch_res[2];
812                 if (sds->flags & MOD_SMOKE_HIGHRES) {
813                         BKE_smoke_reallocate_highres_fluid(sds, ch_dx, ch_res, 1);
814                 }
815         }
816
817         if (sds->fluid) {
818                 size_t res = sds->res[0]*sds->res[1]*sds->res[2];
819                 float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
820                 unsigned char *obstacles;
821                 unsigned int out_len = (unsigned int)res * sizeof(float);
822
823                 smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
824
825                 ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
826                 ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len);
827                 if (cache_fields & SM_ACTIVE_HEAT) {
828                         ptcache_file_compressed_read(pf, (unsigned char *)heat, out_len);
829                         ptcache_file_compressed_read(pf, (unsigned char *)heatold, out_len);
830                 }
831                 if (cache_fields & SM_ACTIVE_FIRE) {
832                         ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len);
833                         ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len);
834                         ptcache_file_compressed_read(pf, (unsigned char *)react, out_len);
835                 }
836                 if (cache_fields & SM_ACTIVE_COLORS) {
837                         ptcache_file_compressed_read(pf, (unsigned char *)r, out_len);
838                         ptcache_file_compressed_read(pf, (unsigned char *)g, out_len);
839                         ptcache_file_compressed_read(pf, (unsigned char *)b, out_len);
840                 }
841                 ptcache_file_compressed_read(pf, (unsigned char *)vx, out_len);
842                 ptcache_file_compressed_read(pf, (unsigned char *)vy, out_len);
843                 ptcache_file_compressed_read(pf, (unsigned char *)vz, out_len);
844                 ptcache_file_compressed_read(pf, (unsigned char *)obstacles, (unsigned int)res);
845                 ptcache_file_read(pf, &dt, 1, sizeof(float));
846                 ptcache_file_read(pf, &dx, 1, sizeof(float));
847                 ptcache_file_read(pf, &sds->p0, 3, sizeof(float));
848                 ptcache_file_read(pf, &sds->p1, 3, sizeof(float));
849                 ptcache_file_read(pf, &sds->dp0, 3, sizeof(float));
850                 ptcache_file_read(pf, &sds->shift, 3, sizeof(int));
851                 ptcache_file_read(pf, &sds->obj_shift_f, 3, sizeof(float));
852                 ptcache_file_read(pf, &sds->obmat, 16, sizeof(float));
853                 ptcache_file_read(pf, &sds->base_res, 3, sizeof(int));
854                 ptcache_file_read(pf, &sds->res_min, 3, sizeof(int));
855                 ptcache_file_read(pf, &sds->res_max, 3, sizeof(int));
856                 ptcache_file_read(pf, &sds->active_color, 3, sizeof(float));
857         }
858
859         if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
860                         int res = sds->res[0]*sds->res[1]*sds->res[2];
861                         int res_big, res_big_array[3];
862                         float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
863                         unsigned int out_len = sizeof(float)*(unsigned int)res;
864                         unsigned int out_len_big;
865
866                         smoke_turbulence_get_res(sds->wt, res_big_array);
867                         res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
868                         out_len_big = sizeof(float) * (unsigned int)res_big;
869
870                         smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
871
872                         ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len_big);
873                         if (cache_fields & SM_ACTIVE_FIRE) {
874                                 ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len_big);
875                                 ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len_big);
876                                 ptcache_file_compressed_read(pf, (unsigned char *)react, out_len_big);
877                         }
878                         if (cache_fields & SM_ACTIVE_COLORS) {
879                                 ptcache_file_compressed_read(pf, (unsigned char *)r, out_len_big);
880                                 ptcache_file_compressed_read(pf, (unsigned char *)g, out_len_big);
881                                 ptcache_file_compressed_read(pf, (unsigned char *)b, out_len_big);
882                         }
883
884                         ptcache_file_compressed_read(pf, (unsigned char *)tcu, out_len);
885                         ptcache_file_compressed_read(pf, (unsigned char *)tcv, out_len);
886                         ptcache_file_compressed_read(pf, (unsigned char *)tcw, out_len);
887                 }
888
889         return 1;
890 }
891
892 #ifdef WITH_OPENVDB
893 /**
894  * Construct matrices which represent the fluid object, for low and high res:
895  * <pre>
896  * vs 0  0  0
897  * 0  vs 0  0
898  * 0  0  vs 0
899  * px py pz 1
900  * </pre>
901  *
902  * with `vs` = voxel size, and `px, py, pz`,
903  * the min position of the domain's bounding box.
904  */
905 static void compute_fluid_matrices(SmokeDomainSettings *sds)
906 {
907         float bbox_min[3];
908
909         copy_v3_v3(bbox_min, sds->p0);
910
911         if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
912                 bbox_min[0] += (sds->cell_size[0] * (float)sds->res_min[0]);
913                 bbox_min[1] += (sds->cell_size[1] * (float)sds->res_min[1]);
914                 bbox_min[2] += (sds->cell_size[2] * (float)sds->res_min[2]);
915                 add_v3_v3(bbox_min, sds->obj_shift_f);
916         }
917
918         /* construct low res matrix */
919         size_to_mat4(sds->fluidmat, sds->cell_size);
920         copy_v3_v3(sds->fluidmat[3], bbox_min);
921
922         /* The smoke simulator stores voxels cell-centered, whilst VDB is node
923          * centered, so we offset the matrix by half a voxel to compensate. */
924         madd_v3_v3fl(sds->fluidmat[3], sds->cell_size, 0.5f);
925
926         mul_m4_m4m4(sds->fluidmat, sds->obmat, sds->fluidmat);
927
928         if (sds->wt) {
929                 float voxel_size_high[3];
930                 /* construct high res matrix */
931                 mul_v3_v3fl(voxel_size_high, sds->cell_size, 1.0f / (float)(sds->amplify + 1));
932                 size_to_mat4(sds->fluidmat_wt, voxel_size_high);
933                 copy_v3_v3(sds->fluidmat_wt[3], bbox_min);
934
935                 /* Same here, add half a voxel to adjust the position of the fluid. */
936                 madd_v3_v3fl(sds->fluidmat_wt[3], voxel_size_high, 0.5f);
937
938                 mul_m4_m4m4(sds->fluidmat_wt, sds->obmat, sds->fluidmat_wt);
939         }
940 }
941
942 static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
943 {
944         SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
945         SmokeDomainSettings *sds = smd->domain;
946
947         OpenVDBWriter_set_flags(writer, sds->openvdb_comp, (sds->data_depth == 16));
948
949         OpenVDBWriter_add_meta_int(writer, "blender/smoke/active_fields", sds->active_fields);
950         OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/resolution", sds->res);
951         OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/min_resolution", sds->res_min);
952         OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/max_resolution", sds->res_max);
953         OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/base_resolution", sds->base_res);
954         OpenVDBWriter_add_meta_v3(writer, "blender/smoke/min_bbox", sds->p0);
955         OpenVDBWriter_add_meta_v3(writer, "blender/smoke/max_bbox", sds->p1);
956         OpenVDBWriter_add_meta_v3(writer, "blender/smoke/dp0", sds->dp0);
957         OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/shift", sds->shift);
958         OpenVDBWriter_add_meta_v3(writer, "blender/smoke/obj_shift_f", sds->obj_shift_f);
959         OpenVDBWriter_add_meta_v3(writer, "blender/smoke/active_color", sds->active_color);
960         OpenVDBWriter_add_meta_mat4(writer, "blender/smoke/obmat", sds->obmat);
961
962         int fluid_fields = BKE_smoke_get_data_flags(sds);
963
964         struct OpenVDBFloatGrid *clip_grid = NULL;
965
966         compute_fluid_matrices(sds);
967
968         OpenVDBWriter_add_meta_int(writer, "blender/smoke/fluid_fields", fluid_fields);
969
970         if (sds->wt) {
971                 struct OpenVDBFloatGrid *wt_density_grid;
972                 float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
973
974                 smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
975
976                 wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, sds->clipping, NULL);
977                 clip_grid = wt_density_grid;
978
979                 if (fluid_fields & SM_ACTIVE_FIRE) {
980                         OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
981                         OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
982                         OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
983                 }
984
985                 if (fluid_fields & SM_ACTIVE_COLORS) {
986                         OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, sds->clipping, wt_density_grid);
987                 }
988
989                 OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, sds->clipping, wt_density_grid);
990         }
991
992         if (sds->fluid) {
993                 struct OpenVDBFloatGrid *density_grid;
994                 float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
995                 unsigned char *obstacles;
996
997                 smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
998                              &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
999
1000                 OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
1001                 OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
1002
1003                 const char *name = (!sds->wt) ? "density" : "density_low";
1004                 density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, sds->clipping, NULL);
1005                 clip_grid = sds->wt ? clip_grid : density_grid;
1006
1007                 OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, sds->clipping, NULL);
1008
1009                 if (fluid_fields & SM_ACTIVE_HEAT) {
1010                         OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, sds->clipping, clip_grid);
1011                         OpenVDB_export_grid_fl(writer, "heat_old", heatold, sds->res, sds->fluidmat, sds->clipping, clip_grid);
1012                 }
1013
1014                 if (fluid_fields & SM_ACTIVE_FIRE) {
1015                         name = (!sds->wt) ? "flame" : "flame_low";
1016                         OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, sds->clipping, density_grid);
1017                         name = (!sds->wt) ? "fuel" : "fuel_low";
1018                         OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, sds->clipping, density_grid);
1019                         name = (!sds->wt) ? "react" : "react_low";
1020                         OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, sds->clipping, density_grid);
1021                 }
1022
1023                 if (fluid_fields & SM_ACTIVE_COLORS) {
1024                         name = (!sds->wt) ? "color" : "color_low";
1025                         OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, sds->clipping, density_grid);
1026                 }
1027
1028                 OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, sds->clipping, clip_grid);
1029                 OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, sds->clipping, NULL);
1030         }
1031
1032         return 1;
1033 }
1034
1035 static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
1036 {
1037         SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
1038
1039         if (!smd) {
1040                 return 0;
1041         }
1042
1043         SmokeDomainSettings *sds = smd->domain;
1044
1045         int fluid_fields = BKE_smoke_get_data_flags(sds);
1046         int active_fields, cache_fields = 0;
1047         int cache_res[3];
1048         float cache_dx;
1049         bool reallocate = false;
1050
1051         OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/min_resolution", sds->res_min);
1052         OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/max_resolution", sds->res_max);
1053         OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/base_resolution", sds->base_res);
1054         OpenVDBReader_get_meta_v3(reader, "blender/smoke/min_bbox", sds->p0);
1055         OpenVDBReader_get_meta_v3(reader, "blender/smoke/max_bbox", sds->p1);
1056         OpenVDBReader_get_meta_v3(reader, "blender/smoke/dp0", sds->dp0);
1057         OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/shift", sds->shift);
1058         OpenVDBReader_get_meta_v3(reader, "blender/smoke/obj_shift_f", sds->obj_shift_f);
1059         OpenVDBReader_get_meta_v3(reader, "blender/smoke/active_color", sds->active_color);
1060         OpenVDBReader_get_meta_mat4(reader, "blender/smoke/obmat", sds->obmat);
1061         OpenVDBReader_get_meta_int(reader, "blender/smoke/fluid_fields", &cache_fields);
1062         OpenVDBReader_get_meta_int(reader, "blender/smoke/active_fields", &active_fields);
1063         OpenVDBReader_get_meta_fl(reader, "blender/smoke/dx", &cache_dx);
1064         OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/resolution", cache_res);
1065
1066         /* check if resolution has changed */
1067         if (sds->res[0] != cache_res[0] ||
1068                 sds->res[1] != cache_res[1] ||
1069                 sds->res[2] != cache_res[2])
1070         {
1071                 if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
1072                         reallocate = true;
1073                 }
1074                 else {
1075                         return 0;
1076                 }
1077         }
1078
1079         /* check if active fields have changed */
1080         if ((fluid_fields != cache_fields) || (active_fields != sds->active_fields)) {
1081                 reallocate = true;
1082         }
1083
1084         /* reallocate fluid if needed*/
1085         if (reallocate) {
1086                 sds->active_fields = active_fields | cache_fields;
1087                 BKE_smoke_reallocate_fluid(sds, cache_dx, cache_res, 1);
1088                 sds->dx = cache_dx;
1089                 copy_v3_v3_int(sds->res, cache_res);
1090                 sds->total_cells = cache_res[0] * cache_res[1] * cache_res[2];
1091
1092                 if (sds->flags & MOD_SMOKE_HIGHRES) {
1093                         BKE_smoke_reallocate_highres_fluid(sds, cache_dx, cache_res, 1);
1094                 }
1095         }
1096
1097         if (sds->fluid) {
1098                 float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
1099                 unsigned char *obstacles;
1100
1101                 smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
1102                              &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
1103
1104                 OpenVDBReader_get_meta_fl(reader, "blender/smoke/dt", &dt);
1105
1106                 OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
1107
1108                 const char *name = (!sds->wt) ? "density" : "density_low";
1109                 OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
1110
1111                 if (cache_fields & SM_ACTIVE_HEAT) {
1112                         OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
1113                         OpenVDB_import_grid_fl(reader, "heat_old", &heatold, sds->res);
1114                 }
1115
1116                 if (cache_fields & SM_ACTIVE_FIRE) {
1117                         name = (!sds->wt) ? "flame" : "flame_low";
1118                         OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
1119                         name = (!sds->wt) ? "fuel" : "fuel_low";
1120                         OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
1121                         name = (!sds->wt) ? "react" : "react_low";
1122                         OpenVDB_import_grid_fl(reader, name, &react, sds->res);
1123                 }
1124
1125                 if (cache_fields & SM_ACTIVE_COLORS) {
1126                         name = (!sds->wt) ? "color" : "color_low";
1127                         OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
1128                 }
1129
1130                 OpenVDB_import_grid_vec(reader, "velocity", &vx, &vy, &vz, sds->res);
1131                 OpenVDB_import_grid_ch(reader, "obstacles", &obstacles, sds->res);
1132         }
1133
1134         if (sds->wt) {
1135                 float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
1136
1137                 smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
1138
1139                 OpenVDB_import_grid_fl(reader, "density", &dens, sds->res_wt);
1140
1141                 if (cache_fields & SM_ACTIVE_FIRE) {
1142                         OpenVDB_import_grid_fl(reader, "flame", &flame, sds->res_wt);
1143                         OpenVDB_import_grid_fl(reader, "fuel", &fuel, sds->res_wt);
1144                         OpenVDB_import_grid_fl(reader, "react", &react, sds->res_wt);
1145                 }
1146
1147                 if (cache_fields & SM_ACTIVE_COLORS) {
1148                         OpenVDB_import_grid_vec(reader, "color", &r, &g, &b, sds->res_wt);
1149                 }
1150
1151                 OpenVDB_import_grid_vec(reader, "texture coordinates", &tcu, &tcv, &tcw, sds->res);
1152         }
1153
1154         OpenVDBReader_free(reader);
1155
1156         return 1;
1157 }
1158 #endif
1159
1160 #else // WITH_SMOKE
1161 static int  ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; }
1162 static void ptcache_smoke_error(void *UNUSED(smoke_v), const char *UNUSED(message)) { }
1163 static int  ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
1164 static int  ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
1165 #endif // WITH_SMOKE
1166
1167 #if !defined(WITH_SMOKE) || !defined(WITH_OPENVDB)
1168 static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
1169 {
1170         UNUSED_VARS(writer, smoke_v);
1171         return 0;
1172 }
1173
1174 static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
1175 {
1176         UNUSED_VARS(reader, smoke_v);
1177         return 0;
1178 }
1179 #endif
1180
1181 static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
1182 {
1183         DynamicPaintSurface *surface = (DynamicPaintSurface*)sd;
1184
1185         if (!surface->data) return 0;
1186         else return surface->data->total_points;
1187 }
1188
1189 static void ptcache_dynamicpaint_error(void *UNUSED(sd), const char *UNUSED(message))
1190 {
1191         /* ignored for now */
1192 }
1193
1194 #define DPAINT_CACHE_VERSION "1.01"
1195
1196 static int  ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
1197 {
1198         DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
1199         int cache_compress = 1;
1200
1201         /* version header */
1202         ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char) * 4);
1203
1204         if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
1205                 int total_points=surface->data->total_points;
1206                 unsigned int in_len;
1207                 unsigned char *out;
1208
1209                 /* cache type */
1210                 ptcache_file_write(pf, &surface->type, 1, sizeof(int));
1211
1212                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
1213                         in_len = sizeof(PaintPoint) * total_points;
1214                 }
1215                 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
1216                          surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
1217                 {
1218                         in_len = sizeof(float) * total_points;
1219                 }
1220                 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
1221                         in_len = sizeof(PaintWavePoint) * total_points;
1222                 }
1223                 else {
1224                         return 0;
1225                 }
1226
1227                 out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
1228
1229                 ptcache_file_compressed_write(pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress);
1230                 MEM_freeN(out);
1231
1232         }
1233         return 1;
1234 }
1235 static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
1236 {
1237         DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
1238         char version[4];
1239
1240         /* version header */
1241         ptcache_file_read(pf, version, 1, sizeof(char) * 4);
1242         if (!STREQLEN(version, DPAINT_CACHE_VERSION, 4)) {
1243                 CLOG_ERROR(&LOG, "Dynamic Paint: Invalid cache version: '%c%c%c%c'!", UNPACK4(version));
1244                 return 0;
1245         }
1246
1247         if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
1248                 unsigned int data_len;
1249                 int surface_type;
1250
1251                 /* cache type */
1252                 ptcache_file_read(pf, &surface_type, 1, sizeof(int));
1253
1254                 if (surface_type != surface->type)
1255                         return 0;
1256
1257                 /* read surface data */
1258                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
1259                         data_len = sizeof(PaintPoint);
1260                 }
1261                 else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
1262                          surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
1263                 {
1264                         data_len = sizeof(float);
1265                 }
1266                 else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
1267                         data_len = sizeof(PaintWavePoint);
1268                 }
1269                 else {
1270                         return 0;
1271                 }
1272
1273                 ptcache_file_compressed_read(pf, (unsigned char *)surface->data->type_data, data_len*surface->data->total_points);
1274
1275         }
1276         return 1;
1277 }
1278
1279 /* Rigid Body functions */
1280 static int  ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
1281 {
1282         RigidBodyWorld *rbw = rb_v;
1283         Object *ob = NULL;
1284
1285         if (rbw->objects)
1286                 ob = rbw->objects[index];
1287
1288         if (ob && ob->rigidbody_object) {
1289                 RigidBodyOb *rbo = ob->rigidbody_object;
1290
1291                 if (rbo->type == RBO_TYPE_ACTIVE) {
1292 #ifdef WITH_BULLET
1293                         RB_body_get_position(rbo->shared->physics_object, rbo->pos);
1294                         RB_body_get_orientation(rbo->shared->physics_object, rbo->orn);
1295 #endif
1296                         PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
1297                         PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
1298                 }
1299         }
1300
1301         return 1;
1302 }
1303 static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data)
1304 {
1305         RigidBodyWorld *rbw = rb_v;
1306         Object *ob = NULL;
1307
1308         if (rbw->objects)
1309                 ob = rbw->objects[index];
1310
1311         if (ob && ob->rigidbody_object) {
1312                 RigidBodyOb *rbo = ob->rigidbody_object;
1313
1314                 if (rbo->type == RBO_TYPE_ACTIVE) {
1315
1316                         if (old_data) {
1317                                 memcpy(rbo->pos, data, 3 * sizeof(float));
1318                                 memcpy(rbo->orn, data + 3, 4 * sizeof(float));
1319                         }
1320                         else {
1321                                 PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos);
1322                                 PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn);
1323                         }
1324                 }
1325         }
1326 }
1327 static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
1328 {
1329         RigidBodyWorld *rbw = rb_v;
1330         Object *ob = NULL;
1331
1332         if (rbw->objects)
1333                 ob = rbw->objects[index];
1334
1335         if (ob && ob->rigidbody_object) {
1336                 RigidBodyOb *rbo = ob->rigidbody_object;
1337
1338                 if (rbo->type == RBO_TYPE_ACTIVE) {
1339                         ParticleKey keys[4];
1340                         ParticleKey result;
1341                         float dfra;
1342
1343                         memset(keys, 0, sizeof(keys));
1344
1345                         copy_v3_v3(keys[1].co, rbo->pos);
1346                         copy_qt_qt(keys[1].rot, rbo->orn);
1347
1348                         if (old_data) {
1349                                 memcpy(keys[2].co, data, 3 * sizeof(float));
1350                                 memcpy(keys[2].rot, data + 3, 4 * sizeof(float));
1351                         }
1352                         else {
1353                                 BKE_ptcache_make_particle_key(&keys[2], 0, data, cfra2);
1354                         }
1355
1356                         dfra = cfra2 - cfra1;
1357
1358                         /* note: keys[0] and keys[3] unused for type < 1 (crappy) */
1359                         psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true);
1360                         interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
1361
1362                         copy_v3_v3(rbo->pos, result.co);
1363                         copy_qt_qt(rbo->orn, result.rot);
1364                 }
1365         }
1366 }
1367 static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
1368 {
1369         RigidBodyWorld *rbw = rb_v;
1370
1371         return rbw->numbodies;
1372 }
1373
1374 static void ptcache_rigidbody_error(void *UNUSED(rb_v), const char *UNUSED(message))
1375 {
1376         /* ignored for now */
1377 }
1378
1379 /* Creating ID's */
1380 void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
1381 {
1382         memset(pid, 0, sizeof(PTCacheID));
1383
1384         pid->ob= ob;
1385         pid->calldata= sb;
1386         pid->type= PTCACHE_TYPE_SOFTBODY;
1387         pid->cache= sb->shared->pointcache;
1388         pid->cache_ptr= &sb->shared->pointcache;
1389         pid->ptcaches= &sb->shared->ptcaches;
1390         pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
1391         pid->error                                      = ptcache_softbody_error;
1392
1393         pid->write_point                        = ptcache_softbody_write;
1394         pid->read_point                         = ptcache_softbody_read;
1395         pid->interpolate_point          = ptcache_softbody_interpolate;
1396
1397         pid->write_stream                       = NULL;
1398         pid->read_stream                        = NULL;
1399
1400         pid->write_openvdb_stream       = NULL;
1401         pid->read_openvdb_stream        = NULL;
1402
1403         pid->write_extra_data           = NULL;
1404         pid->read_extra_data            = NULL;
1405         pid->interpolate_extra_data     = NULL;
1406
1407         pid->write_header                       = ptcache_basic_header_write;
1408         pid->read_header                        = ptcache_basic_header_read;
1409
1410         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
1411         pid->info_types= 0;
1412
1413         pid->stack_index = pid->cache->index;
1414
1415         pid->default_step = 10;
1416         pid->max_step = 20;
1417         pid->file_type = PTCACHE_FILE_PTCACHE;
1418 }
1419 void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
1420 {
1421         memset(pid, 0, sizeof(PTCacheID));
1422
1423         pid->ob= ob;
1424         pid->calldata= psys;
1425         pid->type= PTCACHE_TYPE_PARTICLES;
1426         pid->stack_index= psys->pointcache->index;
1427         pid->cache= psys->pointcache;
1428         pid->cache_ptr= &psys->pointcache;
1429         pid->ptcaches= &psys->ptcaches;
1430
1431         if (psys->part->type != PART_HAIR)
1432                 pid->flag |= PTCACHE_VEL_PER_SEC;
1433
1434         pid->totpoint                           = ptcache_particle_totpoint;
1435         pid->totwrite                           = ptcache_particle_totwrite;
1436         pid->error                                      = ptcache_particle_error;
1437
1438         pid->write_point                                = ptcache_particle_write;
1439         pid->read_point                         = ptcache_particle_read;
1440         pid->interpolate_point          = ptcache_particle_interpolate;
1441
1442         pid->write_stream                       = NULL;
1443         pid->read_stream                        = NULL;
1444
1445         pid->write_openvdb_stream       = NULL;
1446         pid->read_openvdb_stream        = NULL;
1447
1448         pid->write_extra_data           = NULL;
1449         pid->read_extra_data            = NULL;
1450         pid->interpolate_extra_data     = NULL;
1451
1452         pid->write_header                       = ptcache_basic_header_write;
1453         pid->read_header                        = ptcache_basic_header_read;
1454
1455         pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
1456
1457         if (psys->part->phystype == PART_PHYS_BOIDS)
1458                 pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
1459         else if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) {
1460                 pid->write_extra_data = ptcache_particle_extra_write;
1461                 pid->read_extra_data = ptcache_particle_extra_read;
1462         }
1463
1464         if (psys->part->flag & PART_ROTATIONS) {
1465                 pid->data_types|= (1<<BPHYS_DATA_ROTATION);
1466
1467                 if (psys->part->rotmode != PART_ROT_VEL  ||
1468                     psys->part->avemode == PART_AVE_RAND ||
1469                     psys->part->avefac != 0.0f)
1470                 {
1471                         pid->data_types |= (1 << BPHYS_DATA_AVELOCITY);
1472                 }
1473         }
1474
1475         pid->info_types= (1<<BPHYS_DATA_TIMES);
1476
1477         pid->default_step = 10;
1478         pid->max_step = 20;
1479         pid->file_type = PTCACHE_FILE_PTCACHE;
1480 }
1481 void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
1482 {
1483         memset(pid, 0, sizeof(PTCacheID));
1484
1485         pid->ob= ob;
1486         pid->calldata= clmd;
1487         pid->type= PTCACHE_TYPE_CLOTH;
1488         pid->stack_index= clmd->point_cache->index;
1489         pid->cache= clmd->point_cache;
1490         pid->cache_ptr= &clmd->point_cache;
1491         pid->ptcaches= &clmd->ptcaches;
1492         pid->totpoint= pid->totwrite= ptcache_cloth_totpoint;
1493         pid->error                                      = ptcache_cloth_error;
1494
1495         pid->write_point                        = ptcache_cloth_write;
1496         pid->read_point                         = ptcache_cloth_read;
1497         pid->interpolate_point          = ptcache_cloth_interpolate;
1498
1499         pid->write_openvdb_stream       = NULL;
1500         pid->read_openvdb_stream        = NULL;
1501
1502         pid->write_stream                       = NULL;
1503         pid->read_stream                        = NULL;
1504
1505         pid->write_extra_data           = NULL;
1506         pid->read_extra_data            = NULL;
1507         pid->interpolate_extra_data     = NULL;
1508
1509         pid->write_header                       = ptcache_basic_header_write;
1510         pid->read_header                        = ptcache_basic_header_read;
1511
1512         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
1513         pid->info_types= 0;
1514
1515         pid->default_step = 1;
1516         pid->max_step = 1;
1517         pid->file_type = PTCACHE_FILE_PTCACHE;
1518 }
1519 void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
1520 {
1521         SmokeDomainSettings *sds = smd->domain;
1522
1523         memset(pid, 0, sizeof(PTCacheID));
1524
1525         pid->ob= ob;
1526         pid->calldata= smd;
1527
1528         pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
1529         pid->stack_index= sds->point_cache[0]->index;
1530
1531         pid->cache= sds->point_cache[0];
1532         pid->cache_ptr= &(sds->point_cache[0]);
1533         pid->ptcaches= &(sds->ptcaches[0]);
1534
1535         pid->totpoint= pid->totwrite= ptcache_smoke_totpoint;
1536         pid->error                                      = ptcache_smoke_error;
1537
1538         pid->write_point                        = NULL;
1539         pid->read_point                         = NULL;
1540         pid->interpolate_point          = NULL;
1541
1542         pid->read_stream                        = ptcache_smoke_read;
1543         pid->write_stream                       = ptcache_smoke_write;
1544
1545         pid->write_openvdb_stream       = ptcache_smoke_openvdb_write;
1546         pid->read_openvdb_stream        = ptcache_smoke_openvdb_read;
1547
1548         pid->write_extra_data           = NULL;
1549         pid->read_extra_data            = NULL;
1550         pid->interpolate_extra_data     = NULL;
1551
1552         pid->write_header                       = ptcache_basic_header_write;
1553         pid->read_header                        = ptcache_basic_header_read;
1554
1555         pid->data_types= 0;
1556         pid->info_types= 0;
1557
1558         if (sds->fluid)
1559                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW);
1560         if (sds->wt)
1561                 pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH);
1562
1563         pid->default_step = 1;
1564         pid->max_step = 1;
1565         pid->file_type = smd->domain->cache_file_format;
1566 }
1567
1568 void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
1569 {
1570
1571         memset(pid, 0, sizeof(PTCacheID));
1572
1573         pid->ob= ob;
1574         pid->calldata= surface;
1575         pid->type= PTCACHE_TYPE_DYNAMICPAINT;
1576         pid->cache= surface->pointcache;
1577         pid->cache_ptr= &surface->pointcache;
1578         pid->ptcaches= &surface->ptcaches;
1579         pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint;
1580         pid->error                                      = ptcache_dynamicpaint_error;
1581
1582         pid->write_point                        = NULL;
1583         pid->read_point                         = NULL;
1584         pid->interpolate_point          = NULL;
1585
1586         pid->write_stream                       = ptcache_dynamicpaint_write;
1587         pid->read_stream                        = ptcache_dynamicpaint_read;
1588
1589         pid->write_openvdb_stream       = NULL;
1590         pid->read_openvdb_stream        = NULL;
1591
1592         pid->write_extra_data           = NULL;
1593         pid->read_extra_data            = NULL;
1594         pid->interpolate_extra_data     = NULL;
1595
1596         pid->write_header                       = ptcache_basic_header_write;
1597         pid->read_header                        = ptcache_basic_header_read;
1598
1599         pid->data_types= BPHYS_DATA_DYNAMICPAINT;
1600         pid->info_types= 0;
1601
1602         pid->stack_index = pid->cache->index;
1603
1604         pid->default_step = 1;
1605         pid->max_step = 1;
1606         pid->file_type = PTCACHE_FILE_PTCACHE;
1607 }
1608
1609 void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
1610 {
1611
1612         memset(pid, 0, sizeof(PTCacheID));
1613
1614         pid->ob= ob;
1615         pid->calldata= rbw;
1616         pid->type= PTCACHE_TYPE_RIGIDBODY;
1617         pid->cache= rbw->shared->pointcache;
1618         pid->cache_ptr= &rbw->shared->pointcache;
1619         pid->ptcaches= &rbw->shared->ptcaches;
1620         pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
1621         pid->error                                      = ptcache_rigidbody_error;
1622
1623         pid->write_point                        = ptcache_rigidbody_write;
1624         pid->read_point                         = ptcache_rigidbody_read;
1625         pid->interpolate_point          = ptcache_rigidbody_interpolate;
1626
1627         pid->write_stream                       = NULL;
1628         pid->read_stream                        = NULL;
1629
1630         pid->write_openvdb_stream       = NULL;
1631         pid->read_openvdb_stream        = NULL;
1632
1633         pid->write_extra_data           = NULL;
1634         pid->read_extra_data            = NULL;
1635         pid->interpolate_extra_data     = NULL;
1636
1637         pid->write_header                       = ptcache_basic_header_write;
1638         pid->read_header                        = ptcache_basic_header_read;
1639
1640         pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_ROTATION);
1641         pid->info_types= 0;
1642
1643         pid->stack_index = pid->cache->index;
1644
1645         pid->default_step = 1;
1646         pid->max_step = 1;
1647         pid->file_type = PTCACHE_FILE_PTCACHE;
1648 }
1649
1650 PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
1651 {
1652         PTCacheID result = {0};
1653
1654         ListBase pidlist;
1655         BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
1656
1657         for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
1658                 if (pid->cache == cache) {
1659                         result = *pid;
1660                         break;
1661                 }
1662         }
1663
1664         BLI_freelistN(&pidlist);
1665
1666         return result;
1667 }
1668
1669 /* Callback which is used by point cache foreach() family of functions.
1670  *
1671  * Receives ID of the point cache.
1672  *
1673  * NOTE: This ID is owned by foreach() routines and can not be used outside of
1674  * the foreach loop. This means that if one wants to store them those are to be
1675  * malloced and copied over.
1676  *
1677  * If the function returns false, then foreach() loop aborts.
1678  */
1679 typedef bool (*ForeachPtcacheCb)(PTCacheID *pid, void *userdata);
1680
1681 static bool foreach_object_particle_ptcache(Object *object,
1682                                             ForeachPtcacheCb callback,
1683                                             void *callback_user_data)
1684 {
1685         PTCacheID pid;
1686         for (ParticleSystem *psys = object->particlesystem.first;
1687              psys != NULL;
1688              psys = psys->next)
1689         {
1690                 if (psys->part==NULL) {
1691                         continue;
1692                 }
1693                 /* Check to make sure point cache is actually used by the particles. */
1694                 if (ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
1695                         continue;
1696                 }
1697                 /* Hair needs to be included in id-list for cache edit mode to work. */
1698 #if 0
1699                 if ((psys->part->type == PART_HAIR) &&
1700                     (psys->flag & PSYS_HAIR_DYNAMICS) == 0)
1701                 {
1702                         continue;
1703                 }
1704 #endif
1705                 if (psys->part->type == PART_FLUID) {
1706                         continue;
1707                 }
1708                 BKE_ptcache_id_from_particles(&pid, object, psys);
1709                 if (!callback(&pid, callback_user_data)) {
1710                         return false;
1711                 }
1712         }
1713         return true;
1714 }
1715
1716 static bool foreach_object_modifier_ptcache(Object *object,
1717                                             ForeachPtcacheCb callback,
1718                                             void *callback_user_data)
1719 {
1720         PTCacheID pid;
1721         for (ModifierData *md = object->modifiers.first; md != NULL; md = md->next) {
1722                 if (md->type == eModifierType_Cloth) {
1723                         BKE_ptcache_id_from_cloth(&pid, object, (ClothModifierData*)md);
1724                         if (!callback(&pid, callback_user_data)) {
1725                                 return false;
1726                         }
1727                 }
1728                 else if (md->type == eModifierType_Smoke) {
1729                         SmokeModifierData *smd = (SmokeModifierData *)md;
1730                         if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1731                                 BKE_ptcache_id_from_smoke(&pid, object, (SmokeModifierData*)md);
1732                                 if (!callback(&pid, callback_user_data)) {
1733                                         return false;
1734                                 }
1735                         }
1736                 }
1737                 else if (md->type == eModifierType_DynamicPaint) {
1738                         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
1739                         if (pmd->canvas) {
1740                                 DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
1741                                 for (; surface; surface=surface->next) {
1742                                         BKE_ptcache_id_from_dynamicpaint(&pid, object, surface);
1743                                         if (!callback(&pid, callback_user_data)) {
1744                                                 return false;
1745                                         }
1746                                 }
1747                         }
1748                 }
1749         }
1750         return true;
1751 }
1752
1753 /* Return false if any of callbacks returned false. */
1754 static bool foreach_object_ptcache(Scene *scene,
1755                                    Object *object,
1756                                    int duplis,
1757                                    ForeachPtcacheCb callback,
1758                                    void *callback_user_data)
1759 {
1760         PTCacheID pid;
1761         /* Soft body. */
1762         if (object->soft != NULL) {
1763                 BKE_ptcache_id_from_softbody(&pid, object, object->soft);
1764                 if (!callback(&pid, callback_user_data)) {
1765                         return false;
1766                 }
1767         }
1768         /* Particle systems. */
1769         if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) {
1770                 return false;
1771         }
1772         /* Modifiers. */
1773         if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) {
1774                 return false;
1775         }
1776         /* Rigid body. */
1777         if (scene != NULL &&
1778             object->rigidbody_object != NULL &&
1779             scene->rigidbody_world != NULL)
1780         {
1781                 BKE_ptcache_id_from_rigidbody(&pid, object, scene->rigidbody_world);
1782                 if (!callback(&pid, callback_user_data)) {
1783                         return false;
1784                 }
1785         }
1786         /* Consider all object in dupli groups to be part of the same object,
1787          * for baking with linking dupligroups. Once we have better overrides
1788          * this can be revisited so users select the local objects directly. */
1789         if (scene != NULL && (duplis-- > 0) && (object->dup_group != NULL)) {
1790                 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(object->dup_group,
1791                                                           current_object)
1792                 {
1793                         if (current_object == object) {
1794                                 continue;
1795                         }
1796                         foreach_object_ptcache(scene,
1797                                                current_object,
1798                                                duplis,
1799                                                callback,
1800                                                callback_user_data);
1801                 }
1802                 FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
1803         }
1804         return true;
1805 }
1806
1807 typedef struct PTCacheIDsFromObjectData {
1808         ListBase *list_base;
1809 } PTCacheIDsFromObjectData;
1810
1811 static bool ptcache_ids_from_object_cb(PTCacheID *pid, void *userdata)
1812 {
1813         PTCacheIDsFromObjectData *data = userdata;
1814         PTCacheID *own_pid = MEM_mallocN(sizeof(PTCacheID), "PTCacheID");
1815         *own_pid = *pid;
1816         BLI_addtail(data->list_base, own_pid);
1817         return true;
1818 }
1819
1820 void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
1821 {
1822         PTCacheIDsFromObjectData data;
1823         lb->first = lb->last = NULL;
1824         data.list_base = lb;
1825         foreach_object_ptcache(
1826                 scene, ob, duplis, ptcache_ids_from_object_cb, &data);
1827 }
1828
1829 static bool ptcache_object_has_cb(PTCacheID *UNUSED(pid),
1830                                   void *UNUSED(userdata))
1831 {
1832         return false;
1833 }
1834
1835 bool BKE_ptcache_object_has(struct Scene *scene, struct Object *ob, int duplis)
1836 {
1837         return !foreach_object_ptcache(
1838                 scene, ob, duplis, ptcache_object_has_cb, NULL);
1839 }
1840
1841 /* File handling */
1842
1843 static const char *ptcache_file_extension(const PTCacheID *pid)
1844 {
1845         switch (pid->file_type) {
1846                 default:
1847                 case PTCACHE_FILE_PTCACHE:
1848                         return PTCACHE_EXT;
1849                 case PTCACHE_FILE_OPENVDB:
1850                         return ".vdb";
1851         }
1852 }
1853
1854 /**
1855  * Similar to #BLI_path_frame_get, but takes into account the stack-index which is after the frame.
1856  */
1857 static int ptcache_frame_from_filename(const char *filename, const char *ext)
1858 {
1859         const int frame_len = 6;
1860         const int ext_len = frame_len + strlen(ext);
1861         const int len = strlen(filename);
1862
1863         /* could crash if trying to copy a string out of this range */
1864         if (len > ext_len) {
1865                 /* using frame_len here gives compile error (vla) */
1866                 char num[/* frame_len */6 + 1];
1867                 BLI_strncpy(num, filename + len - ext_len, sizeof(num));
1868
1869                 return atoi(num);
1870         }
1871
1872         return -1;
1873 }
1874
1875 /* Takes an Object ID and returns a unique name
1876  * - id: object id
1877  * - cfra: frame for the cache, can be negative
1878  * - stack_index: index in the modifier stack. we can have cache for more than one stack_index
1879  */
1880
1881 #define MAX_PTCACHE_PATH FILE_MAX
1882 #define MAX_PTCACHE_FILE (FILE_MAX * 2)
1883
1884 static int ptcache_path(PTCacheID *pid, char *filename)
1885 {
1886         Library *lib = (pid->ob) ? pid->ob->id.lib : NULL;
1887         const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: BKE_main_blendfile_path_from_global();
1888         size_t i;
1889
1890         if (pid->cache->flag & PTCACHE_EXTERNAL) {
1891                 strcpy(filename, pid->cache->path);
1892
1893                 if (BLI_path_is_rel(filename)) {
1894                         BLI_path_abs(filename, blendfilename);
1895                 }
1896
1897                 return BLI_add_slash(filename); /* new strlen() */
1898         }
1899         else if (G.relbase_valid || lib) {
1900                 char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
1901
1902                 BLI_split_file_part(blendfilename, file, sizeof(file));
1903                 i = strlen(file);
1904
1905                 /* remove .blend */
1906                 if (i > 6)
1907                         file[i-6] = '\0';
1908
1909                 BLI_snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
1910                 BLI_path_abs(filename, blendfilename);
1911                 return BLI_add_slash(filename); /* new strlen() */
1912         }
1913
1914         /* use the temp path. this is weak but better then not using point cache at all */
1915         /* temporary directory is assumed to exist and ALWAYS has a trailing slash */
1916         BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BKE_tempdir_session());
1917
1918         return BLI_add_slash(filename); /* new strlen() */
1919 }
1920
1921 static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
1922 {
1923         int len=0;
1924         char *idname;
1925         char *newname;
1926         filename[0] = '\0';
1927         newname = filename;
1928
1929         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
1930
1931         /* start with temp dir */
1932         if (do_path) {
1933                 len = ptcache_path(pid, filename);
1934                 newname += len;
1935         }
1936         if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
1937                 idname = (pid->ob->id.name + 2);
1938                 /* convert chars to hex so they are always a valid filename */
1939                 while ('\0' != *idname) {
1940                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (unsigned int)(*idname++));
1941                         newname+=2;
1942                         len += 2;
1943                 }
1944         }
1945         else {
1946                 int temp = (int)strlen(pid->cache->name);
1947                 strcpy(newname, pid->cache->name);
1948                 newname+=temp;
1949                 len += temp;
1950         }
1951
1952         if (do_ext) {
1953                 if (pid->cache->index < 0)
1954                         pid->cache->index =  pid->stack_index = BKE_object_insert_ptcache(pid->ob);
1955
1956                 const char *ext = ptcache_file_extension(pid);
1957
1958                 if (pid->cache->flag & PTCACHE_EXTERNAL) {
1959                         if (pid->cache->index >= 0)
1960                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
1961                         else
1962                                 BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d%s", cfra, ext); /* always 6 chars */
1963                 }
1964                 else {
1965                         BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
1966                 }
1967                 len += 16;
1968         }
1969
1970         return len; /* make sure the above string is always 16 chars */
1971 }
1972
1973 /* youll need to close yourself after! */
1974 static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
1975 {
1976         PTCacheFile *pf;
1977         FILE *fp = NULL;
1978         char filename[FILE_MAX * 2];
1979
1980 #ifndef DURIAN_POINTCACHE_LIB_OK
1981         /* don't allow writing for linked objects */
1982         if (pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
1983                 return NULL;
1984 #endif
1985         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
1986
1987         ptcache_filename(pid, filename, cfra, 1, 1);
1988
1989         if (mode==PTCACHE_FILE_READ) {
1990                 fp = BLI_fopen(filename, "rb");
1991         }
1992         else if (mode==PTCACHE_FILE_WRITE) {
1993                 BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
1994                 fp = BLI_fopen(filename, "wb");
1995         }
1996         else if (mode==PTCACHE_FILE_UPDATE) {
1997                 BLI_make_existing_file(filename);
1998                 fp = BLI_fopen(filename, "rb+");
1999         }
2000
2001         if (!fp)
2002                 return NULL;
2003
2004         pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
2005         pf->fp= fp;
2006         pf->old_format = 0;
2007         pf->frame = cfra;
2008
2009         return pf;
2010 }
2011 static void ptcache_file_close(PTCacheFile *pf)
2012 {
2013         if (pf) {
2014                 fclose(pf->fp);
2015                 MEM_freeN(pf);
2016         }
2017 }
2018
2019 static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
2020 {
2021         int r = 0;
2022         unsigned char compressed = 0;
2023         size_t in_len;
2024 #ifdef WITH_LZO
2025         size_t out_len = len;
2026 #endif
2027         unsigned char *in;
2028         unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
2029
2030         ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
2031         if (compressed) {
2032                 unsigned int size;
2033                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
2034                 in_len = (size_t)size;
2035                 if (in_len==0) {
2036                         /* do nothing */
2037                 }
2038                 else {
2039                         in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
2040                         ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
2041 #ifdef WITH_LZO
2042                         if (compressed == 1)
2043                                 r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
2044 #endif
2045 #ifdef WITH_LZMA
2046                         if (compressed == 2) {
2047                                 size_t sizeOfIt;
2048                                 size_t leni = in_len, leno = len;
2049                                 ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
2050                                 sizeOfIt = (size_t)size;
2051                                 ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
2052                                 r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
2053                         }
2054 #endif
2055                         MEM_freeN(in);
2056                 }
2057         }
2058         else {
2059                 ptcache_file_read(pf, result, len, sizeof(unsigned char));
2060         }
2061
2062         MEM_freeN(props);
2063
2064         return r;
2065 }
2066 static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
2067 {
2068         int r = 0;
2069         unsigned char compressed = 0;
2070         size_t out_len= 0;
2071         unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
2072         size_t sizeOfIt = 5;
2073
2074         (void)mode; /* unused when building w/o compression */
2075
2076 #ifdef WITH_LZO
2077         out_len= LZO_OUT_LEN(in_len);
2078         if (mode == 1) {
2079                 LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
2080
2081                 r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
2082                 if (!(r == LZO_E_OK) || (out_len >= in_len))
2083                         compressed = 0;
2084                 else
2085                         compressed = 1;
2086         }
2087 #endif
2088 #ifdef WITH_LZMA
2089         if (mode == 2) {
2090
2091                 r = LzmaCompress(out, &out_len, in, in_len, //assume sizeof(char)==1....
2092                                  props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
2093
2094                 if (!(r == SZ_OK) || (out_len >= in_len))
2095                         compressed = 0;
2096                 else
2097                         compressed = 2;
2098         }
2099 #endif
2100
2101         ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
2102         if (compressed) {
2103                 unsigned int size = out_len;
2104                 ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
2105                 ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
2106         }
2107         else
2108                 ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
2109
2110         if (compressed == 2) {
2111                 unsigned int size = sizeOfIt;
2112                 ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
2113                 ptcache_file_write(pf, props, size, sizeof(unsigned char));
2114         }
2115
2116         MEM_freeN(props);
2117
2118         return r;
2119 }
2120 static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
2121 {
2122         return (fread(f, size, tot, pf->fp) == tot);
2123 }
2124 static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size)
2125 {
2126         return (fwrite(f, size, tot, pf->fp) == tot);
2127 }
2128 static int ptcache_file_data_read(PTCacheFile *pf)
2129 {
2130         int i;
2131
2132         for (i=0; i<BPHYS_TOT_DATA; i++) {
2133                 if ((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
2134                         return 0;
2135         }
2136
2137         return 1;
2138 }
2139 static int ptcache_file_data_write(PTCacheFile *pf)
2140 {
2141         int i;
2142
2143         for (i=0; i<BPHYS_TOT_DATA; i++) {
2144                 if ((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
2145                         return 0;
2146         }
2147
2148         return 1;
2149 }
2150 static int ptcache_file_header_begin_read(PTCacheFile *pf)
2151 {
2152         unsigned int typeflag=0;
2153         int error=0;
2154         char bphysics[8];
2155
2156         pf->data_types = 0;
2157
2158         if (fread(bphysics, sizeof(char), 8, pf->fp) != 8)
2159                 error = 1;
2160
2161         if (!error && !STREQLEN(bphysics, "BPHYSICS", 8))
2162                 error = 1;
2163
2164         if (!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp))
2165                 error = 1;
2166
2167         pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
2168         pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
2169
2170         /* if there was an error set file as it was */
2171         if (error)
2172                 fseek(pf->fp, 0, SEEK_SET);
2173
2174         return !error;
2175 }
2176 static int ptcache_file_header_begin_write(PTCacheFile *pf)
2177 {
2178         const char *bphysics = "BPHYSICS";
2179         unsigned int typeflag = pf->type + pf->flag;
2180
2181         if (fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
2182                 return 0;
2183
2184         if (!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp))
2185                 return 0;
2186
2187         return 1;
2188 }
2189
2190 /* Data pointer handling */
2191 int BKE_ptcache_data_size(int data_type)
2192 {
2193         return ptcache_data_size[data_type];
2194 }
2195
2196 static void ptcache_file_pointers_init(PTCacheFile *pf)
2197 {
2198         int data_types = pf->data_types;
2199
2200         pf->cur[BPHYS_DATA_INDEX] =             (data_types & (1<<BPHYS_DATA_INDEX))    ?               &pf->data.index : NULL;
2201         pf->cur[BPHYS_DATA_LOCATION] =  (data_types & (1<<BPHYS_DATA_LOCATION)) ?               &pf->data.loc   : NULL;
2202         pf->cur[BPHYS_DATA_VELOCITY] =  (data_types & (1<<BPHYS_DATA_VELOCITY)) ?               &pf->data.vel   : NULL;
2203         pf->cur[BPHYS_DATA_ROTATION] =  (data_types & (1<<BPHYS_DATA_ROTATION)) ?               &pf->data.rot   : NULL;
2204         pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))?               &pf->data.ave   : NULL;
2205         pf->cur[BPHYS_DATA_SIZE] =              (data_types & (1<<BPHYS_DATA_SIZE))             ?               &pf->data.size  : NULL;
2206         pf->cur[BPHYS_DATA_TIMES] =             (data_types & (1<<BPHYS_DATA_TIMES))    ?               &pf->data.times : NULL;
2207         pf->cur[BPHYS_DATA_BOIDS] =             (data_types & (1<<BPHYS_DATA_BOIDS))    ?               &pf->data.boids : NULL;
2208 }
2209
2210 /* Check to see if point number "index" is in pm, uses binary search for index data. */
2211 int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
2212 {
2213         if (pm->totpoint > 0 && pm->data[BPHYS_DATA_INDEX]) {
2214                 unsigned int *data = pm->data[BPHYS_DATA_INDEX];
2215                 unsigned int mid, low = 0, high = pm->totpoint - 1;
2216
2217                 if (index < *data || index > *(data+high))
2218                         return -1;
2219
2220                 /* check simple case for continuous indexes first */
2221                 if (index-*data < high && data[index-*data] == index)
2222                         return index-*data;
2223
2224                 while (low <= high) {
2225                         mid= (low + high)/2;
2226
2227                         if (data[mid] > index)
2228                                 high = mid - 1;
2229                         else if (data[mid] < index)
2230                                 low = mid + 1;
2231                         else
2232                                 return mid;
2233                 }
2234
2235                 return -1;
2236         }
2237         else {
2238                 return (index < pm->totpoint ? index : -1);
2239         }
2240 }
2241
2242 void BKE_ptcache_mem_pointers_init(PTCacheMem *pm)
2243 {
2244         int data_types = pm->data_types;
2245         int i;
2246
2247         for (i=0; i<BPHYS_TOT_DATA; i++)
2248                 pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL);
2249 }
2250
2251 void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
2252 {
2253         int i;
2254
2255         for (i=0; i<BPHYS_TOT_DATA; i++) {
2256                 if (pm->cur[i])
2257                         pm->cur[i] = (char *)pm->cur[i] + ptcache_data_size[i];
2258         }
2259 }
2260 int  BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
2261 {
2262         int data_types = pm->data_types;
2263         int i, index = BKE_ptcache_mem_index_find(pm, point_index);
2264
2265         if (index < 0) {
2266                 /* Can't give proper location without reallocation, so don't give any location.
2267                  * Some points will be cached improperly, but this only happens with simulation
2268                  * steps bigger than cache->step, so the cache has to be recalculated anyways
2269                  * at some point.
2270                  */
2271                 return 0;
2272         }
2273
2274         for (i=0; i<BPHYS_TOT_DATA; i++)
2275                 pm->cur[i] = data_types & (1<<i) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL;
2276
2277         return 1;
2278 }
2279 static void ptcache_data_alloc(PTCacheMem *pm)
2280 {
2281         int data_types = pm->data_types;
2282         int totpoint = pm->totpoint;
2283         int i;
2284
2285         for (i=0; i<BPHYS_TOT_DATA; i++) {
2286                 if (data_types & (1<<i))
2287                         pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
2288         }
2289 }
2290 static void ptcache_data_free(PTCacheMem *pm)
2291 {
2292         void **data = pm->data;
2293         int i;
2294
2295         for (i=0; i<BPHYS_TOT_DATA; i++) {
2296                 if (data[i])
2297                         MEM_freeN(data[i]);
2298         }
2299 }
2300 static void ptcache_data_copy(void *from[], void *to[])
2301 {
2302         int i;
2303         for (i=0; i<BPHYS_TOT_DATA; i++) {
2304                 /* note, durian file 03.4b_comp crashes if to[i] is not tested
2305                  * its NULL, not sure if this should be fixed elsewhere but for now its needed */
2306                 if (from[i] && to[i])
2307                         memcpy(to[i], from[i], ptcache_data_size[i]);
2308         }
2309 }
2310
2311 static void ptcache_extra_free(PTCacheMem *pm)
2312 {
2313         PTCacheExtra *extra = pm->extradata.first;
2314
2315         if (extra) {
2316                 for (; extra; extra=extra->next) {
2317                         if (extra->data)
2318                                 MEM_freeN(extra->data);
2319                 }
2320
2321                 BLI_freelistN(&pm->extradata);
2322         }
2323 }
2324 static int ptcache_old_elemsize(PTCacheID *pid)
2325 {
2326         if (pid->type==PTCACHE_TYPE_SOFTBODY)
2327                 return 6 * sizeof(float);
2328         else if (pid->type==PTCACHE_TYPE_PARTICLES)
2329                 return sizeof(ParticleKey);
2330         else if (pid->type==PTCACHE_TYPE_CLOTH)
2331                 return 9 * sizeof(float);
2332
2333         return 0;
2334 }
2335
2336 static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
2337 {
2338         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2339                 int cfra1=frame, cfra2=frame+1;
2340
2341                 while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1))
2342                         cfra1--;
2343
2344                 if (cfra1 < pid->cache->startframe)
2345                         cfra1 = 0;
2346
2347                 while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2))
2348                         cfra2++;
2349
2350                 if (cfra2 > pid->cache->endframe)
2351                         cfra2 = 0;
2352
2353                 if (cfra1 && !cfra2) {
2354                         *fra1 = 0;
2355                         *fra2 = cfra1;
2356                 }
2357                 else {
2358                         *fra1 = cfra1;
2359                         *fra2 = cfra2;
2360                 }
2361         }
2362         else if (pid->cache->mem_cache.first) {
2363                 PTCacheMem *pm = pid->cache->mem_cache.first;
2364                 PTCacheMem *pm2 = pid->cache->mem_cache.last;
2365
2366                 while (pm->next && pm->next->frame <= frame)
2367                         pm= pm->next;
2368
2369                 if (pm2->frame < frame) {
2370                         pm2 = NULL;
2371                 }
2372                 else {
2373                         while (pm2->prev && pm2->prev->frame > frame) {
2374                                 pm2= pm2->prev;
2375                         }
2376                 }
2377
2378                 if (!pm2) {
2379                         *fra1 = 0;
2380                         *fra2 = pm->frame;
2381                 }
2382                 else {
2383                         *fra1 = pm->frame;
2384                         *fra2 = pm2->frame;
2385                 }
2386         }
2387 }
2388
2389 static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
2390 {
2391         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
2392         PTCacheMem *pm = NULL;
2393         unsigned int i, error = 0;
2394
2395         if (pf == NULL)
2396                 return NULL;
2397
2398         if (!ptcache_file_header_begin_read(pf))
2399                 error = 1;
2400
2401         if (!error && (pf->type != pid->type || !pid->read_header(pf)))
2402                 error = 1;
2403
2404         if (!error) {
2405                 pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2406
2407                 pm->totpoint = pf->totpoint;
2408                 pm->data_types = pf->data_types;
2409                 pm->frame = pf->frame;
2410
2411                 ptcache_data_alloc(pm);
2412
2413                 if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
2414                         for (i=0; i<BPHYS_TOT_DATA; i++) {
2415                                 unsigned int out_len = pm->totpoint*ptcache_data_size[i];
2416                                 if (pf->data_types & (1<<i))
2417                                         ptcache_file_compressed_read(pf, (unsigned char *)(pm->data[i]), out_len);
2418                         }
2419                 }
2420                 else {
2421                         BKE_ptcache_mem_pointers_init(pm);
2422                         ptcache_file_pointers_init(pf);
2423
2424                         for (i=0; i<pm->totpoint; i++) {
2425                                 if (!ptcache_file_data_read(pf)) {
2426                                         error = 1;
2427                                         break;
2428                                 }
2429                                 ptcache_data_copy(pf->cur, pm->cur);
2430                                 BKE_ptcache_mem_pointers_incr(pm);
2431                         }
2432                 }
2433         }
2434
2435         if (!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) {
2436                 unsigned int extratype = 0;
2437
2438                 while (ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) {
2439                         PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata");
2440
2441                         extra->type = extratype;
2442
2443                         ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int));
2444
2445                         extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data");
2446
2447                         if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS)
2448                                 ptcache_file_compressed_read(pf, (unsigned char *)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]);
2449                         else
2450                                 ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
2451
2452                         BLI_addtail(&pm->extradata, extra);
2453                 }
2454         }
2455
2456         if (error && pm) {
2457                 ptcache_data_free(pm);
2458                 ptcache_extra_free(pm);
2459                 MEM_freeN(pm);
2460                 pm = NULL;
2461         }
2462
2463         ptcache_file_close(pf);
2464
2465         if (error && G.debug & G_DEBUG)
2466                 printf("Error reading from disk cache\n");
2467
2468         return pm;
2469 }
2470 static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
2471 {
2472         PTCacheFile *pf = NULL;
2473         unsigned int i, error = 0;
2474
2475         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame);
2476
2477         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
2478
2479         if (pf == NULL) {
2480                 if (G.debug & G_DEBUG)
2481                         printf("Error opening disk cache file for writing\n");
2482                 return 0;
2483         }
2484
2485         pf->data_types = pm->data_types;
2486         pf->totpoint = pm->totpoint;
2487         pf->type = pid->type;
2488         pf->flag = 0;
2489
2490         if (pm->extradata.first)
2491                 pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
2492
2493         if (pid->cache->compression)
2494                 pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
2495
2496         if (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))
2497                 error = 1;
2498
2499         if (!error) {
2500                 if (pid->cache->compression) {
2501                         for (i=0; i<BPHYS_TOT_DATA; i++) {
2502                                 if (pm->data[i]) {
2503                                         unsigned int in_len = pm->totpoint*ptcache_data_size[i];
2504                                         unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
2505                                         ptcache_file_compressed_write(pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression);
2506                                         MEM_freeN(out);
2507                                 }
2508                         }
2509                 }
2510                 else {
2511                         BKE_ptcache_mem_pointers_init(pm);
2512                         ptcache_file_pointers_init(pf);
2513
2514                         for (i=0; i<pm->totpoint; i++) {
2515                                 ptcache_data_copy(pm->cur, pf->cur);
2516                                 if (!ptcache_file_data_write(pf)) {
2517                                         error = 1;
2518                                         break;
2519                                 }
2520                                 BKE_ptcache_mem_pointers_incr(pm);
2521                         }
2522                 }
2523         }
2524
2525         if (!error && pm->extradata.first) {
2526                 PTCacheExtra *extra = pm->extradata.first;
2527
2528                 for (; extra; extra=extra->next) {
2529                         if (extra->data == NULL || extra->totdata == 0)
2530                                 continue;
2531
2532                         ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
2533                         ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
2534
2535                         if (pid->cache->compression) {
2536                                 unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
2537                                 unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
2538                                 ptcache_file_compressed_write(pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression);
2539                                 MEM_freeN(out);
2540                         }
2541                         else {
2542                                 ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
2543                         }
2544                 }
2545         }
2546
2547         ptcache_file_close(pf);
2548
2549         if (error && G.debug & G_DEBUG)
2550                 printf("Error writing to disk cache\n");
2551
2552         return error==0;
2553 }
2554
2555 static int ptcache_read_stream(PTCacheID *pid, int cfra)
2556 {
2557         PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
2558         int error = 0;
2559
2560         if (pid->read_stream == NULL)
2561                 return 0;
2562
2563         if (pf == NULL) {
2564                 if (G.debug & G_DEBUG)
2565                         printf("Error opening disk cache file for reading\n");
2566                 return 0;
2567         }
2568
2569         if (!ptcache_file_header_begin_read(pf)) {
2570                 pid->error(pid->calldata, "Failed to read point cache file");
2571                 error = 1;
2572         }
2573         else if (pf->type != pid->type) {
2574                 pid->error(pid->calldata, "Point cache file has wrong type");
2575                 error = 1;
2576         }
2577         else if (!pid->read_header(pf)) {
2578                 pid->error(pid->calldata, "Failed to read point cache file header");
2579                 error = 1;
2580         }
2581         else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) {
2582                 pid->error(pid->calldata, "Number of points in cache does not match mesh");
2583                 error = 1;
2584         }
2585
2586         if (!error) {
2587                 ptcache_file_pointers_init(pf);
2588
2589                 // we have stream reading here
2590                 if (!pid->read_stream(pf, pid->calldata)) {
2591                         pid->error(pid->calldata, "Failed to read point cache file data");
2592                         error = 1;
2593                 }
2594         }
2595
2596         ptcache_file_close(pf);
2597
2598         return error == 0;
2599 }
2600
2601 static int ptcache_read_openvdb_stream(PTCacheID *pid, int cfra)
2602 {
2603 #ifdef WITH_OPENVDB
2604         char filename[FILE_MAX * 2];
2605
2606         /* save blend file before using disk pointcache */
2607         if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0)
2608                 return 0;
2609
2610         ptcache_filename(pid, filename, cfra, 1, 1);
2611
2612         if (!BLI_exists(filename)) {
2613                 return 0;
2614         }
2615
2616         struct OpenVDBReader *reader = OpenVDBReader_create();
2617         OpenVDBReader_open(reader, filename);
2618
2619         if (!pid->read_openvdb_stream(reader, pid->calldata)) {
2620                 return 0;
2621         }
2622
2623         return 1;
2624 #else
2625         UNUSED_VARS(pid, cfra);
2626         return 0;
2627 #endif
2628 }
2629
2630 static int ptcache_read(PTCacheID *pid, int cfra)
2631 {
2632         PTCacheMem *pm = NULL;
2633         int i;
2634         int *index = &i;
2635
2636         /* get a memory cache to read from */
2637         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2638                 pm = ptcache_disk_frame_to_mem(pid, cfra);
2639         }
2640         else {
2641                 pm = pid->cache->mem_cache.first;
2642
2643                 while (pm && pm->frame != cfra)
2644                         pm = pm->next;
2645         }
2646
2647         /* read the cache */
2648         if (pm) {
2649                 int totpoint = pm->totpoint;
2650
2651                 if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) {
2652                         int pid_totpoint = pid->totpoint(pid->calldata, cfra);
2653
2654                         if (totpoint != pid_totpoint) {
2655                                 pid->error(pid->calldata, "Number of points in cache does not match mesh");
2656                                 totpoint = MIN2(totpoint, pid_totpoint);
2657                         }
2658                 }
2659
2660                 BKE_ptcache_mem_pointers_init(pm);
2661
2662                 for (i=0; i<totpoint; i++) {
2663                         if (pm->data_types & (1<<BPHYS_DATA_INDEX))
2664                                 index = pm->cur[BPHYS_DATA_INDEX];
2665
2666                         pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL);
2667
2668                         BKE_ptcache_mem_pointers_incr(pm);
2669                 }
2670
2671                 if (pid->read_extra_data && pm->extradata.first)
2672                         pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
2673
2674                 /* clean up temporary memory cache */
2675                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2676                         ptcache_data_free(pm);
2677                         ptcache_extra_free(pm);
2678                         MEM_freeN(pm);
2679                 }
2680         }
2681
2682         return 1;
2683 }
2684 static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
2685 {
2686         PTCacheMem *pm = NULL;
2687         int i;
2688         int *index = &i;
2689
2690         /* get a memory cache to read from */
2691         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2692                 pm = ptcache_disk_frame_to_mem(pid, cfra2);
2693         }
2694         else {
2695                 pm = pid->cache->mem_cache.first;
2696
2697                 while (pm && pm->frame != cfra2)
2698                         pm = pm->next;
2699         }
2700
2701         /* read the cache */
2702         if (pm) {
2703                 int totpoint = pm->totpoint;
2704
2705                 if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) {
2706                         int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra);
2707
2708                         if (totpoint != pid_totpoint) {
2709                                 pid->error(pid->calldata, "Number of points in cache does not match mesh");
2710                                 totpoint = MIN2(totpoint, pid_totpoint);
2711                         }
2712                 }
2713
2714                 BKE_ptcache_mem_pointers_init(pm);
2715
2716                 for (i=0; i<totpoint; i++) {
2717                         if (pm->data_types & (1<<BPHYS_DATA_INDEX))
2718                                 index = pm->cur[BPHYS_DATA_INDEX];
2719
2720                         pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL);
2721                         BKE_ptcache_mem_pointers_incr(pm);
2722                 }
2723
2724                 if (pid->interpolate_extra_data && pm->extradata.first)
2725                         pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
2726
2727                 /* clean up temporary memory cache */
2728                 if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2729                         ptcache_data_free(pm);
2730                         ptcache_extra_free(pm);
2731                         MEM_freeN(pm);
2732                 }
2733         }
2734
2735         return 1;
2736 }
2737 /* reads cache from disk or memory */
2738 /* possible to get old or interpolated result */
2739 int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
2740 {
2741         int cfrai = (int)floor(cfra), cfra1=0, cfra2=0;
2742         int ret = 0;
2743
2744         /* nothing to read to */
2745         if (pid->totpoint(pid->calldata, cfrai) == 0)
2746                 return 0;
2747
2748         if (pid->cache->flag & PTCACHE_READ_INFO) {
2749                 pid->cache->flag &= ~PTCACHE_READ_INFO;
2750                 ptcache_read(pid, 0);
2751         }
2752
2753         /* first check if we have the actual frame cached */
2754         if (cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai))
2755                 cfra1 = cfrai;
2756
2757         /* no exact cache frame found so try to find cached frames around cfra */
2758         if (cfra1 == 0)
2759                 ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
2760
2761         if (cfra1 == 0 && cfra2 == 0)
2762                 return 0;
2763
2764         /* don't read old cache if already simulated past cached frame */
2765         if (no_extrapolate_old) {
2766                 if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
2767                         return 0;
2768                 if (cfra1 && cfra1 == cfra2)
2769                         return 0;
2770         }
2771         else {
2772                 /* avoid calling interpolate between the same frame values */
2773                 if (cfra1 && cfra1 == cfra2)
2774                         cfra1 = 0;
2775         }
2776
2777         if (cfra1) {
2778                 if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
2779                         if (!ptcache_read_openvdb_stream(pid, cfra1)) {
2780                                 return 0;
2781                         }
2782                 }
2783                 else if (pid->read_stream) {
2784                         if (!ptcache_read_stream(pid, cfra1))
2785                                 return 0;
2786                 }
2787                 else if (pid->read_point)
2788                         ptcache_read(pid, cfra1);
2789         }
2790
2791         if (cfra2) {
2792                 if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
2793                         if (!ptcache_read_openvdb_stream(pid, cfra2)) {
2794                                 return 0;
2795                         }
2796                 }
2797                 else if (pid->read_stream) {
2798                         if (!ptcache_read_stream(pid, cfra2))
2799                                 return 0;
2800                 }
2801                 else if (pid->read_point) {
2802                         if (cfra1 && cfra2 && pid->interpolate_point)
2803                                 ptcache_interpolate(pid, cfra, cfra1, cfra2);
2804                         else
2805                                 ptcache_read(pid, cfra2);
2806                 }
2807         }
2808
2809         if (cfra1)
2810                 ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT);
2811         else if (cfra2) {
2812                 ret = PTCACHE_READ_OLD;
2813                 pid->cache->simframe = cfra2;
2814         }
2815
2816         cfrai = (int)cfra;
2817         /* clear invalid cache frames so that better stuff can be simulated */
2818         if (pid->cache->flag & PTCACHE_OUTDATED) {
2819                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
2820         }
2821         else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
2822                 if (cfra <= pid->cache->last_exact)
2823                         pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
2824
2825                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact));
2826         }
2827
2828         return ret;
2829 }
2830 static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
2831 {
2832         PTCacheFile *pf = NULL;
2833         int error = 0;
2834
2835         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
2836
2837         pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
2838
2839         if (pf==NULL) {
2840                 if (G.debug & G_DEBUG)
2841                         printf("Error opening disk cache file for writing\n");
2842                 return 0;
2843         }
2844
2845         pf->data_types = pid->data_types;
2846         pf->totpoint = totpoint;
2847         pf->type = pid->type;
2848         pf->flag = 0;
2849
2850         if (!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)))
2851                 error = 1;
2852
2853         if (!error && pid->write_stream)
2854                 pid->write_stream(pf, pid->calldata);
2855
2856         ptcache_file_close(pf);
2857
2858         if (error && G.debug & G_DEBUG)
2859                 printf("Error writing to disk cache\n");
2860
2861         return error == 0;
2862 }
2863 static int ptcache_write_openvdb_stream(PTCacheID *pid, int cfra)
2864 {
2865 #ifdef WITH_OPENVDB
2866         struct OpenVDBWriter *writer = OpenVDBWriter_create();
2867         char filename[FILE_MAX * 2];
2868
2869         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
2870
2871         ptcache_filename(pid, filename, cfra, 1, 1);
2872         BLI_make_existing_file(filename);
2873
2874         int error = pid->write_openvdb_stream(writer, pid->calldata);
2875
2876         OpenVDBWriter_write(writer, filename);
2877         OpenVDBWriter_free(writer);
2878
2879         return error == 0;
2880 #else
2881         UNUSED_VARS(pid, cfra);
2882         return 0;
2883 #endif
2884 }
2885 static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
2886 {
2887         PointCache *cache = pid->cache;
2888         PTCacheMem *pm=NULL, *pm2=NULL;
2889         int totpoint = pid->totpoint(pid->calldata, cfra);
2890         int i, error = 0;
2891
2892         pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
2893
2894         pm->totpoint = pid->totwrite(pid->calldata, cfra);
2895         pm->data_types = cfra ? pid->data_types : pid->info_types;
2896
2897         ptcache_data_alloc(pm);
2898         BKE_ptcache_mem_pointers_init(pm);
2899
2900         if (overwrite) {
2901                 if (cache->flag & PTCACHE_DISK_CACHE) {
2902                         int fra = cfra-1;
2903
2904                         while (fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra))
2905                                 fra--;
2906
2907                         pm2 = ptcache_disk_frame_to_mem(pid, fra);
2908                 }
2909                 else
2910                         pm2 = cache->mem_cache.last;
2911         }
2912
2913         if (pid->write_point) {
2914                 for (i=0; i<totpoint; i++) {
2915                         int write = pid->write_point(i, pid->calldata, pm->cur, cfra);
2916                         if (write) {
2917                                 BKE_ptcache_mem_pointers_incr(pm);
2918
2919                                 /* newly born particles have to be copied to previous cached frame */
2920                                 if (overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2))
2921                                         pid->write_point(i, pid->calldata, pm2->cur, cfra);
2922                         }
2923                 }
2924         }
2925
2926         if (pid->write_extra_data)
2927                 pid->write_extra_data(pid->calldata, pm, cfra);
2928
2929         pm->frame = cfra;
2930
2931         if (cache->flag & PTCACHE_DISK_CACHE) {
2932                 error += !ptcache_mem_frame_to_disk(pid, pm);
2933
2934                 // if (pm) /* pm is always set */
2935                 {
2936                         ptcache_data_free(pm);
2937                         ptcache_extra_free(pm);
2938                         MEM_freeN(pm);
2939                 }
2940
2941                 if (pm2) {
2942                         error += !ptcache_mem_frame_to_disk(pid, pm2);
2943                         ptcache_data_free(pm2);
2944                         ptcache_extra_free(pm2);
2945                         MEM_freeN(pm2);
2946                 }
2947         }
2948         else {
2949                 BLI_addtail(&cache->mem_cache, pm);
2950         }
2951
2952         return error;
2953 }
2954 static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
2955 {
2956         PointCache *cache = pid->cache;
2957         int ofra = 0, efra = cache->endframe;
2958
2959         /* always start from scratch on the first frame */
2960         if (cfra && cfra == cache->startframe) {
2961                 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
2962                 cache->flag &= ~PTCACHE_REDO_NEEDED;
2963                 return 1;
2964         }
2965
2966         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
2967                 if (cfra==0 && cache->startframe > 0)
2968                         return 1;
2969
2970                                 /* find last cached frame */
2971                 while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
2972                         efra--;
2973
2974                 /* find second last cached frame */
2975                 ofra = efra-1;
2976                 while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
2977                         ofra--;
2978         }
2979         else {
2980                 PTCacheMem *pm = cache->mem_cache.last;
2981                 /* don't write info file in memory */
2982                 if (cfra == 0)
2983                         return 0;
2984
2985                 if (pm == NULL)
2986                         return 1;
2987
2988                 efra = pm->frame;
2989                 ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
2990         }
2991
2992         if (efra >= cache->startframe && cfra > efra) {
2993                 if (ofra >= cache->startframe && efra - ofra < cache->step) {
2994                         /* overwrite previous frame */
2995                         BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
2996                         *overwrite = 1;
2997                 }
2998                 return 1;
2999         }
3000
3001         return 0;
3002 }
3003 /* writes cache to disk or memory */
3004 int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
3005 {
3006         PointCache *cache = pid->cache;
3007         int totpoint = pid->totpoint(pid->calldata, cfra);
3008         int overwrite = 0, error = 0;
3009
3010         if (totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
3011                 return 0;
3012
3013         if (ptcache_write_needed(pid, cfra, &overwrite)==0)
3014                 return 0;
3015
3016         if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->write_openvdb_stream) {
3017                 ptcache_write_openvdb_stream(pid, cfra);
3018         }
3019         else if (pid->write_stream) {
3020                 ptcache_write_stream(pid, cfra, totpoint);
3021         }
3022         else if (pid->write_point) {
3023                 error += ptcache_write(pid, cfra, overwrite);
3024         }
3025
3026         /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
3027         if (cfra - cache->last_exact == 1 || cfra == cache->startframe) {
3028                 cache->last_exact = cfra;
3029                 cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
3030         }
3031         /* Don't mark skipped when writing info file (frame 0) */
3032         else if (cfra)
3033                 cache->flag |= PTCACHE_FRAMES_SKIPPED;
3034
3035         /* Update timeline cache display */
3036         if (cfra && cache->cached_frames)
3037                 cache->cached_frames[cfra-cache->startframe] = 1;
3038
3039         BKE_ptcache_update_info(pid);
3040
3041         return !error;
3042 }
3043 /* youll need to close yourself after!
3044  * mode - PTCACHE_CLEAR_ALL,
3045  */
3046
3047 /* Clears & resets */
3048 void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
3049 {
3050         unsigned int len; /* store the length of the string */
3051         unsigned int sta, end;
3052
3053         /* mode is same as fopen's modes */
3054         DIR *dir;
3055         struct dirent *de;
3056         char path[MAX_PTCACHE_PATH];
3057         char filename[MAX_PTCACHE_FILE];
3058         char path_full[MAX_PTCACHE_FILE];
3059         char ext[MAX_PTCACHE_PATH];
3060
3061         if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED)
3062                 return;
3063
3064         if (pid->cache->flag & PTCACHE_IGNORE_CLEAR)
3065                 return;
3066
3067         sta = pid->cache->startframe;
3068         end = pid->cache->endframe;
3069
3070 #ifndef DURIAN_POINTCACHE_LIB_OK
3071         /* don't allow clearing for linked objects */
3072         if (pid->ob->id.lib)
3073                 return;
3074 #endif
3075
3076         /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
3077
3078         const char *fext = ptcache_file_extension(pid);
3079
3080         /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
3081         switch (mode) {
3082                 case PTCACHE_CLEAR_ALL:
3083                 case PTCACHE_CLEAR_BEFORE:
3084                 case PTCACHE_CLEAR_AFTER:
3085                         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
3086                                 ptcache_path(pid, path);
3087
3088                                 dir = opendir(path);
3089                                 if (dir==NULL)
3090                                         return;
3091
3092                                 len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
3093                                 /* append underscore terminator to ensure we don't match similar names
3094                                  * from objects whose names start with the same prefix
3095                                  */
3096                                 if (len < sizeof(filename) - 2) {
3097                                         BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len);
3098                                         len += 1;
3099                                 }
3100
3101                                 BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
3102
3103                                 while ((de = readdir(dir)) != NULL) {
3104                                         if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
3105                                                 if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
3106                                                         if (mode == PTCACHE_CLEAR_ALL) {
3107                                                                 pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
3108                                                                 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
3109                                                                 BLI_delete(path_full, false, false);
3110                                                         }
3111                                                         else {
3112                                                                 /* read the number of the file */
3113                                                                 const int frame = ptcache_frame_from_filename(de->d_name, ext);
3114
3115                                                                 if (frame != -1) {
3116                                                                         if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
3117                                                                             (mode == PTCACHE_CLEAR_AFTER && frame > cfra))
3118                                                                         {
3119                                                                                 BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
3120                                                                                 BLI_delete(path_full, false, false);
3121                                                                                 if (pid->cache->cached_frames && frame >=sta && frame <= end)
3122                                                                                         pid->cache->cached_frames[frame-sta] = 0;
3123                                                                         }
3124                                                                 }
3125                                                         }
3126                                                 }
3127                                         }
3128                                 }
3129                                 closedir(dir);
3130
3131                                 if (mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames)
3132                                         memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
3133                         }
3134                         else {
3135                                 PTCacheMem *pm= pid->cache->mem_cache.first;
3136                                 PTCacheMem *link= NULL;
3137
3138                                 if (mode == PTCACHE_CLEAR_ALL) {
3139                                         /*we want startframe if the cache starts before zero*/
3140                                         pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
3141                                         for (; pm; pm=pm->next) {
3142                                                 ptcache_data_free(pm);
3143                                                 ptcache_extra_free(pm);
3144                                         }
3145                                         BLI_freelistN(&pid->cache->mem_cache);
3146
3147                                         if (pid->cache->cached_frames)
3148                                                 memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
3149                                 }
3150                                 else {
3151                                         while (pm) {
3152                                                 if ((mode == PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
3153                                                     (mode == PTCACHE_CLEAR_AFTER && pm->frame > cfra))
3154                                                 {
3155                                                         link = pm;
3156                                                         if (pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end)
3157                                                                 pid->cache->cached_frames[pm->frame-sta] = 0;
3158                                                         ptcache_data_free(pm);
3159                                                         ptcache_extra_free(pm);
3160                                                         pm = pm->next;
3161                                                         BLI_freelinkN(&pid->cache->mem_cache, link);
3162                                                 }
3163                                                 else
3164                                                         pm = pm->next;
3165                                         }
3166                                 }
3167                         }
3168                         break;
3169
3170                 case PTCACHE_CLEAR_FRAME:
3171                         if (pid->cache->flag & PTCACHE_DISK_CACHE) {
3172                                 if (BKE_ptcache_id_exist(pid, cfra)) {
3173                                         ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
3174                                         BLI_delete(filename, false, false);
3175                                 }
3176                         }
3177                         else {
3178                                 PTCacheMem *pm = pid->cache->mem_cache.first;
3179
3180                                 for (; pm; pm=pm->next) {
3181     &