Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/pointcache.c')
-rw-r--r--source/blender/blenkernel/intern/pointcache.c672
1 files changed, 499 insertions, 173 deletions
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 9054ecc7c3f..448aaaa7830 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -83,6 +83,10 @@
#include "smoke_API.h"
#endif
+#ifdef WITH_OPENVDB
+#include "openvdb_capi.h"
+#endif
+
#ifdef WITH_LZO
# ifdef WITH_SYSTEM_LZO
# include <lzo/lzo1x.h>
@@ -691,10 +695,10 @@ static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
SmokeDomainSettings *sds = smd->domain;
if (sds->fluid) {
- size_t res = sds->res[0]*sds->res[1]*sds->res[2];
+ const size_t res = sds->res[0] * sds->res[1] * sds->res[2];
+ const unsigned int out_len = (unsigned int)res * sizeof(float);
float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz;
unsigned char *obstacles;
- unsigned int out_len = (unsigned int)res * sizeof(float);
float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp");
int fluid_fields = smoke_get_data_flags(sds);
@@ -733,13 +737,10 @@ static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
MEM_freeN(tmp_array);
if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
- int res = sds->res[0]*sds->res[1]*sds->res[2];
int res_big, res_big_array[3];
- float *dens, *tcu, *tcv, *tcw;
- unsigned int out_len = sizeof(float)*(unsigned int)res;
+ float *tcu, *tcv, *tcw;
unsigned int out_len_big;
unsigned char *tmp_array_big;
-
smoke_turbulence_get_res(sds->wt, res_big_array);
res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
out_len_big = sizeof(float) * (unsigned int)res_big;
@@ -890,6 +891,274 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
return 1;
}
+#ifdef WITH_OPENVDB
+/**
+ * Construct matrices which represent the fluid object, for low and high res:
+ * <pre>
+ * vs 0 0 0
+ * 0 vs 0 0
+ * 0 0 vs 0
+ * px py pz 1
+ * </pre>
+ *
+ * with `vs` = voxel size, and `px, py, pz`,
+ * the min position of the domain's bounding box.
+ */
+static void compute_fluid_matrices(SmokeDomainSettings *sds)
+{
+ float bbox_min[3];
+
+ copy_v3_v3(bbox_min, sds->p0);
+
+ if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+ bbox_min[0] += (sds->cell_size[0] * (float)sds->res_min[0]);
+ bbox_min[1] += (sds->cell_size[1] * (float)sds->res_min[1]);
+ bbox_min[2] += (sds->cell_size[2] * (float)sds->res_min[2]);
+ add_v3_v3(bbox_min, sds->obj_shift_f);
+ }
+
+ /* construct low res matrix */
+ size_to_mat4(sds->fluidmat, sds->cell_size);
+ copy_v3_v3(sds->fluidmat[3], bbox_min);
+
+ /* The smoke simulator stores voxels cell-centered, whilst VDB is node
+ * centered, so we offset the matrix by half a voxel to compensate. */
+ madd_v3_v3fl(sds->fluidmat[3], sds->cell_size, 0.5f);
+
+ mul_m4_m4m4(sds->fluidmat, sds->obmat, sds->fluidmat);
+
+ if (sds->wt) {
+ float voxel_size_high[3];
+ /* construct high res matrix */
+ mul_v3_v3fl(voxel_size_high, sds->cell_size, 1.0f / (float)(sds->amplify + 1));
+ size_to_mat4(sds->fluidmat_wt, voxel_size_high);
+ copy_v3_v3(sds->fluidmat_wt[3], bbox_min);
+
+ /* Same here, add half a voxel to adjust the position of the fluid. */
+ madd_v3_v3fl(sds->fluidmat_wt[3], voxel_size_high, 0.5f);
+
+ mul_m4_m4m4(sds->fluidmat_wt, sds->obmat, sds->fluidmat_wt);
+ }
+}
+
+static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
+{
+ SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
+ SmokeDomainSettings *sds = smd->domain;
+
+ OpenVDBWriter_set_flags(writer, sds->openvdb_comp, (sds->data_depth == 16));
+
+ OpenVDBWriter_add_meta_int(writer, "blender/smoke/active_fields", sds->active_fields);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/resolution", sds->res);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/min_resolution", sds->res_min);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/max_resolution", sds->res_max);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/base_resolution", sds->base_res);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/min_bbox", sds->p0);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/max_bbox", sds->p1);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/dp0", sds->dp0);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/shift", sds->shift);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/obj_shift_f", sds->obj_shift_f);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/active_color", sds->active_color);
+ OpenVDBWriter_add_meta_mat4(writer, "blender/smoke/obmat", sds->obmat);
+
+ int fluid_fields = smoke_get_data_flags(sds);
+
+ struct OpenVDBFloatGrid *clip_grid = NULL;
+
+ compute_fluid_matrices(sds);
+
+ OpenVDBWriter_add_meta_int(writer, "blender/smoke/fluid_fields", fluid_fields);
+
+ if (sds->wt) {
+ struct OpenVDBFloatGrid *wt_density_grid;
+ float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
+
+ smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+
+ wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, NULL);
+ clip_grid = wt_density_grid;
+
+ if (fluid_fields & SM_ACTIVE_FIRE) {
+ OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ }
+
+ if (fluid_fields & SM_ACTIVE_COLORS) {
+ OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, wt_density_grid);
+ }
+
+ OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, wt_density_grid);
+ }
+
+ if (sds->fluid) {
+ struct OpenVDBFloatGrid *density_grid;
+ float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
+ unsigned char *obstacles;
+
+ smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
+ &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
+
+ OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
+ OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
+
+ const char *name = (!sds->wt) ? "density" : "density low";
+ density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, NULL);
+ clip_grid = sds->wt ? clip_grid : density_grid;
+
+ OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, NULL);
+
+ if (fluid_fields & SM_ACTIVE_HEAT) {
+ OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat old", heatold, sds->res, sds->fluidmat, clip_grid);
+ }
+
+ if (fluid_fields & SM_ACTIVE_FIRE) {
+ name = (!sds->wt) ? "flame" : "flame low";
+ OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, density_grid);
+ name = (!sds->wt) ? "fuel" : "fuel low";
+ OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, density_grid);
+ name = (!sds->wt) ? "react" : "react low";
+ OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, density_grid);
+ }
+
+ if (fluid_fields & SM_ACTIVE_COLORS) {
+ name = (!sds->wt) ? "color" : "color low";
+ OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, density_grid);
+ }
+
+ OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, clip_grid);
+ OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, NULL);
+ }
+
+ return 1;
+}
+
+static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
+{
+ SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
+
+ if (!smd) {
+ return 0;
+ }
+
+ SmokeDomainSettings *sds = smd->domain;
+
+ int fluid_fields = smoke_get_data_flags(sds);
+ int active_fields, cache_fields = 0;
+ int cache_res[3];
+ float cache_dx;
+ bool reallocate = false;
+
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/min_resolution", sds->res_min);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/max_resolution", sds->res_max);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/base_resolution", sds->base_res);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/min_bbox", sds->p0);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/max_bbox", sds->p1);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/dp0", sds->dp0);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/shift", sds->shift);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/obj_shift_f", sds->obj_shift_f);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/active_color", sds->active_color);
+ OpenVDBReader_get_meta_mat4(reader, "blender/smoke/obmat", sds->obmat);
+ OpenVDBReader_get_meta_int(reader, "blender/smoke/fluid_fields", &cache_fields);
+ OpenVDBReader_get_meta_int(reader, "blender/smoke/active_fields", &active_fields);
+ OpenVDBReader_get_meta_fl(reader, "blender/smoke/dx", &cache_dx);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/resolution", cache_res);
+
+ /* check if resolution has changed */
+ if (sds->res[0] != cache_res[0] ||
+ sds->res[1] != cache_res[1] ||
+ sds->res[2] != cache_res[2])
+ {
+ if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+ reallocate = true;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ /* check if active fields have changed */
+ if ((fluid_fields != cache_fields) || (active_fields != sds->active_fields)) {
+ reallocate = true;
+ }
+
+ /* reallocate fluid if needed*/
+ if (reallocate) {
+ sds->active_fields = active_fields | cache_fields;
+ smoke_reallocate_fluid(sds, cache_dx, cache_res, 1);
+ sds->dx = cache_dx;
+ copy_v3_v3_int(sds->res, cache_res);
+ sds->total_cells = cache_res[0] * cache_res[1] * cache_res[2];
+
+ if (sds->flags & MOD_SMOKE_HIGHRES) {
+ smoke_reallocate_highres_fluid(sds, cache_dx, cache_res, 1);
+ }
+ }
+
+ if (sds->fluid) {
+ float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
+ unsigned char *obstacles;
+
+ smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
+ &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
+
+ OpenVDBReader_get_meta_fl(reader, "blender/smoke/dt", &dt);
+
+ OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
+
+ const char *name = (!sds->wt) ? "density" : "density low";
+ OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
+
+ if (cache_fields & SM_ACTIVE_HEAT) {
+ OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
+ OpenVDB_import_grid_fl(reader, "heat old", &heatold, sds->res);
+ }
+
+ if (cache_fields & SM_ACTIVE_FIRE) {
+ name = (!sds->wt) ? "flame" : "flame low";
+ OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
+ name = (!sds->wt) ? "fuel" : "fuel low";
+ OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
+ name = (!sds->wt) ? "react" : "react low";
+ OpenVDB_import_grid_fl(reader, name, &react, sds->res);
+ }
+
+ if (cache_fields & SM_ACTIVE_COLORS) {
+ name = (!sds->wt) ? "color" : "color low";
+ OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
+ }
+
+ OpenVDB_import_grid_vec(reader, "velocity", &vx, &vy, &vz, sds->res);
+ OpenVDB_import_grid_ch(reader, "obstacles", &obstacles, sds->res);
+ }
+
+ if (sds->wt) {
+ float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
+
+ smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+
+ OpenVDB_import_grid_fl(reader, "density", &dens, sds->res_wt);
+
+ if (fluid_fields & SM_ACTIVE_FIRE) {
+ OpenVDB_import_grid_fl(reader, "flame", &flame, sds->res_wt);
+ OpenVDB_import_grid_fl(reader, "fuel", &fuel, sds->res_wt);
+ OpenVDB_import_grid_fl(reader, "react", &react, sds->res_wt);
+ }
+
+ if (fluid_fields & SM_ACTIVE_COLORS) {
+ OpenVDB_import_grid_vec(reader, "color", &r, &g, &b, sds->res_wt);
+ }
+
+ OpenVDB_import_grid_vec(reader, "texture coordinates", &tcu, &tcv, &tcw, sds->res);
+ }
+
+ OpenVDBReader_free(reader);
+
+ return 1;
+}
+#endif
+
#else // WITH_SMOKE
static int ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; }
static void ptcache_smoke_error(void *UNUSED(smoke_v), const char *UNUSED(message)) { }
@@ -897,6 +1166,20 @@ static int ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) {
static int ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
#endif // WITH_SMOKE
+#if !defined(WITH_SMOKE) || !defined(WITH_OPENVDB)
+static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
+{
+ UNUSED_VARS(writer, smoke_v);
+ return 0;
+}
+
+static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
+{
+ UNUSED_VARS(reader, smoke_v);
+ return 0;
+}
+#endif
+
static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
{
DynamicPaintSurface *surface = (DynamicPaintSurface*)sd;
@@ -1116,6 +1399,9 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->write_stream = NULL;
pid->read_stream = NULL;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1130,6 +1416,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->default_step = 10;
pid->max_step = 20;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
{
@@ -1157,6 +1444,9 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->write_stream = NULL;
pid->read_stream = NULL;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1188,6 +1478,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->default_step = 10;
pid->max_step = 20;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
{
@@ -1207,6 +1498,9 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->read_point = ptcache_cloth_read;
pid->interpolate_point = ptcache_cloth_interpolate;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_stream = NULL;
pid->read_stream = NULL;
@@ -1222,6 +1516,7 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
{
@@ -1249,6 +1544,9 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo
pid->read_stream = ptcache_smoke_read;
pid->write_stream = ptcache_smoke_write;
+ pid->write_openvdb_stream = ptcache_smoke_openvdb_write;
+ pid->read_openvdb_stream = ptcache_smoke_openvdb_read;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1266,6 +1564,7 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = smd->domain->cache_file_format;
}
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
@@ -1289,6 +1588,9 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu
pid->write_stream = ptcache_dynamicpaint_write;
pid->read_stream = ptcache_dynamicpaint_read;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1303,6 +1605,7 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
@@ -1325,6 +1628,9 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->write_stream = NULL;
pid->read_stream = NULL;
+
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
@@ -1340,6 +1646,7 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
@@ -1432,6 +1739,38 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
/* File handling */
+static const char *ptcache_file_extension(const PTCacheID *pid)
+{
+ switch (pid->file_type) {
+ default:
+ case PTCACHE_FILE_PTCACHE:
+ return PTCACHE_EXT;
+ case PTCACHE_FILE_OPENVDB:
+ return ".vdb";
+ }
+}
+
+/**
+ * Similar to #BLI_path_frame_get, but takes into account the stack-index which is after the frame.
+ */
+static int ptcache_frame_from_filename(const char *filename, const char *ext)
+{
+ const int frame_len = 6;
+ const int ext_len = frame_len + strlen(ext);
+ const int len = strlen(filename);
+
+ /* could crash if trying to copy a string out of this range */
+ if (len > ext_len) {
+ /* using frame_len here gives compile error (vla) */
+ char num[/* frame_len */6 + 1];
+ BLI_strncpy(num, filename + len - ext_len, sizeof(num));
+
+ return atoi(num);
+ }
+
+ return -1;
+}
+
/* Takes an Object ID and returns a unique name
* - id: object id
* - cfra: frame for the cache, can be negative
@@ -1510,18 +1849,19 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p
}
if (do_ext) {
-
if (pid->cache->index < 0)
pid->cache->index = pid->stack_index = BKE_object_insert_ptcache(pid->ob);
+ const char *ext = ptcache_file_extension(pid);
+
if (pid->cache->flag & PTCACHE_EXTERNAL) {
if (pid->cache->index >= 0)
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+ BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
else
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
+ BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d%s", cfra, ext); /* always 6 chars */
}
else {
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+ BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
}
len += 16;
}
@@ -1546,9 +1886,6 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
ptcache_filename(pid, filename, cfra, 1, 1);
if (mode==PTCACHE_FILE_READ) {
- if (!BLI_exists(filename)) {
- return NULL;
- }
fp = BLI_fopen(filename, "rb");
}
else if (mode==PTCACHE_FILE_WRITE) {
@@ -2159,6 +2496,36 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra)
return error == 0;
}
+
+static int ptcache_read_openvdb_stream(PTCacheID *pid, int cfra)
+{
+#ifdef WITH_OPENVDB
+ char filename[FILE_MAX * 2];
+
+ /* save blend file before using disk pointcache */
+ if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0)
+ return 0;
+
+ ptcache_filename(pid, filename, cfra, 1, 1);
+
+ if (!BLI_exists(filename)) {
+ return 0;
+ }
+
+ struct OpenVDBReader *reader = OpenVDBReader_create();
+ OpenVDBReader_open(reader, filename);
+
+ if (!pid->read_openvdb_stream(reader, pid->calldata)) {
+ return 0;
+ }
+
+ return 1;
+#else
+ UNUSED_VARS(pid, cfra);
+ return 0;
+#endif
+}
+
static int ptcache_read(PTCacheID *pid, int cfra)
{
PTCacheMem *pm = NULL;
@@ -2300,8 +2667,12 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra)
return 0;
if (cfra1) {
-
- if (pid->read_stream) {
+ if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
+ if (!ptcache_read_openvdb_stream(pid, cfra1)) {
+ return 0;
+ }
+ }
+ else if (pid->read_stream) {
if (!ptcache_read_stream(pid, cfra1))
return 0;
}
@@ -2310,8 +2681,12 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra)
}
if (cfra2) {
-
- if (pid->read_stream) {
+ if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
+ if (!ptcache_read_openvdb_stream(pid, cfra2)) {
+ return 0;
+ }
+ }
+ else if (pid->read_stream) {
if (!ptcache_read_stream(pid, cfra2))
return 0;
}
@@ -2377,6 +2752,28 @@ static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
return error == 0;
}
+static int ptcache_write_openvdb_stream(PTCacheID *pid, int cfra)
+{
+#ifdef WITH_OPENVDB
+ struct OpenVDBWriter *writer = OpenVDBWriter_create();
+ char filename[FILE_MAX * 2];
+
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
+
+ ptcache_filename(pid, filename, cfra, 1, 1);
+ BLI_make_existing_file(filename);
+
+ int error = pid->write_openvdb_stream(writer, pid->calldata);
+
+ OpenVDBWriter_write(writer, filename);
+ OpenVDBWriter_free(writer);
+
+ return error == 0;
+#else
+ UNUSED_VARS(pid, cfra);
+ return 0;
+#endif
+}
static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
{
PointCache *cache = pid->cache;
@@ -2508,7 +2905,10 @@ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
if (ptcache_write_needed(pid, cfra, &overwrite)==0)
return 0;
- if (pid->write_stream) {
+ if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->write_openvdb_stream) {
+ ptcache_write_openvdb_stream(pid, cfra);
+ }
+ else if (pid->write_stream) {
ptcache_write_stream(pid, cfra, totpoint);
}
else if (pid->write_point) {
@@ -2566,7 +2966,9 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
#endif
/*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
-
+
+ const char *fext = ptcache_file_extension(pid);
+
/* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
switch (mode) {
case PTCACHE_CLEAR_ALL:
@@ -2588,7 +2990,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
len += 1;
}
- BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
+ BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
@@ -2600,13 +3002,9 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
}
else {
/* read the number of the file */
- unsigned int frame, len2 = (int)strlen(de->d_name);
- char num[7];
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
-
+ if (frame != -1) {
if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
(mode == PTCACHE_CLEAR_AFTER && frame > cfra))
{
@@ -2794,21 +3192,18 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
if (dir==NULL)
return;
- BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
+ const char *fext = ptcache_file_extension(pid);
+
+ BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
- unsigned int frame, len2 = (int)strlen(de->d_name);
- char num[7];
-
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
-
- if (frame >= sta && frame <= end)
- cache->cached_frames[frame-sta] = 1;
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
+
+ if ((frame != -1) && (frame >= sta && frame <= end)) {
+ cache->cached_frames[frame-sta] = 1;
}
}
}
@@ -3113,34 +3508,17 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
{
PTCacheBaker baker;
- baker.bake=0;
- baker.break_data=NULL;
- baker.break_test=NULL;
- baker.pid=NULL;
- baker.progressbar=NULL;
- baker.progressend=NULL;
- baker.progresscontext=NULL;
- baker.render=0;
+ memset(&baker, 0, sizeof(baker));
+ baker.main = bmain;
+ baker.scene = scene;
+ baker.bake = 0;
+ baker.render = 0;
baker.anim_init = 0;
- baker.main=bmain;
- baker.scene=scene;
- baker.quick_step=scene->physics_settings.quick_cache_step;
+ baker.quick_step = scene->physics_settings.quick_cache_step;
BKE_ptcache_bake(&baker);
}
-/* Simulation thread, no need for interlocks as data written in both threads
- * are only unitary integers (I/O assumed to be atomic for them) */
-typedef struct {
- int break_operation;
- int thread_ended;
- int endframe;
- int step;
- int *cfra_ptr;
- Main *main;
- Scene *scene;
-} ptcache_bake_data;
-
static void ptcache_dt_to_str(char *str, double dtime)
{
if (dtime > 60.0) {
@@ -3153,52 +3531,6 @@ static void ptcache_dt_to_str(char *str, double dtime)
sprintf(str, "%is", ((int)dtime) % 60);
}
-static void *ptcache_bake_thread(void *ptr)
-{
- bool use_timer = false;
- int sfra, efra;
- double stime, ptime, ctime, fetd;
- char run[32], cur[32], etd[32];
-
- ptcache_bake_data *data = (ptcache_bake_data*)ptr;
-
- stime = ptime = PIL_check_seconds_timer();
- sfra = *data->cfra_ptr;
- efra = data->endframe;
-
- for (; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) {
- BKE_scene_update_for_newframe(G.main->eval_ctx, data->main, data->scene, data->scene->lay);
- if (G.background) {
- printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe);
- }
- else {
- ctime = PIL_check_seconds_timer();
-
- fetd = (ctime-ptime)*(efra-*data->cfra_ptr)/data->step;
-
- if (use_timer || fetd > 60.0) {
- use_timer = true;
-
- ptcache_dt_to_str(cur, ctime-ptime);
- ptcache_dt_to_str(run, ctime-stime);
- ptcache_dt_to_str(etd, fetd);
-
- printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r", run, *data->cfra_ptr-sfra+1, efra-sfra+1, ctime-ptime, etd);
- }
- ptime = ctime;
- }
- }
-
- if (use_timer) {
- /* start with newline because of \r above */
- ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime);
- printf("\nBake %s %s (%i frames simulated).\n", (data->break_operation ? "canceled after" : "finished in"), run, *data->cfra_ptr-sfra);
- }
-
- data->thread_ended = true;
- return NULL;
-}
-
/* if bake is not given run simulations to current frame */
void BKE_ptcache_bake(PTCacheBaker *baker)
{
@@ -3207,27 +3539,18 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
Scene *sce_iter; /* SETLOOPER macro only */
Base *base;
ListBase pidlist;
- PTCacheID *pid = baker->pid;
+ PTCacheID *pid = &baker->pid;
PointCache *cache = NULL;
float frameleno = scene->r.framelen;
int cfrao = CFRA;
- int startframe = MAXFRAME;
+ int startframe = MAXFRAME, endframe = baker->anim_init ? scene->r.sfra : CFRA;
int bake = baker->bake;
int render = baker->render;
- ListBase threads;
- ptcache_bake_data thread_data;
- int progress, old_progress;
- thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA;
- thread_data.step = baker->quick_step;
- thread_data.cfra_ptr = &CFRA;
- thread_data.scene = baker->scene;
- thread_data.main = baker->main;
-
G.is_break = false;
/* set caches to baking mode and figure out start frame */
- if (pid) {
+ if (pid->ob) {
/* cache/bake a single object */
cache = pid->cache;
if ((cache->flag & PTCACHE_BAKED)==0) {
@@ -3264,11 +3587,11 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
startframe = MAX2(cache->last_exact, cache->startframe);
if (bake) {
- thread_data.endframe = cache->endframe;
+ endframe = cache->endframe;
cache->flag |= PTCACHE_BAKING;
}
else {
- thread_data.endframe = MIN2(thread_data.endframe, cache->endframe);
+ endframe = MIN2(endframe, cache->endframe);
}
cache->flag &= ~PTCACHE_BAKED;
@@ -3303,7 +3626,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
cache->flag |= PTCACHE_BAKING;
if (bake)
- thread_data.endframe = MAX2(thread_data.endframe, cache->endframe);
+ endframe = MAX2(endframe, cache->endframe);
}
cache->flag &= ~PTCACHE_BAKED;
@@ -3316,46 +3639,60 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
CFRA = startframe;
scene->r.framelen = 1.0;
- thread_data.break_operation = false;
- thread_data.thread_ended = false;
- old_progress = -1;
- WM_cursor_wait(1);
-
- if (G.background) {
- ptcache_bake_thread((void*)&thread_data);
- }
- else {
- BLI_init_threads(&threads, ptcache_bake_thread, 1);
- BLI_insert_thread(&threads, (void*)&thread_data);
+ /* bake */
- while (thread_data.thread_ended == false) {
+ bool use_timer = false;
+ double stime, ptime, ctime, fetd;
+ char run[32], cur[32], etd[32];
+ int cancel = 0;
- if (bake)
- progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe));
- else
- progress = CFRA;
+ stime = ptime = PIL_check_seconds_timer();
- /* NOTE: baking should not redraw whole ui as this slows things down */
- if ((baker->progressbar) && (progress != old_progress)) {
- baker->progressbar(baker->progresscontext, progress);
- old_progress = progress;
- }
+ for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) {
+ BKE_scene_update_for_newframe(G.main->eval_ctx, bmain, scene, scene->lay);
+
+ if (baker->update_progress) {
+ float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe));
+ baker->update_progress(baker->bake_job, progress, &cancel);
+ }
+
+ if (G.background) {
+ printf("bake: frame %d :: %d\n", CFRA, endframe);
+ }
+ else {
+ ctime = PIL_check_seconds_timer();
+
+ fetd = (ctime - ptime) * (endframe - CFRA) / baker->quick_step;
- /* Delay to lessen CPU load from UI thread */
- PIL_sleep_ms(200);
+ if (use_timer || fetd > 60.0) {
+ use_timer = true;
+
+ ptcache_dt_to_str(cur, ctime - ptime);
+ ptcache_dt_to_str(run, ctime - stime);
+ ptcache_dt_to_str(etd, fetd);
- /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
- if (blender_test_break() && !thread_data.break_operation) {
- thread_data.break_operation = true;
- if (baker->progressend)
- baker->progressend(baker->progresscontext);
- WM_cursor_wait(1);
+ printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r",
+ run, CFRA - startframe + 1, endframe - startframe + 1, ctime - ptime, etd);
}
+
+ ptime = ctime;
+ }
+
+ /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
+ if ((cancel || G.is_break)) {
+ break;
}
- BLI_end_threads(&threads);
+ CFRA += 1;
}
+
+ if (use_timer) {
+ /* start with newline because of \r above */
+ ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime);
+ printf("\nBake %s %s (%i frames simulated).\n", (cancel ? "canceled after" : "finished in"), run, CFRA - startframe);
+ }
+
/* clear baking flag */
if (pid) {
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
@@ -3378,7 +3715,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
cache = pid->cache;
- if (thread_data.step > 1)
+ if (baker->quick_step > 1)
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
else
cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
@@ -3402,13 +3739,6 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
}
- if (thread_data.break_operation)
- WM_cursor_wait(0);
- else if (baker->progressend)
- baker->progressend(baker->progresscontext);
-
- WM_cursor_wait(0);
-
/* TODO: call redraw all windows somehow */
}
/* Helpers */
@@ -3529,7 +3859,9 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
return;
}
- BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
+ const char *fext = ptcache_file_extension(pid);
+
+ BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
/* put new name into cache */
BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name));
@@ -3538,13 +3870,9 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
if (STREQLEN(old_filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
- int frame, len2 = (int)strlen(de->d_name);
- char num[7];
-
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
+ if (frame != -1) {
BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name);
ptcache_filename(pid, new_path_full, frame, 1, 1);
BLI_rename(old_path_full, new_path_full);
@@ -3584,22 +3912,20 @@ void BKE_ptcache_load_external(PTCacheID *pid)
if (dir==NULL)
return;
+ const char *fext = ptcache_file_extension(pid);
+
if (cache->index >= 0)
- BLI_snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
+ BLI_snprintf(ext, sizeof(ext), "_%02d%s", cache->index, fext);
else
- BLI_strncpy(ext, PTCACHE_EXT, sizeof(ext));
+ BLI_strncpy(ext, fext, sizeof(ext));
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
- int frame, len2 = (int)strlen(de->d_name);
- char num[7];
-
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
+ if (frame != -1) {
if (frame) {
start = MIN2(start, frame);
end = MAX2(end, frame);