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