diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h index 7825ad14d7d..d78aa6732b1 100644 --- a/intern/mantaflow/extern/manta_fluid_API.h +++ b/intern/mantaflow/extern/manta_fluid_API.h @@ -41,23 +41,23 @@ int manta_write_config(struct MANTA *fluid, struct FluidModifierData *mmd, int f int manta_write_data(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_write_noise(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_read_config(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); -int manta_read_data(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); -int manta_read_noise(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); +int manta_read_data(struct MANTA *fluid, + struct FluidModifierData *mmd, + int framenr, + bool resumable); +int manta_read_noise(struct MANTA *fluid, + struct FluidModifierData *mmd, + int framenr, + bool resumable); int manta_read_mesh(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); -int manta_read_particles(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); +int manta_read_particles(struct MANTA *fluid, + struct FluidModifierData *mmd, + int framenr, + bool resumable); int manta_read_guiding(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr, bool sourceDomain); -int manta_update_liquid_structures(struct MANTA *fluid, - struct FluidModifierData *mmd, - int framenr); -int manta_update_mesh_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); -int manta_update_particle_structures(struct MANTA *fluid, - struct FluidModifierData *mmd, - int framenr); -int manta_update_smoke_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); -int manta_update_noise_structures(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_bake_data(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_bake_noise(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); int manta_bake_mesh(struct MANTA *fluid, struct FluidModifierData *mmd, int framenr); diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index e760cef8641..e81b2b2e268 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -301,9 +301,8 @@ void MANTA::initDomain(FluidModifierData *mmd) string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper + fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise + fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding + - fluid_file_import + fluid_file_export + fluid_save_data + fluid_load_data + - fluid_pre_step + fluid_post_step + fluid_adapt_time_step + - fluid_time_stepping; + fluid_file_import + fluid_file_export + fluid_pre_step + fluid_post_step + + fluid_adapt_time_step + fluid_time_stepping; string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -674,7 +673,7 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) if (!mmd) { if (with_debug) - cout << "No modifier data given in RNA map setup - returning early" << endl; + cout << "Fluid: No modifier data given in RNA map setup - returning early" << endl; return; } @@ -730,6 +729,20 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) float viscosity = mds->viscosity_base * pow(10.0f, -mds->viscosity_exponent); float domainSize = MAX3(mds->global_size[0], mds->global_size[1], mds->global_size[2]); + string vdbCompressionMethod = "Compression_None"; + if (mds->openvdb_compression == VDB_COMPRESSION_NONE) + vdbCompressionMethod = "Compression_None"; + else if (mds->openvdb_compression == VDB_COMPRESSION_ZIP) + vdbCompressionMethod = "Compression_Zip"; + else if (mds->openvdb_compression == VDB_COMPRESSION_BLOSC) + vdbCompressionMethod = "Compression_Blosc"; + + string vdbPrecisionHalf = "True"; + if (mds->openvdb_data_depth == VDB_PRECISION_HALF_FLOAT) + vdbPrecisionHalf = "True"; + else if (mds->openvdb_data_depth == VDB_PRECISION_FULL_FLOAT) + vdbPrecisionHalf = "False"; + mRNAMap["USING_SMOKE"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_GAS); mRNAMap["USING_LIQUID"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_LIQUID); mRNAMap["USING_COLORS"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS); @@ -743,7 +756,7 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) mRNAMap["USING_LOG_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG); mRNAMap["USING_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE); mRNAMap["DO_OPEN"] = getBooleanString(mds->border_collisions == 0); - mRNAMap["CACHE_RESUMABLE"] = getBooleanString(mds->cache_type != FLUID_DOMAIN_CACHE_FINAL); + mRNAMap["CACHE_RESUMABLE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE); mRNAMap["USING_ADAPTIVETIME"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME); mRNAMap["USING_SPEEDVECTORS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS); mRNAMap["USING_FRACTIONS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_FRACTIONS); @@ -850,6 +863,9 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) mRNAMap["LIQUID_SURFACE_TENSION"] = to_string(mds->surface_tension); mRNAMap["FLUID_VISCOSITY"] = to_string(viscosity); mRNAMap["FLUID_DOMAIN_SIZE"] = to_string(domainSize); + mRNAMap["FLUID_DOMAIN_SIZE_X"] = to_string(mds->global_size[0]); + mRNAMap["FLUID_DOMAIN_SIZE_Y"] = to_string(mds->global_size[1]); + mRNAMap["FLUID_DOMAIN_SIZE_Z"] = to_string(mds->global_size[2]); mRNAMap["SNDPARTICLE_TYPES"] = particleTypesStr; mRNAMap["GUIDING_ALPHA"] = to_string(mds->guide_alpha); mRNAMap["GUIDING_BETA"] = to_string(mds->guide_beta); @@ -858,6 +874,8 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) mRNAMap["GRAVITY_Y"] = to_string(mds->gravity[1]); mRNAMap["GRAVITY_Z"] = to_string(mds->gravity[2]); mRNAMap["CACHE_DIR"] = cacheDirectory; + mRNAMap["COMPRESSION_OPENVDB"] = vdbCompressionMethod; + mRNAMap["PRECISION_OPENVDB"] = vdbPrecisionHalf; /* Fluid object names. */ mRNAMap["NAME_FLAGS"] = FLUID_NAME_FLAGS; @@ -900,6 +918,8 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) mRNAMap["NAME_DENSITYIN"] = FLUID_NAME_DENSITYIN; mRNAMap["NAME_HEAT"] = FLUID_NAME_HEAT; mRNAMap["NAME_HEATIN"] = FLUID_NAME_HEATIN; + mRNAMap["NAME_TEMPERATURE"] = FLUID_NAME_TEMPERATURE; + mRNAMap["NAME_TEMPERATUREIN"] = FLUID_NAME_TEMPERATUREIN; mRNAMap["NAME_COLORR"] = FLUID_NAME_COLORR; mRNAMap["NAME_COLORG"] = FLUID_NAME_COLORG; mRNAMap["NAME_COLORB"] = FLUID_NAME_COLORB; @@ -921,6 +941,8 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) mRNAMap["NAME_MAPWEIGHTS"] = FLUID_NAME_MAPWEIGHTS; mRNAMap["NAME_PP"] = FLUID_NAME_PP; mRNAMap["NAME_PVEL"] = FLUID_NAME_PVEL; + mRNAMap["NAME_PARTS"] = FLUID_NAME_PARTS; + mRNAMap["NAME_PARTSVELOCITY"] = FLUID_NAME_PARTSVELOCITY; mRNAMap["NAME_PINDEX"] = FLUID_NAME_PINDEX; mRNAMap["NAME_GPI"] = FLUID_NAME_GPI; mRNAMap["NAME_CURVATURE"] = FLUID_NAME_CURVATURE; @@ -967,6 +989,10 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) mRNAMap["NAME_PVEL_PARTICLES"] = FLUID_NAME_PVEL_PARTICLES; mRNAMap["NAME_PFORCE_PARTICLES"] = FLUID_NAME_PFORCE_PARTICLES; mRNAMap["NAME_PLIFE_PARTICLES"] = FLUID_NAME_PLIFE_PARTICLES; + mRNAMap["NAME_PARTS_PARTICLES"] = FLUID_NAME_PARTS_PARTICLES; + mRNAMap["NAME_PARTSVEL_PARTICLES"] = FLUID_NAME_PARTSVEL_PARTICLES; + mRNAMap["NAME_PARTSFORCE_PARTICLES"] = FLUID_NAME_PARTSFORCE_PARTICLES; + mRNAMap["NAME_PARTSLIFE_PARTICLES"] = FLUID_NAME_PARTSLIFE_PARTICLES; mRNAMap["NAME_VELOCITY_PARTICLES"] = FLUID_NAME_VELOCITY_PARTICLES; mRNAMap["NAME_FLAGS_PARTICLES"] = FLUID_NAME_FLAGS_PARTICLES; mRNAMap["NAME_PHI_PARTICLES"] = FLUID_NAME_PHI_PARTICLES; @@ -1000,9 +1026,6 @@ void MANTA::initializeRNAMap(FluidModifierData *mmd) string MANTA::getRealValue(const string &varName) { - if (with_debug) - cout << "MANTA::getRealValue()" << endl; - unordered_map::iterator it; it = mRNAMap.find(varName); @@ -1011,9 +1034,6 @@ string MANTA::getRealValue(const string &varName) << endl; return ""; } - if (with_debug) { - cout << "Found variable " << varName << " with value " << it->second << endl; - } return it->second; } @@ -1062,409 +1082,6 @@ string MANTA::parseScript(const string &setup_string, FluidModifierData *mmd) return res.str(); } -bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr) -{ - if (MANTA::with_debug) - cout << "MANTA::updateFlipStructures()" << endl; - - FluidDomainSettings *mds = mmd->domain; - mFlipFromFile = false; - - if (!mUsingLiquid) - return false; - if (BLI_path_is_rel(mds->cache_directory)) - return false; - - int result = 0; - int expected = 0; /* Expected number of read successes for this frame. */ - - /* Ensure empty data structures at start. */ - if (!mFlipParticleData || !mFlipParticleVelocity) - return false; - - mFlipParticleData->clear(); - mFlipParticleVelocity->clear(); - - string pformat = getCacheFileEnding(mds->cache_particle_format); - string file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_PP, pformat, framenr); - - expected += 1; - if (BLI_exists(file.c_str())) { - result += updateParticlesFromFile(file, false, false); - assert(result == expected); - } - - file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_PVEL, pformat, framenr); - expected += 1; - if (BLI_exists(file.c_str())) { - result += updateParticlesFromFile(file, false, true); - assert(result == expected); - } - - return mFlipFromFile = (result == expected); -} - -bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr) -{ - if (MANTA::with_debug) - cout << "MANTA::updateMeshStructures()" << endl; - - FluidDomainSettings *mds = mmd->domain; - mMeshFromFile = false; - - if (!mUsingMesh) - return false; - if (BLI_path_is_rel(mds->cache_directory)) - return false; - - int result = 0; - int expected = 0; /* Expected number of read successes for this frame. */ - - /* Ensure empty data structures at start. */ - if (!mMeshNodes || !mMeshTriangles) - return false; - - mMeshNodes->clear(); - mMeshTriangles->clear(); - - if (mMeshVelocities) - mMeshVelocities->clear(); - - string mformat = getCacheFileEnding(mds->cache_mesh_format); - string dformat = getCacheFileEnding(mds->cache_data_format); - string file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_LMESH, mformat, framenr); - - expected += 1; - if (BLI_exists(file.c_str())) { - result += updateMeshFromFile(file); - assert(result == expected); - } - - if (mUsingMVel) { - file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_VELOCITYVEC_MESH, dformat, framenr); - expected += 1; - if (BLI_exists(file.c_str())) { - result += updateMeshFromFile(file); - assert(result == expected); - } - } - - return mMeshFromFile = (result == expected); -} - -bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) -{ - if (MANTA::with_debug) - cout << "MANTA::updateParticleStructures()" << endl; - - FluidDomainSettings *mds = mmd->domain; - mParticlesFromFile = false; - - if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) - return false; - if (BLI_path_is_rel(mds->cache_directory)) - return false; - - int result = 0; - int expected = 0; /* Expected number of read successes for this frame. */ - - /* Ensure empty data structures at start. */ - if (!mSndParticleData || !mSndParticleVelocity || !mSndParticleLife) - return false; - - mSndParticleData->clear(); - mSndParticleVelocity->clear(); - mSndParticleLife->clear(); - - string pformat = getCacheFileEnding(mds->cache_particle_format); - string file = getFile( - mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, pformat, framenr); - - expected += 1; - if (BLI_exists(file.c_str())) { - result += updateParticlesFromFile(file, true, false); - assert(result == expected); - } - - file = getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PVEL_PARTICLES, pformat, framenr); - expected += 1; - if (BLI_exists(file.c_str())) { - result += updateParticlesFromFile(file, true, true); - assert(result == expected); - } - - file = getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PLIFE_PARTICLES, pformat, framenr); - expected += 1; - if (BLI_exists(file.c_str())) { - result += updateParticlesFromFile(file, true, false); - assert(result == expected); - } - - return mParticlesFromFile = (result == expected); -} - -static void assertGridItems(vector gList) -{ - vector::iterator gIter = gList.begin(); - int *resPrev = (*gIter).res; - - for (vector::iterator it = gList.begin(); it != gList.end(); ++it) { - MANTA::GridItem item = *it; - assert( - ELEM(item.type, FLUID_DOMAIN_GRID_FLOAT, FLUID_DOMAIN_GRID_INT, FLUID_DOMAIN_GRID_VEC3F)); - assert(item.pointer[0]); - if (item.type == FLUID_DOMAIN_GRID_VEC3F) { - assert(item.pointer[1] && item.pointer[2]); - } - assert(item.res[0] == resPrev[0] && item.res[1] == resPrev[1] && item.res[2] == resPrev[2]); - assert((item.name).compare("") != 0); - } - - UNUSED_VARS(resPrev); -} - -bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr) -{ - if (MANTA::with_debug) - cout << "MANTA::updateGridStructures()" << endl; - - FluidDomainSettings *mds = mmd->domain; - mSmokeFromFile = false; - - if (!mUsingSmoke) - return false; - if (BLI_path_is_rel(mds->cache_directory)) - return false; - - int result = 0; - string dformat = getCacheFileEnding(mds->cache_data_format); - - vector filesData; - vector gridsData; - - int res[] = {mResX, mResY, mResZ}; - - /* Put grid pointers into pointer lists, some grids have more than 1 pointer. */ - void *aDensity[] = {mDensity}; - void *aShadow[] = {mShadow}; - void *aVelocities[] = {mVelocityX, mVelocityY, mVelocityZ}; - void *aHeat[] = {mHeat}; - void *aColorR[] = {mColorR}; - void *aColorG[] = {mColorG}; - void *aColorB[] = {mColorB}; - void *aFlame[] = {mFlame}; - void *aFuel[] = {mFuel}; - void *aReact[] = {mReact}; - - /* File names for grids. */ - string fDensity = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_DENSITY, dformat, framenr); - string fShadow = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_SHADOW, dformat, framenr); - string fVel = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_VELOCITY, dformat, framenr); - string fHeat = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_HEAT, dformat, framenr); - string fColorR = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_COLORR, dformat, framenr); - string fColorG = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_COLORG, dformat, framenr); - string fColorB = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_COLORB, dformat, framenr); - string fFlame = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_FLAME, dformat, framenr); - string fFuel = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_FUEL, dformat, framenr); - string fReact = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_REACT, dformat, framenr); - string fFluid = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_DATA, dformat, framenr); - - /* Prepare grid info containers. */ - GridItem gDensity = {aDensity, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_DENSITY}; - GridItem gShadow = {aShadow, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_SHADOW}; - GridItem gVel = {aVelocities, FLUID_DOMAIN_GRID_VEC3F, res, FLUID_NAME_VELOCITY}; - GridItem gHeat = {aHeat, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_HEAT}; - GridItem gColorR = {aColorR, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_COLORR}; - GridItem gColorG = {aColorG, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_COLORG}; - GridItem gColorB = {aColorB, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_COLORB}; - GridItem gFlame = {aFlame, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_FLAME}; - GridItem gFuel = {aFuel, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_FUEL}; - GridItem gReact = {aReact, FLUID_DOMAIN_GRID_FLOAT, res, FLUID_NAME_REACT}; - - /* TODO (sebbas): For now, only allow single file mode. Combined grid file export is todo. */ - const int fileMode = FLUID_DOMAIN_CACHE_FILES_SINGLE; - if (fileMode == FLUID_DOMAIN_CACHE_FILES_SINGLE) { - - filesData.push_back({fDensity, {gDensity}}); - filesData.push_back({fShadow, {gShadow}}); - filesData.push_back({fVel, {gVel}}); - if (mUsingHeat) { - filesData.push_back({fHeat, {gHeat}}); - } - if (mUsingColors) { - filesData.push_back({fColorR, {gColorR}}); - filesData.push_back({fColorG, {gColorG}}); - filesData.push_back({fColorB, {gColorB}}); - } - if (mUsingFire) { - filesData.push_back({fFlame, {gFlame}}); - filesData.push_back({fFuel, {gFuel}}); - filesData.push_back({fReact, {gReact}}); - } - } - else if (fileMode == FLUID_DOMAIN_CACHE_FILES_COMBINED) { - - gridsData.push_back(gDensity); - gridsData.push_back(gShadow); - gridsData.push_back(gVel); - if (mUsingHeat) { - gridsData.push_back(gHeat); - } - if (mUsingColors) { - gridsData.push_back(gColorR); - gridsData.push_back(gColorG); - gridsData.push_back(gColorB); - } - if (mUsingFire) { - gridsData.push_back(gFlame); - gridsData.push_back(gFuel); - gridsData.push_back(gReact); - } - - if (with_debug) { - assertGridItems(gridsData); - } - filesData.push_back({fFluid, gridsData}); - } - - /* Update files from data directory. */ - for (vector::iterator it = filesData.begin(); it != filesData.end(); ++it) { - FileItem item = *it; - if (BLI_exists(item.filename.c_str())) { - result += updateGridsFromFile(item.filename, item.grids); - assert(result); - } - } - - return mSmokeFromFile = result; -} - -bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr) -{ - if (MANTA::with_debug) - cout << "MANTA::updateNoiseStructures()" << endl; - - FluidDomainSettings *mds = mmd->domain; - mNoiseFromFile = false; - - if (!mUsingSmoke || !mUsingNoise) - return false; - if (BLI_path_is_rel(mds->cache_directory)) - return false; - - int result = 0; - string dformat = getCacheFileEnding(mds->cache_data_format); - string nformat = getCacheFileEnding(mds->cache_noise_format); - - vector filesData, filesNoise; - vector gridsData, gridsNoise; - - int resData[] = {mResX, mResY, mResZ}; - int resNoise[] = {mResXNoise, mResYNoise, mResZNoise}; - - /* Put grid pointers into pointer lists, some grids have more than 1 pointer. */ - void *aShadow[] = {mShadow}; - void *aVelocities[] = {mVelocityX, mVelocityY, mVelocityZ}; - void *aDensity[] = {mDensityHigh}; - void *aColorR[] = {mColorRHigh}; - void *aColorG[] = {mColorGHigh}; - void *aColorB[] = {mColorBHigh}; - void *aFlame[] = {mFlameHigh}; - void *aFuel[] = {mFuelHigh}; - void *aReact[] = {mReactHigh}; - - /* File names for grids. */ - string fShadow = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_SHADOW, dformat, framenr); - string fVel = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_VELOCITY, dformat, framenr); - string fFluid = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DATA, dformat, framenr); - - string fDensity = getFile( - mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, nformat, framenr); - string fColorR = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_COLORR_NOISE, nformat, framenr); - string fColorG = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_COLORG_NOISE, nformat, framenr); - string fColorB = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_COLORB_NOISE, nformat, framenr); - string fFlame = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_FLAME_NOISE, nformat, framenr); - string fFuel = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_FUEL_NOISE, nformat, framenr); - string fReact = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_REACT_NOISE, nformat, framenr); - string fNoise = getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_NOISE, nformat, framenr); - - /* Prepare grid info containers. */ - GridItem gShadow = {aShadow, FLUID_DOMAIN_GRID_FLOAT, resData, FLUID_NAME_SHADOW}; - GridItem gVel = {aVelocities, FLUID_DOMAIN_GRID_VEC3F, resData, FLUID_NAME_VELOCITY}; - - GridItem gDensity = {aDensity, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_NAME_DENSITY_NOISE}; - GridItem gColorR = {aColorR, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_NAME_COLORR_NOISE}; - GridItem gColorG = {aColorG, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_NAME_COLORG_NOISE}; - GridItem gColorB = {aColorB, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_NAME_COLORB_NOISE}; - GridItem gFlame = {aFlame, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_NAME_FLAME_NOISE}; - GridItem gFuel = {aFuel, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_NAME_FUEL_NOISE}; - GridItem gReact = {aReact, FLUID_DOMAIN_GRID_FLOAT, resNoise, FLUID_NAME_REACT_NOISE}; - - /* TODO (sebbas): For now, only allow single file mode. Combined grid file export is todo. */ - const int fileMode = FLUID_DOMAIN_CACHE_FILES_SINGLE; - if (fileMode == FLUID_DOMAIN_CACHE_FILES_SINGLE) { - - filesData.push_back({fShadow, {gShadow}}); - filesData.push_back({fVel, {gVel}}); - - filesNoise.push_back({fDensity, {gDensity}}); - if (mUsingColors) { - filesNoise.push_back({fColorR, {gColorR}}); - filesNoise.push_back({fColorG, {gColorG}}); - filesNoise.push_back({fColorB, {gColorB}}); - } - if (mUsingFire) { - filesNoise.push_back({fFlame, {gFlame}}); - filesNoise.push_back({fFuel, {gFuel}}); - filesNoise.push_back({fReact, {gReact}}); - } - } - else if (fileMode == FLUID_DOMAIN_CACHE_FILES_COMBINED) { - - gridsData.push_back(gShadow); - gridsData.push_back(gVel); - - gridsNoise.push_back(gDensity); - if (mUsingColors) { - gridsNoise.push_back(gColorR); - gridsNoise.push_back(gColorG); - gridsNoise.push_back(gColorB); - } - if (mUsingFire) { - gridsNoise.push_back(gFlame); - gridsNoise.push_back(gFuel); - gridsNoise.push_back(gReact); - } - - if (with_debug) { - assertGridItems(gridsData); - assertGridItems(gridsNoise); - } - filesData.push_back({fFluid, gridsData}); - filesNoise.push_back({fNoise, gridsNoise}); - } - - /* Update files from data directory. */ - for (vector::iterator it = filesData.begin(); it != filesData.end(); ++it) { - FileItem item = *it; - if (BLI_exists(item.filename.c_str())) { - result += updateGridsFromFile(item.filename, item.grids); - assert(result); - } - } - - /* Update files from noise directory. */ - for (vector::iterator it = filesNoise.begin(); it != filesNoise.end(); ++it) { - FileItem item = *it; - if (BLI_exists(item.filename.c_str())) { - result += updateGridsFromFile(item.filename, item.grids); - assert(result); - } - } - - return mNoiseFromFile = result; -} - /* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */ static string escapeSlashes(string const &s) { @@ -1514,6 +1131,7 @@ bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr) gzwrite(gzf, &mds->res_max, 3 * sizeof(int)); gzwrite(gzf, &mds->active_color, 3 * sizeof(float)); gzwrite(gzf, &mds->time_total, sizeof(int)); + gzwrite(gzf, &FLUID_CACHE_VERSION, 4 * sizeof(char)); return (gzclose(gzf) == Z_OK); } @@ -1528,27 +1146,19 @@ bool MANTA::writeData(FluidModifierData *mmd, int framenr) FluidDomainSettings *mds = mmd->domain; string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); - string dformat = getCacheFileEnding(mds->cache_data_format); - string pformat = getCacheFileEnding(mds->cache_particle_format); - - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; - - ss.str(""); - ss << "fluid_save_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << dformat << "', " << resumable_cache << ")"; - pythonCommands.push_back(ss.str()); + string volume_format = getCacheFileEnding(mds->cache_data_format); + string resumable_cache = !(mds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True"; if (mUsingSmoke) { ss.str(""); ss << "smoke_save_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << dformat << "', " << resumable_cache << ")"; + << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); } if (mUsingLiquid) { ss.str(""); ss << "liquid_save_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << dformat << "', " << resumable_cache << ")"; + << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); } return runPythonString(pythonCommands); @@ -1564,15 +1174,13 @@ bool MANTA::writeNoise(FluidModifierData *mmd, int framenr) FluidDomainSettings *mds = mmd->domain; string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); - string nformat = getCacheFileEnding(mds->cache_noise_format); - - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; + string volume_format = getCacheFileEnding(mds->cache_data_format); + string resumable_cache = !(mds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True"; if (mUsingSmoke && mUsingNoise) { ss.str(""); ss << "smoke_save_noise_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << nformat << "', " << resumable_cache << ")"; + << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); } return runPythonString(pythonCommands); @@ -1593,7 +1201,7 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) if (!hasConfig(mmd, framenr)) return false; - gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); // do some compression + gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); /* Do some compression. */ if (!gzf) { cerr << "Fluid Error -- Cannot open file " << file << endl; return false; @@ -1602,7 +1210,7 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) gzread(gzf, &mds->active_fields, sizeof(int)); gzread(gzf, &mds->res, 3 * sizeof(int)); gzread(gzf, &mds->dx, sizeof(float)); - gzread(gzf, &dummy, sizeof(float)); // dt not needed right now + gzread(gzf, &dummy, sizeof(float)); /* dt not needed right now. */ gzread(gzf, &mds->p0, 3 * sizeof(float)); gzread(gzf, &mds->p1, 3 * sizeof(float)); gzread(gzf, &mds->dp0, 3 * sizeof(float)); @@ -1614,13 +1222,14 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) gzread(gzf, &mds->res_max, 3 * sizeof(int)); gzread(gzf, &mds->active_color, 3 * sizeof(float)); gzread(gzf, &mds->time_total, sizeof(int)); + gzread(gzf, &mds->cache_id, 4 * sizeof(char)); /* Older caches might have no id. */ mds->total_cells = mds->res[0] * mds->res[1] * mds->res[2]; return (gzclose(gzf) == Z_OK); } -bool MANTA::readData(FluidModifierData *mmd, int framenr) +bool MANTA::readData(FluidModifierData *mmd, int framenr, bool resumable) { if (with_debug) cout << "MANTA::readData()" << endl; @@ -1634,39 +1243,31 @@ bool MANTA::readData(FluidModifierData *mmd, int framenr) bool result = true; string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); - string dformat = getCacheFileEnding(mds->cache_data_format); - string pformat = getCacheFileEnding(mds->cache_particle_format); - - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; + string volume_format = getCacheFileEnding(mds->cache_data_format); + string resumable_cache = (!resumable) ? "False" : "True"; /* Sanity check: Are cache files present? */ if (!hasData(mmd, framenr)) return false; - ss.str(""); - ss << "fluid_load_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << dformat << "', " << resumable_cache << ")"; - pythonCommands.push_back(ss.str()); - if (mUsingSmoke) { ss.str(""); ss << "smoke_load_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << dformat << "', " << resumable_cache << ")"; + << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); result &= runPythonString(pythonCommands); } if (mUsingLiquid) { ss.str(""); ss << "liquid_load_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << dformat << "', " << resumable_cache << ")"; + << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); result &= runPythonString(pythonCommands); } return result; } -bool MANTA::readNoise(FluidModifierData *mmd, int framenr) +bool MANTA::readNoise(FluidModifierData *mmd, int framenr, bool resumable) { if (with_debug) cout << "MANTA::readNoise()" << endl; @@ -1679,10 +1280,12 @@ bool MANTA::readNoise(FluidModifierData *mmd, int framenr) FluidDomainSettings *mds = mmd->domain; string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); - string nformat = getCacheFileEnding(mds->cache_noise_format); + string resumable_cache = (resumable) ? "False" : "True"; - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; + /* Support older caches which had more granular file format control. */ + char format = (!strcmp(mds->cache_id, FLUID_CACHE_VERSION)) ? mds->cache_data_format : + mds->cache_noise_format; + string volume_format = getCacheFileEnding(format); /* Sanity check: Are cache files present? */ if (!hasNoise(mmd, framenr)) @@ -1690,15 +1293,12 @@ bool MANTA::readNoise(FluidModifierData *mmd, int framenr) ss.str(""); ss << "smoke_load_noise_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << nformat << "', " << resumable_cache << ")"; + << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); } -/* Deprecated! This function reads mesh data via the Manta Python API. - * MANTA:updateMeshStructures() reads cache files directly from disk - * and is preferred due to its better performance. */ bool MANTA::readMesh(FluidModifierData *mmd, int framenr) { if (with_debug) @@ -1712,8 +1312,8 @@ bool MANTA::readMesh(FluidModifierData *mmd, int framenr) FluidDomainSettings *mds = mmd->domain; string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_MESH); - string mformat = getCacheFileEnding(mds->cache_mesh_format); - string dformat = getCacheFileEnding(mds->cache_data_format); + string mesh_format = getCacheFileEnding(mds->cache_mesh_format); + string volume_format = getCacheFileEnding(mds->cache_data_format); /* Sanity check: Are cache files present? */ if (!hasMesh(mmd, framenr)) @@ -1721,23 +1321,20 @@ bool MANTA::readMesh(FluidModifierData *mmd, int framenr) ss.str(""); ss << "liquid_load_mesh_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << mformat << "')"; + << ", '" << mesh_format << "')"; pythonCommands.push_back(ss.str()); if (mUsingMVel) { ss.str(""); ss << "liquid_load_meshvel_" << mCurrentID << "('" << escapeSlashes(directory) << "', " - << framenr << ", '" << dformat << "')"; + << framenr << ", '" << volume_format << "')"; pythonCommands.push_back(ss.str()); } return runPythonString(pythonCommands); } -/* Deprecated! This function reads particle data via the Manta Python API. - * MANTA:updateParticleStructures() reads cache files directly from disk - * and is preferred due to its better performance. */ -bool MANTA::readParticles(FluidModifierData *mmd, int framenr) +bool MANTA::readParticles(FluidModifierData *mmd, int framenr, bool resumable) { if (with_debug) cout << "MANTA::readParticles()" << endl; @@ -1752,10 +1349,12 @@ bool MANTA::readParticles(FluidModifierData *mmd, int framenr) FluidDomainSettings *mds = mmd->domain; string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_PARTICLES); - string pformat = getCacheFileEnding(mds->cache_particle_format); + string resumable_cache = (!resumable) ? "False" : "True"; - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; + /* Support older caches which had more granular file format control. */ + char format = (!strcmp(mds->cache_id, FLUID_CACHE_VERSION)) ? mds->cache_data_format : + mds->cache_particle_format; + string volume_format = getCacheFileEnding(format); /* Sanity check: Are cache files present? */ if (!hasParticles(mmd, framenr)) @@ -1763,7 +1362,7 @@ bool MANTA::readParticles(FluidModifierData *mmd, int framenr) ss.str(""); ss << "liquid_load_particles_" << mCurrentID << "('" << escapeSlashes(directory) << "', " - << framenr << ", '" << pformat << "', " << resumable_cache << ")"; + << framenr << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); @@ -1786,7 +1385,7 @@ bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) string directory = (sourceDomain) ? getDirectory(mmd, FLUID_DOMAIN_DIR_DATA) : getDirectory(mmd, FLUID_DOMAIN_DIR_GUIDE); - string gformat = getCacheFileEnding(mds->cache_data_format); + string volume_format = getCacheFileEnding(mds->cache_data_format); /* Sanity check: Are cache files present? */ if (!hasGuiding(mmd, framenr, sourceDomain)) @@ -1795,12 +1394,12 @@ bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) if (sourceDomain) { ss.str(""); ss << "fluid_load_vel_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr - << ", '" << gformat << "')"; + << ", '" << volume_format << "')"; } else { ss.str(""); ss << "fluid_load_guiding_" << mCurrentID << "('" << escapeSlashes(directory) << "', " - << framenr << ", '" << gformat << "')"; + << framenr << ", '" << volume_format << "')"; } pythonCommands.push_back(ss.str()); @@ -1821,9 +1420,7 @@ bool MANTA::bakeData(FluidModifierData *mmd, int framenr) cacheDirData[0] = '\0'; cacheDirGuiding[0] = '\0'; - string dformat = getCacheFileEnding(mds->cache_data_format); - string pformat = getCacheFileEnding(mds->cache_particle_format); - string gformat = dformat; // Use same data format for guiding format + string volume_format = getCacheFileEnding(mds->cache_data_format); BLI_path_join( cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); @@ -1836,9 +1433,8 @@ bool MANTA::bakeData(FluidModifierData *mmd, int framenr) BLI_path_make_safe(cacheDirGuiding); ss.str(""); - ss << "bake_fluid_data_" << mCurrentID << "('" << escapeSlashes(cacheDirData) << "', '" - << escapeSlashes(cacheDirGuiding) << "', " << framenr << ", '" << dformat << "', '" << pformat - << "', '" << gformat << "')"; + ss << "bake_fluid_data_" << mCurrentID << "('" << escapeSlashes(cacheDirData) << "', " << framenr + << ", '" << volume_format << "')"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); @@ -1853,27 +1449,18 @@ bool MANTA::bakeNoise(FluidModifierData *mmd, int framenr) vector pythonCommands; FluidDomainSettings *mds = mmd->domain; - char cacheDirData[FILE_MAX], cacheDirNoise[FILE_MAX]; - cacheDirData[0] = '\0'; + char cacheDirNoise[FILE_MAX]; cacheDirNoise[0] = '\0'; - string dformat = getCacheFileEnding(mds->cache_data_format); - string nformat = getCacheFileEnding(mds->cache_noise_format); + string volume_format = getCacheFileEnding(mds->cache_data_format); - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; - - BLI_path_join( - cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); BLI_path_join( cacheDirNoise, sizeof(cacheDirNoise), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, nullptr); - BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirNoise); ss.str(""); - ss << "bake_noise_" << mCurrentID << "('" << escapeSlashes(cacheDirData) << "', '" - << escapeSlashes(cacheDirNoise) << "', " << framenr << ", '" << dformat << "', '" << nformat - << "', " << resumable_cache << ")"; + ss << "bake_noise_" << mCurrentID << "('" << escapeSlashes(cacheDirNoise) << "', " << framenr + << ", '" << volume_format << "')"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); @@ -1888,25 +1475,19 @@ bool MANTA::bakeMesh(FluidModifierData *mmd, int framenr) vector pythonCommands; FluidDomainSettings *mds = mmd->domain; - char cacheDirData[FILE_MAX], cacheDirMesh[FILE_MAX]; - cacheDirData[0] = '\0'; + char cacheDirMesh[FILE_MAX]; cacheDirMesh[0] = '\0'; - string dformat = getCacheFileEnding(mds->cache_data_format); - string mformat = getCacheFileEnding(mds->cache_mesh_format); - string pformat = getCacheFileEnding(mds->cache_particle_format); + string volume_format = getCacheFileEnding(mds->cache_data_format); + string mesh_format = getCacheFileEnding(mds->cache_mesh_format); - BLI_path_join( - cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); BLI_path_join( cacheDirMesh, sizeof(cacheDirMesh), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, nullptr); - BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirMesh); ss.str(""); - ss << "bake_mesh_" << mCurrentID << "('" << escapeSlashes(cacheDirData) << "', '" - << escapeSlashes(cacheDirMesh) << "', " << framenr << ", '" << dformat << "', '" << mformat - << "', '" << pformat << "')"; + ss << "bake_mesh_" << mCurrentID << "('" << escapeSlashes(cacheDirMesh) << "', " << framenr + << ", '" << volume_format << "', '" << mesh_format << "')"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); @@ -1921,30 +1502,22 @@ bool MANTA::bakeParticles(FluidModifierData *mmd, int framenr) vector pythonCommands; FluidDomainSettings *mds = mmd->domain; - char cacheDirData[FILE_MAX], cacheDirParticles[FILE_MAX]; - cacheDirData[0] = '\0'; + char cacheDirParticles[FILE_MAX]; cacheDirParticles[0] = '\0'; - string dformat = getCacheFileEnding(mds->cache_data_format); - string pformat = getCacheFileEnding(mds->cache_particle_format); + string volume_format = getCacheFileEnding(mds->cache_data_format); + string resumable_cache = !(mds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True"; - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; - - BLI_path_join( - cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); BLI_path_join(cacheDirParticles, sizeof(cacheDirParticles), mds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, nullptr); - BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirParticles); ss.str(""); - ss << "bake_particles_" << mCurrentID << "('" << escapeSlashes(cacheDirData) << "', '" - << escapeSlashes(cacheDirParticles) << "', " << framenr << ", '" << dformat << "', '" - << pformat << "', " << resumable_cache << ")"; + ss << "bake_particles_" << mCurrentID << "('" << escapeSlashes(cacheDirParticles) << "', " + << framenr << ", '" << volume_format << "', " << resumable_cache << ")"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); @@ -1962,10 +1535,7 @@ bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr) char cacheDirGuiding[FILE_MAX]; cacheDirGuiding[0] = '\0'; - string gformat = getCacheFileEnding(mds->cache_data_format); - - bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); - string resumable_cache = (final_cache) ? "False" : "True"; + string volume_format = getCacheFileEnding(mds->cache_data_format); BLI_path_join(cacheDirGuiding, sizeof(cacheDirGuiding), @@ -1976,7 +1546,7 @@ bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr) ss.str(""); ss << "bake_guiding_" << mCurrentID << "('" << escapeSlashes(cacheDirGuiding) << "', " << framenr - << ", '" << gformat << "', " << resumable_cache << ")"; + << ", '" << volume_format << "')"; pythonCommands.push_back(ss.str()); return runPythonString(pythonCommands); @@ -2092,8 +1662,7 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd) manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step; // Import - manta_script += header_import + fluid_file_import + fluid_cache_helper + fluid_load_data + - smoke_load_data; + manta_script += header_import + fluid_file_import + fluid_cache_helper + smoke_load_data; if (noise) manta_script += smoke_load_noise; if (guiding) @@ -2198,8 +1767,7 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step; // Import - manta_script += header_import + fluid_file_import + fluid_cache_helper + fluid_load_data + - liquid_load_data; + manta_script += header_import + fluid_file_import + fluid_cache_helper + liquid_load_data; if (mesh) manta_script += liquid_load_mesh; if (drops || bubble || floater || tracer) @@ -2241,7 +1809,7 @@ static PyObject *callPythonFunction(string varName, string functionName, bool is { if ((varName == "") || (functionName == "")) { if (MANTA::with_debug) - cout << "Missing Python variable name and/or function name -- name is: " << varName + cout << "Fluid: Missing Python variable name and/or function name -- name is: " << varName << ", function name is: " << functionName << endl; return nullptr; } @@ -2384,952 +1952,6 @@ void MANTA::adaptTimestep() runPythonString(pythonCommands); } -bool MANTA::updateMeshFromFile(string filename) -{ - string fname(filename); - string::size_type idx; - - idx = fname.rfind('.'); - if (idx != string::npos) { - string extension = fname.substr(idx + 1); - - if (extension.compare("gz") == 0) - return updateMeshFromBobj(filename); - else if (extension.compare("obj") == 0) - return updateMeshFromObj(filename); - else if (extension.compare("uni") == 0) - return updateMeshFromUni(filename); - else - cerr << "Fluid Error -- updateMeshFromFile(): Invalid file extension in file: " << filename - << endl; - } - else { - cerr << "Fluid Error -- updateMeshFromFile(): Unable to open file: " << filename << endl; - } - return false; -} - -bool MANTA::updateMeshFromBobj(string filename) -{ - if (with_debug) - cout << "MANTA::updateMeshFromBobj()" << endl; - - gzFile gzf; - - gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression - if (!gzf) { - cerr << "Fluid Error -- updateMeshFromBobj(): Unable to open file: " << filename << endl; - return false; - } - - int numBuffer = 0, readBytes = 0; - - // Num vertices - readBytes = gzread(gzf, &numBuffer, sizeof(int)); - if (!readBytes) { - cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh vertices from " - << filename << endl; - gzclose(gzf); - return false; - } - - if (with_debug) - cout << "read mesh , num verts: " << numBuffer << " , in file: " << filename << endl; - - int numChunks = (int)(ceil((float)numBuffer / NODE_CHUNK)); - int readLen, readStart, readEnd, k; - - if (numBuffer) { - // Vertices - int todoVertices = numBuffer; - float *bufferVerts = (float *)MEM_malloc_arrayN( - NODE_CHUNK, sizeof(float) * 3, "fluid_mesh_vertices"); - - mMeshNodes->resize(numBuffer); - - for (int i = 0; i < numChunks && todoVertices > 0; ++i) { - readLen = NODE_CHUNK; - if (todoVertices < NODE_CHUNK) { - readLen = todoVertices; - } - - readBytes = gzread(gzf, bufferVerts, readLen * sizeof(float) * 3); - if (!readBytes) { - cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh vertices from " - << filename << endl; - MEM_freeN(bufferVerts); - gzclose(gzf); - return false; - } - - readStart = (numBuffer - todoVertices); - CLAMP(readStart, 0, numBuffer); - readEnd = readStart + readLen; - CLAMP(readEnd, 0, numBuffer); - - k = 0; - for (vector::size_type j = readStart; j < readEnd; j++, k += 3) { - mMeshNodes->at(j).pos[0] = bufferVerts[k]; - mMeshNodes->at(j).pos[1] = bufferVerts[k + 1]; - mMeshNodes->at(j).pos[2] = bufferVerts[k + 2]; - } - todoVertices -= readLen; - } - MEM_freeN(bufferVerts); - } - - // Num normals - readBytes = gzread(gzf, &numBuffer, sizeof(int)); - if (!readBytes) { - cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh normals from " - << filename << endl; - gzclose(gzf); - return false; - } - - if (with_debug) - cout << "read mesh , num normals : " << numBuffer << " , in file: " << filename << endl; - - if (numBuffer) { - // Normals - int todoNormals = numBuffer; - float *bufferNormals = (float *)MEM_malloc_arrayN( - NODE_CHUNK, sizeof(float) * 3, "fluid_mesh_normals"); - - if (!getNumVertices()) - mMeshNodes->resize(numBuffer); - - for (int i = 0; i < numChunks && todoNormals > 0; ++i) { - readLen = NODE_CHUNK; - if (todoNormals < NODE_CHUNK) { - readLen = todoNormals; - } - - readBytes = gzread(gzf, bufferNormals, readLen * sizeof(float) * 3); - if (!readBytes) { - cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh normals from " - << filename << endl; - MEM_freeN(bufferNormals); - gzclose(gzf); - return false; - } - - readStart = (numBuffer - todoNormals); - CLAMP(readStart, 0, numBuffer); - readEnd = readStart + readLen; - CLAMP(readEnd, 0, numBuffer); - - k = 0; - for (vector::size_type j = readStart; j < readEnd; j++, k += 3) { - mMeshNodes->at(j).normal[0] = bufferNormals[k]; - mMeshNodes->at(j).normal[1] = bufferNormals[k + 1]; - mMeshNodes->at(j).normal[2] = bufferNormals[k + 2]; - } - todoNormals -= readLen; - } - MEM_freeN(bufferNormals); - } - - // Num triangles - readBytes = gzread(gzf, &numBuffer, sizeof(int)); - if (!readBytes) { - cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh triangles from " - << filename << endl; - gzclose(gzf); - return false; - } - - if (with_debug) - cout << "Fluid: Read mesh , num triangles : " << numBuffer << " , in file: " << filename - << endl; - - numChunks = (int)(ceil((float)numBuffer / TRIANGLE_CHUNK)); - - if (numBuffer) { - // Triangles - int todoTriangles = numBuffer; - int *bufferTriangles = (int *)MEM_malloc_arrayN( - TRIANGLE_CHUNK, sizeof(int) * 3, "fluid_mesh_triangles"); - - mMeshTriangles->resize(numBuffer); - - for (int i = 0; i < numChunks && todoTriangles > 0; ++i) { - readLen = TRIANGLE_CHUNK; - if (todoTriangles < TRIANGLE_CHUNK) { - readLen = todoTriangles; - } - - readBytes = gzread(gzf, bufferTriangles, readLen * sizeof(int) * 3); - if (!readBytes) { - cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh triangles from " - << filename << endl; - MEM_freeN(bufferTriangles); - gzclose(gzf); - return false; - } - - readStart = (numBuffer - todoTriangles); - CLAMP(readStart, 0, numBuffer); - readEnd = readStart + readLen; - CLAMP(readEnd, 0, numBuffer); - - k = 0; - for (vector::size_type j = readStart; j < readEnd; j++, k += 3) { - mMeshTriangles->at(j).c[0] = bufferTriangles[k]; - mMeshTriangles->at(j).c[1] = bufferTriangles[k + 1]; - mMeshTriangles->at(j).c[2] = bufferTriangles[k + 2]; - } - todoTriangles -= readLen; - } - MEM_freeN(bufferTriangles); - } - return (gzclose(gzf) == Z_OK); -} - -bool MANTA::updateMeshFromObj(string filename) -{ - if (with_debug) - cout << "MANTA::updateMeshFromObj()" << endl; - - ifstream ifs(filename); - float fbuffer[3]; - int ibuffer[3]; - int cntVerts = 0, cntNormals = 0, cntTris = 0; - - if (!ifs.good()) { - cerr << "Fluid Error -- updateMeshFromObj(): Unable to open file: " << filename << endl; - return false; - } - - while (ifs.good() && !ifs.eof()) { - string id; - ifs >> id; - - if (id[0] == '#') { - // comment - getline(ifs, id); - continue; - } - if (id == "vt") { - // tex coord, ignore - } - else if (id == "vn") { - // normals - if (getNumVertices() != cntVerts) { - cerr << "Fluid Error -- updateMeshFromObj(): Invalid number of mesh nodes in file: " - << filename << endl; - return false; - } - - ifs >> fbuffer[0] >> fbuffer[1] >> fbuffer[2]; - MANTA::Node *node = &mMeshNodes->at(cntNormals); - (*node).normal[0] = fbuffer[0]; - (*node).normal[1] = fbuffer[1]; - (*node).normal[2] = fbuffer[2]; - cntNormals++; - } - else if (id == "v") { - // vertex - ifs >> fbuffer[0] >> fbuffer[1] >> fbuffer[2]; - MANTA::Node node; - node.pos[0] = fbuffer[0]; - node.pos[1] = fbuffer[1]; - node.pos[2] = fbuffer[2]; - mMeshNodes->push_back(node); - cntVerts++; - } - else if (id == "g") { - // group - string group; - ifs >> group; - } - else if (id == "f") { - // face - string face; - for (int i = 0; i < 3; i++) { - ifs >> face; - if (face.find('/') != string::npos) - face = face.substr(0, face.find('/')); // ignore other indices - int idx = atoi(face.c_str()) - 1; - if (idx < 0) { - cerr << "Fluid Error -- updateMeshFromObj(): Invalid face encountered in file: " - << filename << endl; - return false; - } - ibuffer[i] = idx; - } - MANTA::Triangle triangle; - triangle.c[0] = ibuffer[0]; - triangle.c[1] = ibuffer[1]; - triangle.c[2] = ibuffer[2]; - mMeshTriangles->push_back(triangle); - cntTris++; - } - else { - // whatever, ignore - } - // kill rest of line - getline(ifs, id); - } - ifs.close(); - return true; -} - -bool MANTA::updateMeshFromUni(string filename) -{ - if (with_debug) - cout << "MANTA::updateMeshFromUni()" << endl; - - gzFile gzf; - float fbuffer[4]; - int ibuffer[4]; - - gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression - if (!gzf) { - cerr << "Fluid Error -- updateMeshFromUni(): Unable to open file: " << filename << endl; - return false; - } - - int readBytes = 0; - char file_magic[5] = {0, 0, 0, 0, 0}; - readBytes = gzread(gzf, file_magic, 4); - if (!readBytes) { - cerr << "Fluid Error -- updateMeshFromUni(): Unable to read header in file: " << filename - << endl; - gzclose(gzf); - return false; - } - - vector *velocityPointer = mMeshVelocities; - - // mdata uni header - const int STR_LEN_PDATA = 256; - int elementType, bytesPerElement, numParticles; - char info[STR_LEN_PDATA]; // mantaflow build information - unsigned long long timestamp; // creation time - - // read mesh header - gzread(gzf, &ibuffer, sizeof(int) * 4); // num particles, dimX, dimY, dimZ - gzread(gzf, &elementType, sizeof(int)); - gzread(gzf, &bytesPerElement, sizeof(int)); - gzread(gzf, &info, sizeof(info)); - gzread(gzf, ×tamp, sizeof(unsigned long long)); - - if (with_debug) - cout << "Fluid: Read " << ibuffer[0] << " vertices in file: " << filename << endl; - - // Sanity checks - const int meshSize = sizeof(float) * 3 + sizeof(int); - if (!(bytesPerElement == meshSize) && (elementType == 0)) { - cerr << "Fluid Error -- updateMeshFromUni(): Invalid header in file: " << filename << endl; - gzclose(gzf); - return false; - } - if (!ibuffer[0]) { // Any vertices present? - cerr << "Fluid Error -- updateMeshFromUni(): No vertices present in file: " << filename - << endl; - gzclose(gzf); - return false; - } - - // Reading mesh - if (!strcmp(file_magic, "MB01")) { - // TODO (sebbas): Future update could add uni mesh support - } - // Reading mesh data file v1 with vec3 - else if (!strcmp(file_magic, "MD01")) { - numParticles = ibuffer[0]; - - velocityPointer->resize(numParticles); - MANTA::pVel *bufferPVel; - for (vector::iterator it = velocityPointer->begin(); it != velocityPointer->end(); - ++it) { - gzread(gzf, fbuffer, sizeof(float) * 3); - bufferPVel = (MANTA::pVel *)fbuffer; - it->pos[0] = bufferPVel->pos[0]; - it->pos[1] = bufferPVel->pos[1]; - it->pos[2] = bufferPVel->pos[2]; - } - } - return (gzclose(gzf) == Z_OK); -} - -bool MANTA::updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData) -{ - if (with_debug) - cout << "MANTA::updateParticlesFromFile()" << endl; - - string fname(filename); - string::size_type idx; - - idx = fname.rfind('.'); - if (idx != string::npos) { - string extension = fname.substr(idx + 1); - - if (extension.compare("uni") == 0) - return updateParticlesFromUni(filename, isSecondarySys, isVelData); - else - cerr << "Fluid Error -- updateParticlesFromFile(): Invalid file extension in file: " - << filename << endl; - return false; - } - else { - cerr << "Fluid Error -- updateParticlesFromFile(): Unable to open file: " << filename << endl; - return false; - } -} - -bool MANTA::updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData) -{ - if (with_debug) - cout << "MANTA::updateParticlesFromUni()" << endl; - - gzFile gzf; - int ibuffer[4]; - - gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression - if (!gzf) { - cerr << "Fluid Error -- updateParticlesFromUni(): Unable to open file: " << filename << endl; - return false; - } - - int readBytes = 0; - char file_magic[5] = {0, 0, 0, 0, 0}; - readBytes = gzread(gzf, file_magic, 4); - if (!readBytes) { - cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read header in file: " << filename - << endl; - gzclose(gzf); - return false; - } - - if (!strcmp(file_magic, "PB01")) { - cerr << "Fluid Error -- updateParticlesFromUni(): Particle uni file format v01 not " - "supported anymore." - << endl; - gzclose(gzf); - return false; - } - - // Pointer to FLIP system or to secondary particle system - vector *dataPointer = nullptr; - vector *velocityPointer = nullptr; - vector *lifePointer = nullptr; - - if (isSecondarySys) { - dataPointer = mSndParticleData; - velocityPointer = mSndParticleVelocity; - lifePointer = mSndParticleLife; - } - else { - dataPointer = mFlipParticleData; - velocityPointer = mFlipParticleVelocity; - } - - // pdata uni header - const int STR_LEN_PDATA = 256; - int elementType, bytesPerElement, numParticles; - char info[STR_LEN_PDATA]; // mantaflow build information - unsigned long long timestamp; // creation time - - // read particle header - gzread(gzf, &ibuffer, sizeof(int) * 4); // num particles, dimX, dimY, dimZ - gzread(gzf, &elementType, sizeof(int)); - gzread(gzf, &bytesPerElement, sizeof(int)); - gzread(gzf, &info, sizeof(info)); - gzread(gzf, ×tamp, sizeof(unsigned long long)); - - if (with_debug) - cout << "Fluid: Read " << ibuffer[0] << " particles in file: " << filename << endl; - - // Sanity checks - const int partSysSize = sizeof(float) * 3 + sizeof(int); - if (!(bytesPerElement == partSysSize) && (elementType == 0)) { - cerr << "Fluid Error -- updateParticlesFromUni(): Invalid header in file: " << filename - << endl; - gzclose(gzf); - return false; - } - if (!ibuffer[0]) { // Any particles present? - if (with_debug) - cout << "Fluid: No particles present in file: " << filename << endl; - gzclose(gzf); - return true; // return true since having no particles in a cache file is valid - } - - numParticles = ibuffer[0]; - - const int numChunks = (int)(ceil((float)numParticles / PARTICLE_CHUNK)); - int todoParticles, readLen; - int readStart, readEnd; - - // Reading base particle system file v2 - if (!strcmp(file_magic, "PB02")) { - MANTA::pData *bufferPData; - todoParticles = numParticles; - bufferPData = (MANTA::pData *)MEM_malloc_arrayN( - PARTICLE_CHUNK, sizeof(MANTA::pData), "fluid_particle_data"); - - dataPointer->resize(numParticles); - - for (int i = 0; i < numChunks && todoParticles > 0; ++i) { - readLen = PARTICLE_CHUNK; - if (todoParticles < PARTICLE_CHUNK) { - readLen = todoParticles; - } - - readBytes = gzread(gzf, bufferPData, readLen * sizeof(pData)); - if (!readBytes) { - cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle data in file: " - << filename << endl; - MEM_freeN(bufferPData); - gzclose(gzf); - return false; - } - - readStart = (numParticles - todoParticles); - CLAMP(readStart, 0, numParticles); - readEnd = readStart + readLen; - CLAMP(readEnd, 0, numParticles); - - int k = 0; - for (vector::size_type j = readStart; j < readEnd; j++, k++) { - dataPointer->at(j).pos[0] = bufferPData[k].pos[0]; - dataPointer->at(j).pos[1] = bufferPData[k].pos[1]; - dataPointer->at(j).pos[2] = bufferPData[k].pos[2]; - dataPointer->at(j).flag = bufferPData[k].flag; - } - todoParticles -= readLen; - } - MEM_freeN(bufferPData); - } - // Reading particle data file v1 with velocities - else if (!strcmp(file_magic, "PD01") && isVelData) { - MANTA::pVel *bufferPVel; - todoParticles = numParticles; - bufferPVel = (MANTA::pVel *)MEM_malloc_arrayN( - PARTICLE_CHUNK, sizeof(MANTA::pVel), "fluid_particle_velocity"); - - velocityPointer->resize(numParticles); - - for (int i = 0; i < numChunks && todoParticles > 0; ++i) { - readLen = PARTICLE_CHUNK; - if (todoParticles < PARTICLE_CHUNK) { - readLen = todoParticles; - } - - readBytes = gzread(gzf, bufferPVel, readLen * sizeof(pVel)); - if (!readBytes) { - cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle velocities " - "in file: " - << filename << endl; - MEM_freeN(bufferPVel); - gzclose(gzf); - return false; - } - - readStart = (numParticles - todoParticles); - CLAMP(readStart, 0, numParticles); - readEnd = readStart + readLen; - CLAMP(readEnd, 0, numParticles); - - int k = 0; - for (vector::size_type j = readStart; j < readEnd; j++, k++) { - velocityPointer->at(j).pos[0] = bufferPVel[k].pos[0]; - velocityPointer->at(j).pos[1] = bufferPVel[k].pos[1]; - velocityPointer->at(j).pos[2] = bufferPVel[k].pos[2]; - } - todoParticles -= readLen; - } - MEM_freeN(bufferPVel); - } - // Reading particle data file v1 with lifetime - else if (!strcmp(file_magic, "PD01")) { - float *bufferPLife; - todoParticles = numParticles; - bufferPLife = (float *)MEM_malloc_arrayN(PARTICLE_CHUNK, sizeof(float), "fluid_particle_life"); - - lifePointer->resize(numParticles); - - for (int i = 0; i < numChunks && todoParticles > 0; ++i) { - readLen = PARTICLE_CHUNK; - if (todoParticles < PARTICLE_CHUNK) { - readLen = todoParticles; - } - - readBytes = gzread(gzf, bufferPLife, readLen * sizeof(float)); - if (!readBytes) { - cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle life in file: " - << filename << endl; - MEM_freeN(bufferPLife); - gzclose(gzf); - return false; - } - - readStart = (numParticles - todoParticles); - CLAMP(readStart, 0, numParticles); - readEnd = readStart + readLen; - CLAMP(readEnd, 0, numParticles); - - int k = 0; - for (vector::size_type j = readStart; j < readEnd; j++, k++) { - lifePointer->at(j) = bufferPLife[k]; - } - todoParticles -= readLen; - } - MEM_freeN(bufferPLife); - } - return (gzclose(gzf) == Z_OK); -} - -bool MANTA::updateGridsFromFile(string filename, vector grids) -{ - if (with_debug) - cout << "MANTA::updateGridsFromFile()" << endl; - - if (grids.empty()) { - cerr << "Fluid Error -- updateGridsFromFile(): Cannot read into uninitialized grid vector." - << endl; - return false; - } - - string fname(filename); - string::size_type idx; - - idx = fname.rfind('.'); - if (idx != string::npos) { - string extension = fname.substr(idx); - - if (extension.compare(FLUID_DOMAIN_EXTENSION_UNI) == 0) { - return updateGridsFromUni(filename, grids); - } -#if OPENVDB == 1 - else if (extension.compare(FLUID_DOMAIN_EXTENSION_OPENVDB) == 0) { - return updateGridsFromVDB(filename, grids); - } -#endif - else if (extension.compare(FLUID_DOMAIN_EXTENSION_RAW) == 0) { - return updateGridsFromRaw(filename, grids); - } - else { - cerr << "Fluid Error -- updateGridsFromFile(): Invalid file extension in file: " << filename - << endl; - } - return false; - } - else { - cerr << "Fluid Error -- updateGridsFromFile(): Unable to open file: " << filename << endl; - return false; - } -} - -bool MANTA::updateGridsFromUni(string filename, vector grids) -{ - if (with_debug) - cout << "MANTA::updateGridsFromUni()" << endl; - - gzFile gzf; - int expectedBytes = 0, readBytes = 0; - int ibuffer[4]; - - gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); - if (!gzf) { - cerr << "Fluid Error -- updateGridsFromUni(): Unable to open file: " << filename << endl; - return false; - } - - char file_magic[5] = {0, 0, 0, 0, 0}; - readBytes = gzread(gzf, file_magic, 4); - if (!readBytes) { - cerr << "Fluid Error -- updateGridsFromUni(): Invalid header in file: " << filename << endl; - gzclose(gzf); - return false; - } - if (!strcmp(file_magic, "DDF2") || !strcmp(file_magic, "MNT1") || !strcmp(file_magic, "MNT2")) { - cerr << "Fluid Error -- updateGridsFromUni(): Unsupported header in file: " << filename - << endl; - gzclose(gzf); - return false; - } - - if (!strcmp(file_magic, "MNT3")) { - - // grid uni header - const int STR_LEN_GRID = 252; - int elementType, bytesPerElement; // data type info - char info[STR_LEN_GRID]; // mantaflow build information - int dimT; // optionally store forth dimension for 4d grids - unsigned long long timestamp; // creation time - - // read grid header - gzread(gzf, &ibuffer, sizeof(int) * 4); // dimX, dimY, dimZ, gridType - gzread(gzf, &elementType, sizeof(int)); - gzread(gzf, &bytesPerElement, sizeof(int)); - gzread(gzf, &info, sizeof(info)); - gzread(gzf, &dimT, sizeof(int)); - gzread(gzf, ×tamp, sizeof(unsigned long long)); - - if (with_debug) - cout << "Fluid: Read " << ibuffer[3] << " grid type in file: " << filename << endl; - - for (vector::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) { - GridItem gridItem = *gIter; - void **pointerList = gridItem.pointer; - int type = gridItem.type; - int *res = gridItem.res; - assert(pointerList[0]); - assert(res[0] == res[0] && res[1] == res[1] && res[2] == res[2]); - UNUSED_VARS(res); - - switch (type) { - case FLUID_DOMAIN_GRID_VEC3F: { - assert(pointerList[1] && pointerList[2]); - float **fpointers = (float **)pointerList; - expectedBytes = sizeof(float) * 3 * ibuffer[0] * ibuffer[1] * ibuffer[2]; - readBytes = 0; - for (int i = 0; i < ibuffer[0] * ibuffer[1] * ibuffer[2]; ++i) { - for (int j = 0; j < 3; ++j) { - readBytes += gzread(gzf, fpointers[j], sizeof(float)); - ++fpointers[j]; - } - } - break; - } - case FLUID_DOMAIN_GRID_FLOAT: { - float **fpointers = (float **)pointerList; - expectedBytes = sizeof(float) * ibuffer[0] * ibuffer[1] * ibuffer[2]; - readBytes = gzread( - gzf, fpointers[0], sizeof(float) * ibuffer[0] * ibuffer[1] * ibuffer[2]); - break; - } - default: { - cerr << "Fluid Error -- Unknown grid type" << endl; - } - } - - if (!readBytes) { - cerr << "Fluid Error -- updateGridFromRaw(): Unable to read raw file: " << filename - << endl; - gzclose(gzf); - return false; - } - assert(expectedBytes == readBytes); - UNUSED_VARS(expectedBytes); - - if (with_debug) - cout << "Fluid: Read successfully: " << filename << endl; - } - } - else { - cerr << "Fluid Error -- updateGridsFromUni(): Unknown header in file: " << filename << endl; - gzclose(gzf); - return false; - } - - return (gzclose(gzf) == Z_OK); -} - -#if OPENVDB == 1 -bool MANTA::updateGridsFromVDB(string filename, vector grids) -{ - if (with_debug) - cout << "MANTA::updateGridsFromVDB()" << endl; - - openvdb::initialize(); - openvdb::io::File file(filename); - try { - file.open(); - } - catch (const openvdb::IoError &) { - cerr << "Fluid Error -- updateGridsFromVDB(): IOError, invalid OpenVDB file: " << filename - << endl; - return false; - } - if (grids.empty()) { - cerr << "Fluid Error -- updateGridsFromVDB(): No grids found in grid vector" << endl; - return false; - } - - unordered_map floatAccessors; - unordered_map vec3fAccessors; - openvdb::GridBase::Ptr baseGrid; - - /* Get accessors to all grids in this OpenVDB file.*/ - for (vector::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) { - GridItem gridItem = *gIter; - string itemName = gridItem.name; - int itemType = gridItem.type; - - for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName(); - ++nameIter) { - string vdbName = nameIter.gridName(); - bool nameMatch = !itemName.compare(vdbName); - - /* Support for <= 2.83: If file has only one grid in it, use that grid. */ - openvdb::io::File::NameIterator peekNext = nameIter; - bool onlyGrid = (++peekNext == file.endName()); - if (onlyGrid) { - vdbName = itemName; - } - - if (nameMatch || onlyGrid) { - baseGrid = file.readGrid(nameIter.gridName()); - - switch (itemType) { - case FLUID_DOMAIN_GRID_VEC3F: { - openvdb::Vec3SGrid::Ptr gridVDB = openvdb::gridPtrCast(baseGrid); - openvdb::Vec3SGrid::Accessor vdbAccessor = gridVDB->getAccessor(); - vec3fAccessors.emplace(vdbName, vdbAccessor); - break; - } - case FLUID_DOMAIN_GRID_FLOAT: { - openvdb::FloatGrid::Ptr gridVDB = openvdb::gridPtrCast(baseGrid); - openvdb::FloatGrid::Accessor vdbAccessor = gridVDB->getAccessor(); - floatAccessors.emplace(vdbName, vdbAccessor); - break; - } - default: { - cerr << "Fluid Error -- Unknown grid type" << endl; - } - } - } - else { - cerr << "Fluid Error -- Could not read grid from file" << endl; - return false; - } - } - } - file.close(); - - size_t index = 0; - - /* Use res of first grid for grid loop. All grids must be same size anyways. */ - vector::iterator gIter = grids.begin(); - int *res = (*gIter).res; - - for (int z = 0; z < res[2]; ++z) { - for (int y = 0; y < res[1]; ++y) { - for (int x = 0; x < res[0]; ++x, ++index) { - openvdb::Coord xyz(x, y, z); - - for (vector::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) { - GridItem gridItem = *gIter; - void **pointerList = gridItem.pointer; - int type = gridItem.type; - int *res = gridItem.res; - assert(pointerList[0]); - assert(res[0] == res[0] && res[1] == res[1] && res[2] == res[2]); - UNUSED_VARS(res); - - switch (type) { - case FLUID_DOMAIN_GRID_VEC3F: { - unordered_map::iterator it; - it = vec3fAccessors.find(gridItem.name); - if (it == vec3fAccessors.end()) { - cerr << "Fluid Error -- '" << gridItem.name << "' not in vdb grid map" << endl; - return false; - } - openvdb::Vec3f v = it->second.getValue(xyz); - - assert(pointerList[1] && pointerList[2]); - float **fpointers = (float **)pointerList; - for (int j = 0; j < 3; ++j) { - (fpointers[j])[index] = (float)v[j]; - } - break; - } - case FLUID_DOMAIN_GRID_FLOAT: { - unordered_map::iterator it; - it = floatAccessors.find(gridItem.name); - if (it == floatAccessors.end()) { - cerr << "Fluid Error -- '" << gridItem.name << "' not in vdb grid map" << endl; - return false; - } - float v = it->second.getValue(xyz); - float **fpointers = (float **)pointerList; - (fpointers[0])[index] = v; - break; - } - default: { - cerr << "Fluid Error -- Unknown grid type" << endl; - } - } - } - } - } - } - if (with_debug) - cout << "Fluid: Read successfully: " << filename << endl; - - return true; -} -#endif - -bool MANTA::updateGridsFromRaw(string filename, vector grids) -{ - if (with_debug) - cout << "MANTA::updateGridsFromRaw()" << endl; - - gzFile gzf; - int expectedBytes, readBytes; - - gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb"); - if (!gzf) { - cout << "MANTA::updateGridsFromRaw(): unable to open file" << endl; - return false; - } - - for (vector::iterator gIter = grids.begin(); gIter != grids.end(); ++gIter) { - GridItem gridItem = *gIter; - void **pointerList = gridItem.pointer; - int type = gridItem.type; - int *res = gridItem.res; - assert(pointerList[0]); - assert(res[0] == res[0] && res[1] == res[1] && res[2] == res[2]); - UNUSED_VARS(res); - - switch (type) { - case FLUID_DOMAIN_GRID_VEC3F: { - assert(pointerList[1] && pointerList[2]); - float **fpointers = (float **)pointerList; - expectedBytes = sizeof(float) * 3 * res[0] * res[1] * res[2]; - readBytes = 0; - for (int i = 0; i < res[0] * res[1] * res[2]; ++i) { - for (int j = 0; j < 3; ++j) { - readBytes += gzread(gzf, fpointers[j], sizeof(float)); - ++fpointers[j]; - } - } - break; - } - case FLUID_DOMAIN_GRID_FLOAT: { - float **fpointers = (float **)pointerList; - expectedBytes = sizeof(float) * res[0] * res[1] * res[2]; - readBytes = gzread(gzf, fpointers[0], expectedBytes); - break; - } - default: { - cerr << "Fluid Error -- Unknown grid type" << endl; - } - } - - if (!readBytes) { - cerr << "Fluid Error -- updateGridsFromRaw(): Unable to read raw file: " << filename << endl; - gzclose(gzf); - return false; - } - assert(expectedBytes == readBytes); - - if (with_debug) - cout << "Fluid: Read successfully: " << filename << endl; - } - - if (with_debug) - cout << "Fluid: Read successfully: " << filename << endl; - - return (gzclose(gzf) == Z_OK); -} - void MANTA::updatePointers() { if (with_debug) @@ -3487,43 +2109,78 @@ bool MANTA::hasData(FluidModifierData *mmd, int framenr) string filename = (mUsingSmoke) ? FLUID_NAME_DENSITY : FLUID_NAME_PP; exists = BLI_exists(getFile(mmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str()); } + if (with_debug) + cout << "Fluid: Has Data: " << exists << endl; + return exists; } bool MANTA::hasNoise(FluidModifierData *mmd, int framenr) { - string extension = getCacheFileEnding(mmd->domain->cache_noise_format); + string extension = getCacheFileEnding(mmd->domain->cache_data_format); bool exists = BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_NOISE, extension, framenr).c_str()); /* Check single file naming. */ if (!exists) { + extension = getCacheFileEnding(mmd->domain->cache_data_format); exists = BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr) .c_str()); } + /* Check single file naming with deprecated extension. */ + if (!exists) { + extension = getCacheFileEnding(mmd->domain->cache_noise_format); + exists = BLI_exists( + getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr) + .c_str()); + } + if (with_debug) + cout << "Fluid: Has Noise: " << exists << endl; + return exists; } bool MANTA::hasMesh(FluidModifierData *mmd, int framenr) { string extension = getCacheFileEnding(mmd->domain->cache_mesh_format); - return BLI_exists( - getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_LMESH, extension, framenr).c_str()); + bool exists = BLI_exists( + getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_MESH, extension, framenr).c_str()); + + /* Check old file naming. */ + if (!exists) { + exists = BLI_exists( + getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_LMESH, extension, framenr).c_str()); + } + if (with_debug) + cout << "Fluid: Has Mesh: " << exists << endl; + + return exists; } bool MANTA::hasParticles(FluidModifierData *mmd, int framenr) { - string extension = getCacheFileEnding(mmd->domain->cache_particle_format); + string extension = getCacheFileEnding(mmd->domain->cache_data_format); bool exists = BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PARTICLES, extension, framenr).c_str()); /* Check single file naming. */ if (!exists) { + extension = getCacheFileEnding(mmd->domain->cache_data_format); exists = BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr) .c_str()); } + /* Check single file naming with deprecated extension. */ + if (!exists) { + extension = getCacheFileEnding(mmd->domain->cache_particle_format); + exists = BLI_exists( + getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr) + .c_str()); + } + if (with_debug) + cout << "Fluid: Has Particles: " << exists << endl; + return exists; } @@ -3532,7 +2189,11 @@ bool MANTA::hasGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE; string filename = (sourceDomain) ? FLUID_NAME_VELOCITY : FLUID_NAME_GUIDEVEL; string extension = getCacheFileEnding(mmd->domain->cache_data_format); - return BLI_exists(getFile(mmd, subdirectory, filename, extension, framenr).c_str()); + bool exists = BLI_exists(getFile(mmd, subdirectory, filename, extension, framenr).c_str()); + if (with_debug) + cout << "Fluid: Has Guiding: " << exists << endl; + + return exists; } string MANTA::getDirectory(FluidModifierData *mmd, string subdirectory) diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h index 6a8484c75d9..38cbd33ea0a 100644 --- a/intern/mantaflow/intern/MANTA_main.h +++ b/intern/mantaflow/intern/MANTA_main.h @@ -60,19 +60,6 @@ struct MANTA { int flags; } Triangle; - // Cache helper typedefs - typedef struct GridItem { - void **pointer; /* Array of pointers for this grid.*/ - int type; - int *res; - string name; - } GridItem; - - typedef struct FileItem { - string filename; - vector grids; - } FileItem; - // Manta step, handling everything void step(struct FluidModifierData *mmd, int startFrame); @@ -104,10 +91,10 @@ struct MANTA { // Read cache (via Manta save/load) bool readConfiguration(FluidModifierData *mmd, int framenr); - bool readData(FluidModifierData *mmd, int framenr); - bool readNoise(FluidModifierData *mmd, int framenr); + bool readData(FluidModifierData *mmd, int framenr, bool resumable); + bool readNoise(FluidModifierData *mmd, int framenr, bool resumable); bool readMesh(FluidModifierData *mmd, int framenr); - bool readParticles(FluidModifierData *mmd, int framenr); + bool readParticles(FluidModifierData *mmd, int framenr, bool resumable); bool readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain); // Read cache (via file read functions in MANTA - e.g. read .bobj.gz meshes, .uni particles) @@ -899,16 +886,6 @@ struct MANTA { string getRealValue(const string &varName); string parseLine(const string &line); string parseScript(const string &setup_string, FluidModifierData *mmd = NULL); - bool updateMeshFromBobj(string filename); - bool updateMeshFromObj(string filename); - bool updateMeshFromUni(string filename); - bool updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData); - bool updateGridsFromUni(string filename, vector grids); - bool updateGridsFromVDB(string filename, vector grids); - bool updateGridsFromRaw(string filename, vector grids); - bool updateMeshFromFile(string filename); - bool updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData); - bool updateGridsFromFile(string filename, vector grids); string getDirectory(struct FluidModifierData *mmd, string subdirectory); string getFile(struct FluidModifierData *mmd, string subdirectory, diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp index 49bc224b3fa..f1607f1bd99 100644 --- a/intern/mantaflow/intern/manta_fluid_API.cpp +++ b/intern/mantaflow/intern/manta_fluid_API.cpp @@ -94,18 +94,18 @@ int manta_read_config(MANTA *fluid, FluidModifierData *mmd, int framenr) return fluid->readConfiguration(mmd, framenr); } -int manta_read_data(MANTA *fluid, FluidModifierData *mmd, int framenr) +int manta_read_data(MANTA *fluid, FluidModifierData *mmd, int framenr, bool resumable) { if (!fluid || !mmd) return 0; - return fluid->readData(mmd, framenr); + return fluid->readData(mmd, framenr, resumable); } -int manta_read_noise(MANTA *fluid, FluidModifierData *mmd, int framenr) +int manta_read_noise(MANTA *fluid, FluidModifierData *mmd, int framenr, bool resumable) { if (!fluid || !mmd) return 0; - return fluid->readNoise(mmd, framenr); + return fluid->readNoise(mmd, framenr, resumable); } int manta_read_mesh(MANTA *fluid, FluidModifierData *mmd, int framenr) @@ -115,11 +115,11 @@ int manta_read_mesh(MANTA *fluid, FluidModifierData *mmd, int framenr) return fluid->readMesh(mmd, framenr); } -int manta_read_particles(MANTA *fluid, FluidModifierData *mmd, int framenr) +int manta_read_particles(MANTA *fluid, FluidModifierData *mmd, int framenr, bool resumable) { if (!fluid || !mmd) return 0; - return fluid->readParticles(mmd, framenr); + return fluid->readParticles(mmd, framenr, resumable); } int manta_read_guiding(MANTA *fluid, FluidModifierData *mmd, int framenr, bool sourceDomain) @@ -129,41 +129,6 @@ int manta_read_guiding(MANTA *fluid, FluidModifierData *mmd, int framenr, bool s return fluid->readGuiding(mmd, framenr, sourceDomain); } -int manta_update_liquid_structures(MANTA *fluid, FluidModifierData *mmd, int framenr) -{ - if (!fluid || !mmd) - return 0; - return fluid->updateFlipStructures(mmd, framenr); -} - -int manta_update_mesh_structures(MANTA *fluid, FluidModifierData *mmd, int framenr) -{ - if (!fluid || !mmd) - return 0; - return fluid->updateMeshStructures(mmd, framenr); -} - -int manta_update_particle_structures(MANTA *fluid, FluidModifierData *mmd, int framenr) -{ - if (!fluid || !mmd) - return 0; - return fluid->updateParticleStructures(mmd, framenr); -} - -int manta_update_smoke_structures(MANTA *fluid, FluidModifierData *mmd, int framenr) -{ - if (!fluid || !mmd) - return 0; - return fluid->updateSmokeStructures(mmd, framenr); -} - -int manta_update_noise_structures(MANTA *fluid, FluidModifierData *mmd, int framenr) -{ - if (!fluid || !mmd) - return 0; - return fluid->updateNoiseStructures(mmd, framenr); -} - int manta_bake_data(MANTA *fluid, FluidModifierData *mmd, int framenr) { if (!fluid || !mmd) diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h index 637dd22f128..0fb577cc109 100644 --- a/intern/mantaflow/intern/strings/fluid_script.h +++ b/intern/mantaflow/intern/strings/fluid_script.h @@ -33,7 +33,7 @@ from manta import *\n\ import os.path, shutil, math, sys, gc, multiprocessing, platform, time\n\ \n\ withMPBake = False # Bake files asynchronously\n\ -withMPSave = True # Save files asynchronously\n\ +withMPSave = False # Save files asynchronously\n\ isWindows = platform.system() != 'Darwin' and platform.system() != 'Linux'\n\ # TODO (sebbas): Use this to simulate Windows multiprocessing (has default mode spawn)\n\ #try:\n\ @@ -161,7 +161,19 @@ mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\ scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimstep_s$ID$ # [blength/btime] to [cells/frameLength]\n\ mantaMsg('scaleSpeedTime is ' + str(scaleSpeedTime_s$ID$))\n\ \n\ -gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n"; +gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n\ +\n\ +# OpenVDB options\n\ +vdbCompression_s$ID$ = $COMPRESSION_OPENVDB$\n\ +vdbPrecisionHalf_s$ID$ = $PRECISION_OPENVDB$\n\ +\n\ +# Cache file names\n\ +file_data_s$ID$ = '$NAME_DATA$'\n\ +file_noise_s$ID$ = '$NAME_NOISE$'\n\ +file_mesh_s$ID$ = '$NAME_MESH$'\n\ +file_meshvel_s$ID$ = '$NAME_MESH$'\n\ +file_particles_s$ID$ = '$NAME_PARTICLES$'\n\ +file_guiding_s$ID$ = '$NAME_GUIDING$'"; const std::string fluid_variables_noise = "\n\ @@ -282,8 +294,8 @@ phiIn_s$ID$.setConst(9999)\n\ phiOut_s$ID$.setConst(9999)\n\ \n\ # Keep track of important objects in dict to load them later on\n\ -fluid_data_dict_final_s$ID$ = dict(vel=vel_s$ID$, velTmp=velTmp_s$ID$)\n\ -fluid_data_dict_resume_s$ID$ = dict(phiObs=phiObs_s$ID$, phiIn=phiIn_s$ID$, phiOut=phiOut_s$ID$, flags=flags_s$ID$)\n"; +fluid_data_dict_final_s$ID$ = { 'vel' : vel_s$ID$ }\n\ +fluid_data_dict_resume_s$ID$ = { 'phiObs' : phiObs_s$ID$, 'phiIn' : phiIn_s$ID$, 'phiOut' : phiOut_s$ID$, 'flags' : flags_s$ID$, 'velTmp' : velTmp_s$ID$ }\n"; const std::string fluid_alloc_obstacle = "\n\ @@ -497,10 +509,12 @@ def fluid_cache_get_framenr_formatted_$ID$(framenr):\n\ const std::string fluid_bake_multiprocessing = "\n\ -def fluid_cache_multiprocessing_start_$ID$(function, framenr, format_data=None, format_noise=None, format_mesh=None, format_particles=None, format_guiding=None, path_data=None, path_noise=None, path_mesh=None, path_particles=None, path_guiding=None, dict=None, do_join=True, resumable=False):\n\ +def fluid_cache_multiprocessing_start_$ID$(function, framenr, file_name=None, format_data=None, format_noise=None, format_mesh=None, format_particles=None, format_guiding=None, path_data=None, path_noise=None, path_mesh=None, path_particles=None, path_guiding=None, dict=None, do_join=True, resumable=False):\n\ mantaMsg('Multiprocessing cache')\n\ if __name__ == '__main__':\n\ args = (framenr,)\n\ + if file_name:\n\ + args += (file_name,)\n\ if format_data:\n\ args += (format_data,)\n\ if format_noise:\n\ @@ -531,7 +545,7 @@ def fluid_cache_multiprocessing_start_$ID$(function, framenr, format_data=None, const std::string fluid_bake_data = "\n\ -def bake_fluid_process_data_$ID$(framenr, format_data, format_particles, format_guiding, path_data, path_guiding):\n\ +def bake_fluid_process_data_$ID$(framenr, format_data, path_data):\n\ mantaMsg('Bake fluid data')\n\ \n\ s$ID$.frame = framenr\n\ @@ -545,15 +559,15 @@ def bake_fluid_process_data_$ID$(framenr, format_data, format_particles, format_ liquid_adaptive_step_$ID$(framenr)\n\ mantaMsg('--- Step: %s seconds ---' % (time.time() - start_time))\n\ \n\ -def bake_fluid_data_$ID$(path_data, path_guiding, framenr, format_data, format_particles, format_guiding):\n\ +def bake_fluid_data_$ID$(path_data, framenr, format_data):\n\ if not withMPBake or isWindows:\n\ - bake_fluid_process_data_$ID$(framenr, format_data, format_particles, format_guiding, path_data, path_guiding)\n\ + bake_fluid_process_data_$ID$(framenr, format_data, path_data)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=bake_fluid_process_data_$ID$, framenr=framenr, format_data=format_data, format_particles=format_particles, format_guiding=format_guiding, path_data=path_data, path_guiding=path_guiding, do_join=False)\n"; + fluid_cache_multiprocessing_start_$ID$(function=bake_fluid_process_data_$ID$, framenr=framenr, format_data=format_data, path_data=path_data, do_join=False)\n"; const std::string fluid_bake_noise = "\n\ -def bake_noise_process_$ID$(framenr, format_data, format_noise, path_data, path_noise, resumable):\n\ +def bake_noise_process_$ID$(framenr, format_noise, path_noise):\n\ mantaMsg('Bake fluid noise')\n\ \n\ sn$ID$.frame = framenr\n\ @@ -563,15 +577,15 @@ def bake_noise_process_$ID$(framenr, format_data, format_noise, path_data, path_ \n\ smoke_step_noise_$ID$(framenr)\n\ \n\ -def bake_noise_$ID$(path_data, path_noise, framenr, format_data, format_noise, resumable):\n\ +def bake_noise_$ID$(path_noise, framenr, format_noise):\n\ if not withMPBake or isWindows:\n\ - bake_noise_process_$ID$(framenr, format_data, format_noise, path_data, path_noise, resumable)\n\ + bake_noise_process_$ID$(framenr, format_noise, path_noise)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=bake_noise_process_$ID$, framenr=framenr, format_data=format_data, format_noise=format_noise, path_data=path_data, path_noise=path_noise, resumable=resumable)\n"; + fluid_cache_multiprocessing_start_$ID$(function=bake_noise_process_$ID$, framenr=framenr, format_noise=format_noise, path_noise=path_noise)\n"; const std::string fluid_bake_mesh = "\n\ -def bake_mesh_process_$ID$(framenr, format_data, format_mesh, format_particles, path_data, path_mesh):\n\ +def bake_mesh_process_$ID$(framenr, format_data, format_mesh, path_mesh):\n\ mantaMsg('Bake fluid mesh')\n\ \n\ sm$ID$.frame = framenr\n\ @@ -587,15 +601,15 @@ def bake_mesh_process_$ID$(framenr, format_data, format_mesh, format_particles, if using_speedvectors_s$ID$:\n\ liquid_save_meshvel_$ID$(path_mesh, framenr, format_data)\n\ \n\ -def bake_mesh_$ID$(path_data, path_mesh, framenr, format_data, format_mesh, format_particles):\n\ +def bake_mesh_$ID$(path_mesh, framenr, format_data, format_mesh):\n\ if not withMPBake or isWindows:\n\ - bake_mesh_process_$ID$(framenr, format_data, format_mesh, format_particles, path_data, path_mesh)\n\ + bake_mesh_process_$ID$(framenr, format_data, format_mesh, path_mesh)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=bake_mesh_process_$ID$, framenr=framenr, format_data=format_data, format_mesh=format_mesh, format_particles=format_particles, path_data=path_data, path_mesh=path_mesh)\n"; + fluid_cache_multiprocessing_start_$ID$(function=bake_mesh_process_$ID$, framenr=framenr, format_data=format_data, format_mesh=format_mesh, path_mesh=path_mesh)\n"; const std::string fluid_bake_particles = "\n\ -def bake_particles_process_$ID$(framenr, format_data, format_particles, path_data, path_particles, resumable):\n\ +def bake_particles_process_$ID$(framenr, format_particles, path_particles, resumable):\n\ mantaMsg('Bake secondary particles')\n\ \n\ sp$ID$.frame = framenr\n\ @@ -609,11 +623,11 @@ def bake_particles_process_$ID$(framenr, format_data, format_particles, path_dat liquid_step_particles_$ID$()\n\ liquid_save_particles_$ID$(path_particles, framenr, format_particles, resumable)\n\ \n\ -def bake_particles_$ID$(path_data, path_particles, framenr, format_data, format_particles, resumable):\n\ +def bake_particles_$ID$(path_particles, framenr, format_particles, resumable):\n\ if not withMPBake or isWindows:\n\ - bake_particles_process_$ID$(framenr, format_data, format_particles, path_data, path_particles, resumable)\n\ + bake_particles_process_$ID$(framenr, format_particles, path_particles, resumable)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=bake_particles_process_$ID$, framenr=framenr, format_data=format_data, format_particles=format_particles, path_data=path_data, path_particles=path_particles, resumable=resumable)\n"; + fluid_cache_multiprocessing_start_$ID$(function=bake_particles_process_$ID$, framenr=framenr, format_particles=format_particles, path_particles=path_particles, resumable=resumable)\n"; const std::string fluid_bake_guiding = "\n\ @@ -650,43 +664,47 @@ def bake_guiding_$ID$(path_guiding, framenr, format_guiding, resumable):\n\ const std::string fluid_file_import = "\n\ -def fluid_file_import_s$ID$(dict, path, framenr, file_format):\n\ +def fluid_file_import_s$ID$(dict, path, framenr, file_format, file_name=None):\n\ + mantaMsg('Fluid file import, frame: ' + str(framenr))\n\ try:\n\ framenr = fluid_cache_get_framenr_formatted_$ID$(framenr)\n\ - for name, object in dict.items():\n\ - file = os.path.join(path, name + '_' + framenr + file_format)\n\ + # New cache: Try to load the data from a single file\n\ + loadCombined = 0\n\ + if file_name is not None:\n\ + file = os.path.join(path, file_name + '_' + framenr + file_format)\n\ if os.path.isfile(file):\n\ - object.load(file)\n\ - else:\n\ - mantaMsg('Could not load file ' + str(file))\n\ - except:\n\ - mantaMsg('exception found')\n\ - #mantaMsg(str(e))\n\ - pass # Just skip file load errors for now\n"; - -const std::string fluid_load_data = - "\n\ -def fluid_load_data_$ID$(path, framenr, file_format, resumable):\n\ - mantaMsg('Fluid load data, frame ' + str(framenr))\n\ - fluid_file_import_s$ID$(dict=fluid_data_dict_final_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ - \n\ - if resumable:\n\ - fluid_file_import_s$ID$(dict=fluid_data_dict_resume_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ + if file_format == '.vdb':\n\ + loadCombined = load(name=file, objects=list(dict.values()), worldSize=domainSize_s$ID$)\n\ + elif file_format == '.bobj.gz' or file_format == '.obj':\n\ + for name, object in dict.items():\n\ + if os.path.isfile(file):\n\ + loadCombined = object.load(file)\n\ \n\ - # When adaptive domain bake is resumed we need correct values in xyz vel grids\n\ - copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n"; + # Old cache: Try to load the data from separate files, i.e. per object with the object based load() function\n\ + if not loadCombined:\n\ + for name, object in dict.items():\n\ + file = os.path.join(path, name + '_' + framenr + file_format)\n\ + if os.path.isfile(file):\n\ + loadCombined = object.load(file)\n\ + \n\ + if not loadCombined:\n\ + mantaMsg('Could not load file ' + str(file))\n\ + \n\ + except Exception as e:\n\ + mantaMsg('Exception in Python fluid file import: ' + str(e))\n\ + pass # Just skip file load errors for now\n"; const std::string fluid_load_guiding = "\n\ def fluid_load_guiding_$ID$(path, framenr, file_format):\n\ mantaMsg('Fluid load guiding, frame ' + str(framenr))\n\ - fluid_file_import_s$ID$(dict=fluid_guiding_dict_s$ID$, path=path, framenr=framenr, file_format=file_format)\n"; + fluid_file_import_s$ID$(dict=fluid_guiding_dict_s$ID$, path=path, framenr=framenr, file_format=file_format, file_name=file_guiding_s$ID$)\n"; const std::string fluid_load_vel = "\n\ def fluid_load_vel_$ID$(path, framenr, file_format):\n\ mantaMsg('Fluid load vel, frame ' + str(framenr))\n\ - fluid_vel_dict_s$ID$ = dict(vel=guidevel_sg$ID$)\n\ + fluid_vel_dict_s$ID$ = { 'vel' : guidevel_sg$ID$ }\n\ fluid_file_import_s$ID$(dict=fluid_vel_dict_s$ID$, path=path, framenr=framenr, file_format=file_format)\n"; ////////////////////////////////////////////////////////////////////// @@ -695,7 +713,7 @@ def fluid_load_vel_$ID$(path, framenr, file_format):\n\ const std::string fluid_file_export = "\n\ -def fluid_file_export_s$ID$(framenr, file_format, path, dict, mode_override=True, skip_subframes=True):\n\ +def fluid_file_export_s$ID$(framenr, file_format, path, dict, file_name=None, mode_override=True, skip_subframes=True):\n\ if skip_subframes and ((timePerFrame_s$ID$ + dt0_s$ID$) < frameLength_s$ID$):\n\ return\n\ mantaMsg('Fluid file export, frame: ' + str(framenr))\n\ @@ -703,36 +721,37 @@ def fluid_file_export_s$ID$(framenr, file_format, path, dict, mode_override=True framenr = fluid_cache_get_framenr_formatted_$ID$(framenr)\n\ if not os.path.exists(path):\n\ os.makedirs(path)\n\ - for name, object in dict.items():\n\ - file = os.path.join(path, name + '_' + framenr + file_format)\n\ - if not os.path.isfile(file) or mode_override: object.save(file)\n\ + \n\ + # New cache: Try to save the data to a single file\n\ + saveCombined = 0\n\ + if file_name is not None:\n\ + file = os.path.join(path, file_name + '_' + framenr + file_format)\n\ + if not os.path.isfile(file) or mode_override:\n\ + if file_format == '.vdb':\n\ + saveCombined = save(name=file, objects=list(dict.values()), worldSize=domainSize_s$ID$, skipDeletedParts=True, compression=vdbCompression_s$ID$, precisionHalf=vdbPrecisionHalf_s$ID$)\n\ + elif file_format == '.bobj.gz' or file_format == '.obj':\n\ + for name, object in dict.items():\n\ + if not os.path.isfile(file) or mode_override:\n\ + saveCombined = object.save(file)\n\ + \n\ + # Old cache: Try to save the data to separate files, i.e. per object with the object based save() function\n\ + if not saveCombined:\n\ + for name, object in dict.items():\n\ + file = os.path.join(path, name + '_' + framenr + file_format)\n\ + if not os.path.isfile(file) or mode_override: object.save(file)\n\ + \n\ except Exception as e:\n\ - mantaMsg(str(e))\n\ + mantaMsg('Exception in Python fluid file export: ' + str(e))\n\ pass # Just skip file save errors for now\n"; -const std::string fluid_save_data = - "\n\ -def fluid_save_data_$ID$(path, framenr, file_format, resumable):\n\ - mantaMsg('Fluid save data, frame ' + str(framenr))\n\ - start_time = time.time()\n\ - if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(framenr=framenr, file_format=file_format, path=path, dict=fluid_data_dict_final_s$ID$)\n\ - if resumable:\n\ - fluid_file_export_s$ID$(framenr=framenr, file_format=file_format, path=path, dict=fluid_data_dict_resume_s$ID$)\n\ - else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=fluid_data_dict_final_s$ID$, do_join=False)\n\ - if resumable:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=fluid_data_dict_resume_s$ID$, do_join=False)\n\ - mantaMsg('--- Save: %s seconds ---' % (time.time() - start_time))\n"; - const std::string fluid_save_guiding = "\n\ -def fluid_save_guiding_$ID$(path, framenr, file_format, resumable):\n\ +def fluid_save_guiding_$ID$(path, framenr, file_format):\n\ mantaMsg('Fluid save guiding, frame ' + str(framenr))\n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(dict=fluid_guiding_dict_s$ID$, framenr=framenr, file_format=file_format, path=path)\n\ + fluid_file_export_s$ID$(dict=fluid_guiding_dict_s$ID$, framenr=framenr, file_format=file_format, path=path, file_name=file_guiding_s$ID$)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=fluid_guiding_dict_s$ID$, do_join=False)\n"; + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_guiding_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=fluid_guiding_dict_s$ID$, do_join=False)\n"; ////////////////////////////////////////////////////////////////////// // STANDALONE MODE diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h index 65733aad736..1dec61c02da 100644 --- a/intern/mantaflow/intern/strings/liquid_script.h +++ b/intern/mantaflow/intern/strings/liquid_script.h @@ -86,16 +86,16 @@ mapWeights_s$ID$ = s$ID$.create(MACGrid, name='$NAME_MAPWEIGHTS$')\n\ fractions_s$ID$ = None # allocated dynamically\n\ curvature_s$ID$ = None\n\ \n\ -pp_s$ID$ = s$ID$.create(BasicParticleSystem, name='$NAME_PP$')\n\ -pVel_pp$ID$ = pp_s$ID$.create(PdataVec3, name='$NAME_PVEL$')\n\ +pp_s$ID$ = s$ID$.create(BasicParticleSystem, name='$NAME_PARTS$')\n\ +pVel_pp$ID$ = pp_s$ID$.create(PdataVec3, name='$NAME_PARTSVELOCITY$')\n\ \n\ # Acceleration data for particle nbs\n\ pindex_s$ID$ = s$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX$')\n\ gpi_s$ID$ = s$ID$.create(IntGrid, name='$NAME_GPI$')\n\ \n\ # Keep track of important objects in dict to load them later on\n\ -liquid_data_dict_final_s$ID$ = dict(pp=pp_s$ID$, pVel=pVel_pp$ID$)\n\ -liquid_data_dict_resume_s$ID$ = dict(phiParts=phiParts_s$ID$, phi=phi_s$ID$, phiTmp=phiTmp_s$ID$)\n"; +liquid_data_dict_final_s$ID$ = { 'pVel' : pVel_pp$ID$, 'pp' : pp_s$ID$ }\n\ +liquid_data_dict_resume_s$ID$ = { 'phiParts' : phiParts_s$ID$, 'phi' : phi_s$ID$, 'phiTmp' : phiTmp_s$ID$ }\n"; const std::string liquid_alloc_mesh = "\n\ @@ -104,7 +104,7 @@ phiParts_sm$ID$ = sm$ID$.create(LevelsetGrid, name='$NAME_PHIPARTS_MESH$')\n\ phi_sm$ID$ = sm$ID$.create(LevelsetGrid, name='$NAME_PHI_MESH$')\n\ pp_sm$ID$ = sm$ID$.create(BasicParticleSystem, name='$NAME_PP_MESH$')\n\ flags_sm$ID$ = sm$ID$.create(FlagGrid, name='$NAME_FLAGS_MESH$')\n\ -mesh_sm$ID$ = sm$ID$.create(Mesh, name='$NAME_LMESH$')\n\ +mesh_sm$ID$ = sm$ID$.create(Mesh, name='$NAME_MESH$')\n\ \n\ if using_speedvectors_s$ID$:\n\ mVel_mesh$ID$ = mesh_sm$ID$.create(MdataVec3, name='$NAME_VELOCITYVEC_MESH$')\n\ @@ -119,10 +119,10 @@ phiParts_sm$ID$.setConst(9999)\n\ phi_sm$ID$.setConst(9999)\n\ \n\ # Keep track of important objects in dict to load them later on\n\ -liquid_mesh_dict_s$ID$ = dict(lMesh=mesh_sm$ID$)\n\ +liquid_mesh_dict_s$ID$ = { 'lMesh' : mesh_sm$ID$ }\n\ \n\ if using_speedvectors_s$ID$:\n\ - liquid_meshvel_dict_s$ID$ = dict(lVelMesh=mVel_mesh$ID$)\n"; + liquid_meshvel_dict_s$ID$ = { 'lVelMesh' : mVel_mesh$ID$ }\n"; const std::string liquid_alloc_curvature = "\n\ @@ -131,10 +131,10 @@ curvature_s$ID$ = s$ID$.create(RealGrid, name='$NAME_CURVATURE$')\n"; const std::string liquid_alloc_particles = "\n\ -ppSnd_sp$ID$ = sp$ID$.create(BasicParticleSystem, name='$NAME_PP_PARTICLES$')\n\ -pVelSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PVEL_PARTICLES$')\n\ -pForceSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PFORCE_PARTICLES$')\n\ -pLifeSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataReal, name='$NAME_PLIFE_PARTICLES$')\n\ +ppSnd_sp$ID$ = sp$ID$.create(BasicParticleSystem, name='$NAME_PARTS_PARTICLES$')\n\ +pVelSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PARTSVEL_PARTICLES$')\n\ +pForceSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataVec3, name='$NAME_PARTSFORCE_PARTICLES$')\n\ +pLifeSnd_pp$ID$ = ppSnd_sp$ID$.create(PdataReal, name='$NAME_PARTSLIFE_PARTICLES$')\n\ vel_sp$ID$ = sp$ID$.create(MACGrid, name='$NAME_VELOCITY_PARTICLES$')\n\ flags_sp$ID$ = sp$ID$.create(FlagGrid, name='$NAME_FLAGS_PARTICLES$')\n\ phi_sp$ID$ = sp$ID$.create(LevelsetGrid, name='$NAME_PHI_PARTICLES$')\n\ @@ -152,8 +152,8 @@ phiObs_sp$ID$.setConst(9999)\n\ phiOut_sp$ID$.setConst(9999)\n\ \n\ # Keep track of important objects in dict to load them later on\n\ -liquid_particles_dict_final_s$ID$ = dict(ppSnd=ppSnd_sp$ID$, pVelSnd=pVelSnd_pp$ID$, pLifeSnd=pLifeSnd_pp$ID$)\n\ -liquid_particles_dict_resume_s$ID$ = dict(trappedAir=trappedAir_sp$ID$, waveCrest=waveCrest_sp$ID$, kineticEnergy=kineticEnergy_sp$ID$)\n"; +liquid_particles_dict_final_s$ID$ = { 'pVelSnd' : pVelSnd_pp$ID$, 'pLifeSnd' : pLifeSnd_pp$ID$, 'ppSnd' : ppSnd_sp$ID$ }\n\ +liquid_particles_dict_resume_s$ID$ = { 'trappedAir' : trappedAir_sp$ID$, 'waveCrest' : waveCrest_sp$ID$, 'kineticEnergy' : kineticEnergy_sp$ID$ }\n"; const std::string liquid_init_phi = "\n\ @@ -401,27 +401,29 @@ const std::string liquid_load_data = "\n\ def liquid_load_data_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Liquid load data')\n\ - fluid_file_import_s$ID$(dict=liquid_data_dict_final_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ - if resumable:\n\ - fluid_file_import_s$ID$(dict=liquid_data_dict_resume_s$ID$, path=path, framenr=framenr, file_format=file_format)\n"; + dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **liquid_data_dict_final_s$ID$, **liquid_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **liquid_data_dict_final_s$ID$ }\n\ + fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\ + \n\ + copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n"; const std::string liquid_load_mesh = "\n\ def liquid_load_mesh_$ID$(path, framenr, file_format):\n\ mantaMsg('Liquid load mesh')\n\ - fluid_file_import_s$ID$(dict=liquid_mesh_dict_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ + dict = liquid_mesh_dict_s$ID$\n\ + fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_mesh_s$ID$)\n\ \n\ def liquid_load_meshvel_$ID$(path, framenr, file_format):\n\ mantaMsg('Liquid load meshvel')\n\ - fluid_file_import_s$ID$(dict=liquid_meshvel_dict_s$ID$, path=path, framenr=framenr, file_format=file_format)\n"; + dict = liquid_meshvel_dict_s$ID$\n\ + fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_meshvel_s$ID$)\n"; const std::string liquid_load_particles = "\n\ def liquid_load_particles_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Liquid load particles')\n\ - fluid_file_import_s$ID$(dict=liquid_particles_dict_final_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ - if resumable:\n\ - fluid_file_import_s$ID$(dict=liquid_particles_dict_resume_s$ID$, path=path, framenr=framenr, file_format=file_format)\n"; + dict = { **liquid_particles_dict_final_s$ID$, **liquid_particles_dict_resume_s$ID$ } if resumable else { **liquid_particles_dict_final_s$ID$ }\n\ + fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_particles_s$ID$)\n"; ////////////////////////////////////////////////////////////////////// // EXPORT @@ -431,43 +433,39 @@ const std::string liquid_save_data = "\n\ def liquid_save_data_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Liquid save data')\n\ + dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **liquid_data_dict_final_s$ID$, **liquid_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **liquid_data_dict_final_s$ID$ }\n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(dict=liquid_data_dict_final_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ - if resumable:\n\ - fluid_file_export_s$ID$(dict=liquid_data_dict_resume_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ + fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=liquid_data_dict_final_s$ID$, do_join=False)\n\ - if resumable:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=liquid_data_dict_resume_s$ID$, do_join=False)\n"; + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_data_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n"; const std::string liquid_save_mesh = "\n\ def liquid_save_mesh_$ID$(path, framenr, file_format):\n\ mantaMsg('Liquid save mesh')\n\ + dict = liquid_mesh_dict_s$ID$\n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(dict=liquid_mesh_dict_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ + fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_mesh_s$ID$)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=liquid_mesh_dict_s$ID$, do_join=False)\n\ + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_mesh_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n\ \n\ def liquid_save_meshvel_$ID$(path, framenr, file_format):\n\ mantaMsg('Liquid save mesh vel')\n\ + dict = liquid_meshvel_dict_s$ID$\n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(dict=liquid_meshvel_dict_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ + fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=liquid_meshvel_dict_s$ID$, do_join=False)\n"; + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n"; const std::string liquid_save_particles = "\n\ def liquid_save_particles_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Liquid save particles')\n\ + dict = { **liquid_particles_dict_final_s$ID$, **liquid_particles_dict_resume_s$ID$ } if resumable else { **liquid_particles_dict_final_s$ID$ }\n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(dict=liquid_particles_dict_final_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ - if resumable:\n\ - fluid_file_export_s$ID$(dict=liquid_particles_dict_resume_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ + fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_particles_s$ID$)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=liquid_particles_dict_final_s$ID$, do_join=False)\n\ - if resumable:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=liquid_particles_dict_resume_s$ID$, do_join=False)\n"; + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_particles_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n"; ////////////////////////////////////////////////////////////////////// // STANDALONE MODE @@ -477,7 +475,6 @@ const std::string liquid_standalone = "\n\ # Helper function to call cache load functions\n\ def load(frame, cache_resumable):\n\ - fluid_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\ liquid_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\ if using_sndparts_s$ID$:\n\ liquid_load_particles_$ID$(os.path.join(cache_dir, 'particles'), frame, file_format_particles, cache_resumable)\n\ diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h index a592ad8644a..5e80e4443a3 100644 --- a/intern/mantaflow/intern/strings/smoke_script.h +++ b/intern/mantaflow/intern/strings/smoke_script.h @@ -101,8 +101,8 @@ color_g_in_s$ID$ = None\n\ color_b_in_s$ID$ = None\n\ \n\ # Keep track of important objects in dict to load them later on\n\ -smoke_data_dict_final_s$ID$ = dict(density=density_s$ID$, shadow=shadow_s$ID$)\n\ -smoke_data_dict_resume_s$ID$ = dict(densityIn=densityIn_s$ID$, emission=emission_s$ID$)\n"; +smoke_data_dict_final_s$ID$ = { 'density' : density_s$ID$, 'shadow' : shadow_s$ID$ }\n\ +smoke_data_dict_resume_s$ID$ = { 'densityIn' : densityIn_s$ID$, 'emission' : emission_s$ID$ }\n"; const std::string smoke_alloc_noise = "\n\ @@ -213,8 +213,8 @@ if 'heat_s$ID$' in globals(): del heat_s$ID$\n\ if 'heatIn_s$ID$' in globals(): del heatIn_s$ID$\n\ \n\ mantaMsg('Allocating heat')\n\ -heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_HEAT$')\n\ -heatIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_HEATIN$')\n\ +heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATURE$')\n\ +heatIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATUREIN$')\n\ \n\ # Add objects to dict to load them later on\n\ if 'smoke_data_dict_final_s$ID$' in globals():\n\ @@ -542,19 +542,19 @@ const std::string smoke_load_data = "\n\ def smoke_load_data_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Smoke load data')\n\ - fluid_file_import_s$ID$(dict=smoke_data_dict_final_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ - if resumable:\n\ - fluid_file_import_s$ID$(dict=smoke_data_dict_resume_s$ID$, path=path, framenr=framenr, file_format=file_format)\n"; + dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **smoke_data_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **smoke_data_dict_final_s$ID$ }\n\ + fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\ + \n\ + copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n"; const std::string smoke_load_noise = "\n\ def smoke_load_noise_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Smoke load noise')\n\ - fluid_file_import_s$ID$(dict=smoke_noise_dict_final_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ + dict = { **smoke_noise_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\ + fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_noise_s$ID$)\n\ \n\ if resumable:\n\ - fluid_file_import_s$ID$(dict=smoke_noise_dict_resume_s$ID$, path=path, framenr=framenr, file_format=file_format)\n\ - \n\ # Fill up xyz texture grids, important when resuming a bake\n\ copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\ copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n"; @@ -568,28 +568,22 @@ const std::string smoke_save_data = def smoke_save_data_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Smoke save data')\n\ start_time = time.time()\n\ + dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **smoke_data_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **smoke_data_dict_final_s$ID$ } \n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(framenr=framenr, file_format=file_format, path=path, dict=smoke_data_dict_final_s$ID$,)\n\ - if resumable:\n\ - fluid_file_export_s$ID$(framenr=framenr, file_format=file_format, path=path, dict=smoke_data_dict_resume_s$ID$,)\n\ + fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=smoke_data_dict_final_s$ID$, do_join=False)\n\ - if resumable:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=smoke_data_dict_resume_s$ID$, do_join=False)\n\ + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_data_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n\ mantaMsg('--- Save: %s seconds ---' % (time.time() - start_time))\n"; const std::string smoke_save_noise = "\n\ def smoke_save_noise_$ID$(path, framenr, file_format, resumable):\n\ mantaMsg('Smoke save noise')\n\ + dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\ if not withMPSave or isWindows:\n\ - fluid_file_export_s$ID$(dict=smoke_noise_dict_final_s$ID$, framenr=framenr, file_format=file_format, path=path)\n\ - if resumable:\n\ - fluid_file_export_s$ID$(dict=smoke_noise_dict_resume_s$ID$, framenr=framenr, file_format=file_format, path=path)\n\ + fluid_file_export_s$ID$(dict=dict, framenr=framenr, file_format=file_format, path=path, file_name=file_noise_s$ID$)\n\ else:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=smoke_noise_dict_final_s$ID$, do_join=False)\n\ - if resumable:\n\ - fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=smoke_noise_dict_resume_s$ID$, do_join=False)\n"; + fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_noise_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n"; ////////////////////////////////////////////////////////////////////// // STANDALONE MODE @@ -599,7 +593,6 @@ const std::string smoke_standalone = "\n\ # Helper function to call cache load functions\n\ def load(frame, cache_resumable):\n\ - fluid_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\ smoke_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\ if using_noise_s$ID$:\n\ smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_noise, cache_resumable)\n\ diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index 71153ba8b74..59b66b427f1 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -399,9 +399,6 @@ class QuickSmoke(ObjectModeOperator, Operator): if self.style == 'FIRE' or self.style == 'BOTH': obj.modifiers[-1].domain_settings.use_noise = True - # set correct cache file format for smoke - obj.modifiers[-1].domain_settings.cache_data_format = 'UNI' - # Setup material # Cycles and Eevee diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index 833cd05dd81..1727771637d 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -213,7 +213,7 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel): split.enabled = note_flag bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end) - if domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete: + if domain.cache_resumable and domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete: col = split.column() col.operator("fluid.bake_data", text="Resume") col = split.column() @@ -1119,9 +1119,7 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel): is_baking_any = domain.is_cache_baking_any has_baked_data = domain.has_cache_baked_data - has_baked_noise = domain.has_cache_baked_noise has_baked_mesh = domain.has_cache_baked_mesh - has_baked_particles = domain.has_cache_baked_particles col = layout.column() col.prop(domain, "cache_directory", text="") @@ -1146,35 +1144,32 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel): col.separator() col = flow.column() + col.enabled = not is_baking_any and not has_baked_data + col.prop(domain, "cache_resumable", text="Is Resumable") + row = col.row() row.enabled = not is_baking_any and not has_baked_data - row.prop(domain, "cache_data_format", text="Data File Format") + row.prop(domain, "cache_data_format", text="Format Volumes") - if md.domain_settings.domain_type in {'GAS'}: - if domain.use_noise: - row = col.row() - row.enabled = not is_baking_any and not has_baked_noise - row.prop(domain, "cache_noise_format", text="Noise File Format") - - if md.domain_settings.domain_type in {'LIQUID'}: - # File format for all particle systemes (FLIP and secondary) + if md.domain_settings.domain_type in {'LIQUID'} and domain.use_mesh: row = col.row() - row.enabled = not is_baking_any and not has_baked_particles and not has_baked_data - row.prop(domain, "cache_particle_format", text="Particle File Format") + row.enabled = not is_baking_any and not has_baked_mesh + row.prop(domain, "cache_mesh_format", text="Meshes") - if domain.use_mesh: - row = col.row() - row.enabled = not is_baking_any and not has_baked_mesh - row.prop(domain, "cache_mesh_format", text="Mesh File Format") - - if domain.cache_type == 'FINAL': + if domain.cache_type == 'ALL': col.separator() split = layout.split() - if domain.is_cache_baking_data and not domain.has_cache_baked_data: + bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end) + if domain.cache_resumable and domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete: + col = split.column() + col.operator("fluid.bake_all", text="Resume") + col = split.column() + col.operator("fluid.free_all", text="Free") + elif domain.is_cache_baking_data and not domain.has_cache_baked_data: split.enabled = False - split.operator("fluid.pause_bake", text="Baking All - ESC to cancel") + split.operator("fluid.pause_bake", text="Baking All - ESC to pause") elif not domain.has_cache_baked_data and not domain.is_cache_baking_data: split.operator("fluid.bake_all", text="Bake All") else: @@ -1189,8 +1184,8 @@ class PHYSICS_PT_export(PhysicButtonsPanel, Panel): @classmethod def poll(cls, context): - # Only show the advanced panel to advanced users who know Mantaflow's birthday :) - if not PhysicButtonsPanel.poll_fluid_domain(context) or bpy.app.debug_value != 3001: + domain = context.fluid.domain_settings + if not PhysicButtonsPanel.poll_fluid_domain(context) or (domain.cache_data_format != 'OPENVDB' and bpy.app.debug_value != 3001): return False return (context.engine in cls.COMPAT_ENGINES) @@ -1203,12 +1198,24 @@ class PHYSICS_PT_export(PhysicButtonsPanel, Panel): is_baking_any = domain.is_cache_baking_any has_baked_any = domain.has_cache_baked_any + has_baked_data = domain.has_cache_baked_data flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) flow.enabled = not is_baking_any and not has_baked_any col = flow.column() - col.prop(domain, "export_manta_script", text="Export Mantaflow Script") + + if domain.cache_data_format == 'OPENVDB': + col.enabled = not is_baking_any and not has_baked_data + col.prop(domain, "openvdb_cache_compress_type", text="Compression Volumes") + + col = flow.column() + col.prop(domain, "openvdb_data_depth", text="Precision Volumes") + + # Only show the advanced panel to advanced users who know Mantaflow's birthday :) + if bpy.app.debug_value == 3001: + col = flow.column() + col.prop(domain, "export_manta_script", text="Export Mantaflow Script") class PHYSICS_PT_field_weights(PhysicButtonsPanel, Panel): diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index a66454d2bcc..103c3bb119d 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -3809,6 +3809,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, bubble = mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE; floater = mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; + bool with_resumable_cache = mds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE; bool with_script, with_adaptive, with_noise, with_mesh, with_particles, with_guide; with_script = mds->flags & FLUID_DOMAIN_EXPORT_MANTA_SCRIPT; with_adaptive = mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN; @@ -3868,13 +3869,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Cache mode specific settings. */ switch (mode) { - case FLUID_DOMAIN_CACHE_FINAL: - /* Just load the data that has already been baked */ - if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) { - read_cache = true; - bake_cache = false; - } - break; + case FLUID_DOMAIN_CACHE_ALL: case FLUID_DOMAIN_CACHE_MODULAR: /* Just load the data that has already been baked */ if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) { @@ -3929,6 +3924,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, break; } + bool read_partial = false, read_all = false; /* Try to read from cache and keep track of read success. */ if (read_cache) { @@ -3937,20 +3933,16 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, has_config = manta_read_config(mds->fluid, mmd, mesh_frame); /* Update mesh data from file is faster than via Python (manta_read_mesh()). */ - has_mesh = manta_update_mesh_structures(mds->fluid, mmd, mesh_frame); + has_mesh = manta_read_mesh(mds->fluid, mmd, mesh_frame); } /* Read particles cache. */ if (with_liquid && with_particles) { has_config = manta_read_config(mds->fluid, mmd, particles_frame); - if (!baking_data && !baking_particles && next_particles) { - /* Update particle data from file is faster than via Python (manta_read_particles()). */ - has_particles = manta_update_particle_structures(mds->fluid, mmd, particles_frame); - } - else { - has_particles = manta_read_particles(mds->fluid, mmd, particles_frame); - } + read_partial = !baking_data && !baking_particles && next_particles; + read_all = !read_partial && with_resumable_cache; + has_particles = manta_read_particles(mds->fluid, mmd, particles_frame, read_all); } /* Read guide cache. */ @@ -3968,12 +3960,10 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } - if (!baking_data && !baking_noise && next_noise) { - has_noise = manta_update_noise_structures(mds->fluid, mmd, noise_frame); - } - else { - has_noise = manta_read_noise(mds->fluid, mmd, noise_frame); - } + + read_partial = !baking_data && !baking_noise && next_noise; + read_all = !read_partial && with_resumable_cache; + has_noise = manta_read_noise(mds->fluid, mmd, noise_frame, read_all); /* When using the adaptive domain, copy all data that was read to a new fluid object. */ if (with_adaptive && baking_noise) { @@ -3987,12 +3977,10 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift); } } - if (!baking_data && !baking_noise && next_data && next_noise) { - /* Nothing to do here since we already loaded noise grids. */ - } - else { - has_data = manta_read_data(mds->fluid, mmd, data_frame); - } + + read_partial = !baking_data && !baking_noise && next_data && next_noise; + read_all = !read_partial && with_resumable_cache; + has_data = manta_read_data(mds->fluid, mmd, data_frame, read_all); } /* Read data cache only */ else { @@ -4003,28 +3991,17 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, if (has_config && manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } - /* Read data cache */ - if (!baking_data && !baking_particles && !baking_mesh && next_data) { - has_data = manta_update_smoke_structures(mds->fluid, mmd, data_frame); - } - else { - has_data = manta_read_data(mds->fluid, mmd, data_frame); - } - } - if (with_liquid) { - if (!baking_data && !baking_particles && !baking_mesh && next_data) { - has_data = manta_update_liquid_structures(mds->fluid, mmd, data_frame); - } - else { - has_data = manta_read_data(mds->fluid, mmd, data_frame); - } } + + read_partial = !baking_data && !baking_particles && !baking_mesh && next_data; + read_all = !read_partial && with_resumable_cache; + has_data = manta_read_data(mds->fluid, mmd, data_frame, read_all); } } /* Cache mode specific settings */ switch (mode) { - case FLUID_DOMAIN_CACHE_FINAL: + case FLUID_DOMAIN_CACHE_ALL: case FLUID_DOMAIN_CACHE_MODULAR: if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) { bake_cache = false; @@ -4987,12 +4964,12 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd) /* OpenVDB cache options */ #ifdef WITH_OPENVDB_BLOSC - mmd->domain->openvdb_comp = VDB_COMPRESSION_BLOSC; + mmd->domain->openvdb_compression = VDB_COMPRESSION_BLOSC; #else - mmd->domain->openvdb_comp = VDB_COMPRESSION_ZIP; + mmd->domain->openvdb_compression = VDB_COMPRESSION_ZIP; #endif mmd->domain->clipping = 1e-6f; - mmd->domain->data_depth = 0; + mmd->domain->openvdb_data_depth = 0; } else if (mmd->type & MOD_FLUID_TYPE_FLOW) { if (mmd->flow) { @@ -5229,9 +5206,9 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *mmd, } /* OpenVDB cache options */ - tmds->openvdb_comp = mds->openvdb_comp; + tmds->openvdb_compression = mds->openvdb_compression; tmds->clipping = mds->clipping; - tmds->data_depth = mds->data_depth; + tmds->openvdb_data_depth = mds->openvdb_data_depth; } else if (tmmd->flow) { FluidFlowSettings *tmfs = tmmd->flow; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 298c0b1d78b..c56dbcba133 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1062,7 +1062,7 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke FluidModifierData *mmd = (FluidModifierData *)smoke_v; FluidDomainSettings *mds = mmd->domain; - OpenVDBWriter_set_flags(writer, mds->openvdb_comp, (mds->data_depth == 16)); + OpenVDBWriter_set_flags(writer, mds->openvdb_compression, (mds->openvdb_data_depth == 16)); OpenVDBWriter_add_meta_int(writer, "blender/smoke/active_fields", mds->active_fields); OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/resolution", mds->res); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 8524870c15e..8f6b5aa8bc3 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -270,31 +270,31 @@ static void fluid_bake_sequence(FluidJob *job) *(job->do_update) = true; } - /* Get current pause frame (pointer) - depending on bake type */ + /* Get current pause frame (pointer) - depending on bake type. */ pause_frame = job->pause_frame; - /* Set frame to start point (depending on current pause frame value) */ + /* Set frame to start point (depending on current pause frame value). */ is_first_frame = ((*pause_frame) == 0); frame = is_first_frame ? mds->cache_frame_start : (*pause_frame); - /* Save orig frame and update scene frame */ + /* Save orig frame and update scene frame. */ orig_frame = CFRA; CFRA = frame; - /* Loop through selected frames */ + /* Loop through selected frames. */ for (; frame <= mds->cache_frame_end; frame++) { const float progress = (frame - mds->cache_frame_start) / (float)frames; - /* Keep track of pause frame - needed to init future loop */ + /* Keep track of pause frame - needed to init future loop. */ (*pause_frame) = frame; - /* If user requested stop, quit baking */ + /* If user requested stop, quit baking. */ if (G.is_break) { job->success = 0; return; } - /* Update progress bar */ + /* Update progress bar. */ if (job->do_update) { *(job->do_update) = true; } @@ -304,17 +304,17 @@ static void fluid_bake_sequence(FluidJob *job) CFRA = frame; - /* Update animation system */ + /* Update animation system. */ ED_update_for_newframe(job->bmain, job->depsgraph); - /* If user requested stop, quit baking */ + /* If user requested stop, quit baking. */ if (G.is_break) { job->success = 0; return; } } - /* Restore frame position that we were on before bake */ + /* Restore frame position that we were on before bake. */ CFRA = orig_frame; } @@ -355,9 +355,9 @@ static void fluid_bake_endjob(void *customdata) WM_set_locked_interface(G_MAIN->wm.first, false); /* Bake was successful: - * Report for ended bake and how long it took */ + * Report for ended bake and how long it took. */ if (job->success) { - /* Show bake info */ + /* Show bake info. */ WM_reportf( RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start); } @@ -365,7 +365,7 @@ static void fluid_bake_endjob(void *customdata) if (mds->error[0] != '\0') { WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error); } - else { /* User canceled the bake */ + else { /* User canceled the bake. */ WM_reportf(RPT_WARNING, "Fluid: %s canceled!", job->name); } } diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h index e8a22d8c821..263cd3f7887 100644 --- a/source/blender/makesdna/DNA_fluid_types.h +++ b/source/blender/makesdna/DNA_fluid_types.h @@ -45,6 +45,7 @@ enum { FLUID_DOMAIN_USE_FRACTIONS = (1 << 13), /* Use second order obstacles. */ FLUID_DOMAIN_DELETE_IN_OBSTACLE = (1 << 14), /* Delete fluid inside obstacles. */ FLUID_DOMAIN_USE_DIFFUSION = (1 << 15), /* Use diffusion (e.g. viscosity, surface tension). */ + FLUID_DOMAIN_USE_RESUMABLE_CACHE = (1 << 16), /* Determine if cache should be resumable. */ }; /* Border collisions. */ @@ -214,6 +215,7 @@ enum { #define FLUID_DOMAIN_DIR_SCRIPT "script" #define FLUID_DOMAIN_SMOKE_SCRIPT "smoke_script.py" #define FLUID_DOMAIN_LIQUID_SCRIPT "liquid_script.py" +#define FLUID_CACHE_VERSION "C01" /* Cache file names. */ #define FLUID_NAME_CONFIG "config" @@ -224,24 +226,24 @@ enum { #define FLUID_NAME_GUIDING "fluid_guiding" /* Fluid object names.*/ -#define FLUID_NAME_FLAGS "flags" -#define FLUID_NAME_VELOCITY "vel" -#define FLUID_NAME_VELOCITYTMP "velocityTmp" +#define FLUID_NAME_FLAGS "flags" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_VELOCITY "velocity" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_VELOCITYTMP "velocity_previous" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_VELOCITYX "x_vel" #define FLUID_NAME_VELOCITYY "y_vel" #define FLUID_NAME_VELOCITYZ "z_vel" #define FLUID_NAME_PRESSURE "pressure" -#define FLUID_NAME_PHIOBS "phiObs" +#define FLUID_NAME_PHIOBS "phi_obstacle" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_PHISIN "phiSIn" -#define FLUID_NAME_PHIIN "phiIn" -#define FLUID_NAME_PHIOUT "phiOut" +#define FLUID_NAME_PHIIN "phi_inflow" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_PHIOUT "phi_out" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_FORCES "forces" #define FLUID_NAME_FORCE_X "x_force" #define FLUID_NAME_FORCE_Y "y_force" #define FLUID_NAME_FORCE_Z "z_force" #define FLUID_NAME_NUMOBS "numObs" #define FLUID_NAME_PHIOBSSIN "phiObsSIn" -#define FLUID_NAME_PHIOBSIN "phiObsIn" +#define FLUID_NAME_PHIOBSIN "phi_obstacle_inflow" #define FLUID_NAME_OBVEL "obvel" #define FLUID_NAME_OBVELC "obvelC" #define FLUID_NAME_OBVEL_X "x_obvel" @@ -254,44 +256,48 @@ enum { #define FLUID_NAME_INVEL_Y "y_invel" #define FLUID_NAME_INVEL_Z "z_invel" #define FLUID_NAME_PHIOUTSIN "phiOutSIn" -#define FLUID_NAME_PHIOUTIN "phiOutIn" +#define FLUID_NAME_PHIOUTIN "phi_out_inflow" /* Smoke object names. */ -#define FLUID_NAME_SHADOW "shadow" -#define FLUID_NAME_EMISSION "emission" +#define FLUID_NAME_SHADOW "shadow" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_EMISSION "emission" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_EMISSIONIN "emissionIn" -#define FLUID_NAME_DENSITY "density" -#define FLUID_NAME_DENSITYIN "densityIn" +#define FLUID_NAME_DENSITY "density" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_DENSITYIN "density_inflow" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_HEAT "heat" #define FLUID_NAME_HEATIN "heatIn" -#define FLUID_NAME_COLORR "color_r" -#define FLUID_NAME_COLORG "color_g" -#define FLUID_NAME_COLORB "color_b" -#define FLUID_NAME_COLORRIN "color_r_in" -#define FLUID_NAME_COLORGIN "color_g_in" -#define FLUID_NAME_COLORBIN "color_b_in" -#define FLUID_NAME_FLAME "flame" -#define FLUID_NAME_FUEL "fuel" -#define FLUID_NAME_REACT "react" -#define FLUID_NAME_FUELIN "fuelIn" -#define FLUID_NAME_REACTIN "reactIn" +#define FLUID_NAME_TEMPERATURE "temperature" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_TEMPERATUREIN "temperature_inflow" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORR "color_r" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORG "color_g" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORB "color_b" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORRIN "color_r_inflow" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORGIN "color_g_inflow" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORBIN "color_b_inflow" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_FLAME "flame" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_FUEL "fuel" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_REACT "react" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_FUELIN "fuel_inflow" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_REACTIN "react_inflow" /* == OpenVDB grid attribute name. */ /* Liquid object names. */ -#define FLUID_NAME_PHIPARTS "phiParts" -#define FLUID_NAME_PHI "phi" -#define FLUID_NAME_PHITMP "phiTmp" +#define FLUID_NAME_PHIPARTS "phi_particles" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_PHI "phi" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_PHITMP "phi_previous" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_VELOCITYOLD "velOld" #define FLUID_NAME_VELOCITYPARTS "velParts" #define FLUID_NAME_MAPWEIGHTS "mapWeights" #define FLUID_NAME_PP "pp" #define FLUID_NAME_PVEL "pVel" +#define FLUID_NAME_PARTS "particles" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_PARTSVELOCITY "particles_velocity" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_PINDEX "pindex" #define FLUID_NAME_GPI "gpi" #define FLUID_NAME_CURVATURE "gpi" /* Noise object names. */ #define FLUID_NAME_VELOCITY_NOISE "velocity_noise" -#define FLUID_NAME_DENSITY_NOISE "density_noise" +#define FLUID_NAME_DENSITY_NOISE "density_noise" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_PHIIN_NOISE "phiIn_noise" #define FLUID_NAME_PHIOUT_NOISE "phiOut_noise" #define FLUID_NAME_PHIOBS_NOISE "phiObs_noise" @@ -306,11 +312,11 @@ enum { #define FLUID_NAME_TEXTURE_U2 "textureU2" #define FLUID_NAME_TEXTURE_V2 "textureV2" #define FLUID_NAME_TEXTURE_W2 "textureW2" -#define FLUID_NAME_UV0 "uvGrid0" -#define FLUID_NAME_UV1 "uvGrid1" -#define FLUID_NAME_COLORR_NOISE "color_r_noise" -#define FLUID_NAME_COLORG_NOISE "color_g_noise" -#define FLUID_NAME_COLORB_NOISE "color_b_noise" +#define FLUID_NAME_UV0 "uv_grid_0" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_UV1 "uv_grid_1" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORR_NOISE "color_r_noise" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORG_NOISE "color_g_noise" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_COLORB_NOISE "color_b_noise" /* == OpenVDB grid attribute name. */ #define FLUID_NAME_FLAME_NOISE "flame_noise" #define FLUID_NAME_FUEL_NOISE "fuel_noise" #define FLUID_NAME_REACT_NOISE "react_noise" @@ -321,7 +327,8 @@ enum { #define FLUID_NAME_PP_MESH "pp_mesh" #define FLUID_NAME_FLAGS_MESH "flags_mesh" #define FLUID_NAME_LMESH "lMesh" -#define FLUID_NAME_VELOCITYVEC_MESH "lVelMesh" +#define FLUID_NAME_VELOCITYVEC_MESH "vertex_velocities_mesh" /* == OpenVDB grid attribute name. \ + */ #define FLUID_NAME_VELOCITY_MESH "velocity_mesh" #define FLUID_NAME_PINDEX_MESH "pindex_mesh" #define FLUID_NAME_GPI_MESH "gpi_mesh" @@ -329,18 +336,27 @@ enum { /* Particles object names. */ #define FLUID_NAME_PP_PARTICLES "ppSnd" #define FLUID_NAME_PVEL_PARTICLES "pVelSnd" -#define FLUID_NAME_PFORCE_PARTICLES "pForceSnd" #define FLUID_NAME_PLIFE_PARTICLES "pLifeSnd" -#define FLUID_NAME_VELOCITY_PARTICLES "velocity_particles" -#define FLUID_NAME_FLAGS_PARTICLES "flags_particles" -#define FLUID_NAME_PHI_PARTICLES "phi_particles" -#define FLUID_NAME_PHIOBS_PARTICLES "phiObs_particles" -#define FLUID_NAME_PHIOUT_PARTICLES "phiOut_particles" -#define FLUID_NAME_NORMAL_PARTICLES "normal_particles" -#define FLUID_NAME_NEIGHBORRATIO_PARTICLES "neighborRatio_particles" -#define FLUID_NAME_TRAPPEDAIR_PARTICLES "trappedAir_particles" -#define FLUID_NAME_WAVECREST_PARTICLES "waveCrest_particles" -#define FLUID_NAME_KINETICENERGY_PARTICLES "kineticEnergy_particles" +#define FLUID_NAME_PFORCE_PARTICLES "pForceSnd" +#define FLUID_NAME_PARTS_PARTICLES "particles_secondary" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_PARTSVEL_PARTICLES \ + "particles_velocity_secondary" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_PARTSLIFE_PARTICLES \ + "particles_life_secondary" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_PARTSFORCE_PARTICLES "particles_force_secondary" +#define FLUID_NAME_VELOCITY_PARTICLES "velocity_secondary" +#define FLUID_NAME_FLAGS_PARTICLES "flags_secondary" +#define FLUID_NAME_PHI_PARTICLES "phi_secondary" +#define FLUID_NAME_PHIOBS_PARTICLES "phiObs_secondary" +#define FLUID_NAME_PHIOUT_PARTICLES "phiOut_secondary" +#define FLUID_NAME_NORMAL_PARTICLES "normal_secondary" +#define FLUID_NAME_NEIGHBORRATIO_PARTICLES "neighbor_ratio_secondary" +#define FLUID_NAME_TRAPPEDAIR_PARTICLES \ + "trapped_air_secondary" /* == OpenVDB grid attribute name. */ +#define FLUID_NAME_WAVECREST_PARTICLES "wave_crest_secondary" /* == OpenVDB grid attribute name. \ + */ +#define FLUID_NAME_KINETICENERGY_PARTICLES \ + "kinetic_energy_secondary" /* == OpenVDB grid attribute name. */ /* Guiding object names. */ #define FLUID_NAME_VELT "velT" @@ -349,9 +365,9 @@ enum { #define FLUID_NAME_PHIGUIDEIN "phiGuideIn" #define FLUID_NAME_GUIDEVELC "guidevelC" #define FLUID_NAME_GUIDEVEL_X "x_guidevel" -#define FLUID_NAME_GUIDEVEL_Y "Y_guidevel" +#define FLUID_NAME_GUIDEVEL_Y "y_guidevel" #define FLUID_NAME_GUIDEVEL_Z "z_guidevel" -#define FLUID_NAME_GUIDEVEL "guidevel" +#define FLUID_NAME_GUIDEVEL "velocity_guide" /* Cache file extensions. */ #define FLUID_DOMAIN_EXTENSION_UNI ".uni" @@ -374,7 +390,18 @@ enum { enum { FLUID_DOMAIN_CACHE_REPLAY = 0, FLUID_DOMAIN_CACHE_MODULAR = 1, - FLUID_DOMAIN_CACHE_FINAL = 2, + FLUID_DOMAIN_CACHE_ALL = 2, +}; + +enum { + VDB_COMPRESSION_BLOSC = 0, + VDB_COMPRESSION_ZIP = 1, + VDB_COMPRESSION_NONE = 2, +}; + +enum { + VDB_PRECISION_HALF_FLOAT = 0, + VDB_PRECISION_FULL_FLOAT = 1, }; /* Deprecated values (i.e. all defines and enums below this line up until typedefs). */ @@ -391,12 +418,6 @@ enum { SM_HRES_FULLSAMPLE = 2, }; -enum { - VDB_COMPRESSION_BLOSC = 0, - VDB_COMPRESSION_ZIP = 1, - VDB_COMPRESSION_NONE = 2, -}; - typedef struct FluidDomainVertexVelocity { float vel[3]; } FluidDomainVertexVelocity; @@ -566,7 +587,8 @@ typedef struct FluidDomainSettings { char cache_directory[1024]; char error[64]; /* Bake error description. */ short cache_type; - char _pad8[2]; /* Unused. */ + char cache_id[4]; /* Run-time only */ + char _pad8[6]; /* Time options. */ float dt; @@ -591,17 +613,17 @@ typedef struct FluidDomainSettings { char coba_field; /* Simulation field used for the color mapping. */ char interp_method; + /* OpenVDB cache options. */ + int openvdb_compression; + float clipping; + char openvdb_data_depth; + char _pad9[7]; /* Unused. */ + /* -- Deprecated / unsed options (below). -- */ /* View options. */ int viewsettings; - char _pad9[4]; /* Unused. */ - - /* OpenVDB cache options. */ - int openvdb_comp; - float clipping; - char data_depth; - char _pad10[7]; /* Unused. */ + char _pad10[4]; /* Unused. */ /* Pointcache options. */ /* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 94ba09b2bb8..b4fa791362f 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -557,7 +557,7 @@ static const EnumPropertyItem *rna_Fluid_cachetype_mesh_itemf(bContext *UNUSED(C } static const EnumPropertyItem *rna_Fluid_cachetype_volume_itemf(bContext *UNUSED(C), - PointerRNA *UNUSED(ptr), + PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { @@ -579,11 +579,16 @@ static const EnumPropertyItem *rna_Fluid_cachetype_volume_itemf(bContext *UNUSED RNA_enum_item_add(&item, &totitem, &tmp); # endif - tmp.value = FLUID_DOMAIN_FILE_RAW; - tmp.identifier = "RAW"; - tmp.name = "Raw Cache"; - tmp.description = "Raw file format (.raw)"; - RNA_enum_item_add(&item, &totitem, &tmp); + /* Support for deprecated .raw format. */ + FluidDomainSettings *mds = (FluidDomainSettings *)ptr->data; + if (mds->cache_data_format == FLUID_DOMAIN_FILE_RAW || + mds->cache_noise_format == FLUID_DOMAIN_FILE_RAW) { + tmp.value = FLUID_DOMAIN_FILE_RAW; + tmp.identifier = "RAW"; + tmp.name = "Raw Cache"; + tmp.description = "Raw file format (.raw)"; + RNA_enum_item_add(&item, &totitem, &tmp); + } RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -1058,27 +1063,18 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) }; static EnumPropertyItem cache_types[] = { - {FLUID_DOMAIN_CACHE_REPLAY, - "REPLAY", - 0, - "Replay", - "Use the timeline to bake the scene. Pausing and resuming possible"}, + {FLUID_DOMAIN_CACHE_REPLAY, "REPLAY", 0, "Replay", "Use the timeline to bake the scene"}, {FLUID_DOMAIN_CACHE_MODULAR, "MODULAR", 0, "Modular", - "Bake every stage of the simulation separately. Pausing and resuming possible"}, - {FLUID_DOMAIN_CACHE_FINAL, - "FINAL", - 0, - "Final", - "Bake the entire simulation at once. Only generates the most essential cache files. " - "Pausing and resuming not possible"}, + "Bake every stage of the simulation separately"}, + {FLUID_DOMAIN_CACHE_ALL, "ALL", 0, "All", "Bake all simulation settings at once"}, {0, NULL, 0, NULL, NULL}}; - static const EnumPropertyItem smoke_data_depth_items[] = { - {16, "16", 0, "Float (Half)", "Half float (16 bit data)"}, - {0, "32", 0, "Float (Full)", "Full float (32 bit data)"}, /* default */ + static const EnumPropertyItem fluid_data_depth_items[] = { + {VDB_PRECISION_HALF_FLOAT, "16", 0, "Half", "Half float (16 bit data)"}, + {VDB_PRECISION_FULL_FLOAT, "32", 0, "Full", "Full float (32 bit data)"}, {0, NULL, 0, NULL, NULL}, }; @@ -2072,6 +2068,16 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", "Change the cache type of the simulation"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_domain_reset"); + prop = RNA_def_property(srna, "cache_resumable", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_RESUMABLE_CACHE); + RNA_def_property_ui_text( + prop, + "Resumable", + "Additional data will be saved so that the bake jobs can be resumed after pausing. Because " + "more data will be written to disk it is recommended to avoid enabling this option when " + "baking at high resolutions"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); + prop = RNA_def_property(srna, "cache_directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_maxlength(prop, FILE_MAX); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Fluid_cache_directory_set"); @@ -2320,13 +2326,13 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) /* OpenVDB options */ prop = RNA_def_property(srna, "openvdb_cache_compress_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "openvdb_comp"); + RNA_def_property_enum_sdna(prop, NULL, "openvdb_compression"); RNA_def_property_enum_items(prop, prop_compression_items); - RNA_def_property_ui_text(prop, "Compression", "Compression method to be used"); + RNA_def_property_ui_text(prop, "Compression", "facession method to be used"); - prop = RNA_def_property(srna, "data_depth", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_depth"); - RNA_def_property_enum_items(prop, smoke_data_depth_items); + prop = RNA_def_property(srna, "openvdb_data_depth", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "openvdb_data_depth"); + RNA_def_property_enum_items(prop, fluid_data_depth_items); RNA_def_property_ui_text(prop, "Data Depth", "Bit depth for writing all scalar (including vector) "