Fluid: Refactored Python pointer update function

Use static_cast() where possible and refresh pointers for every frame when in replay mode. The latter is particularly important as this seems to have caused the issue where smoke in the viewport was flickering when loading data from pointers after loading them from disk for the frame before (e.g. when resuming a bake job).
This commit is contained in:
Sebastián Barschkis 2020-07-31 15:27:01 +02:00
parent 227e20f370
commit f2b04302cd
Notes: blender-bot 2023-02-14 09:38:57 +01:00
Referenced by commit 7e64f6cee4, Fluid: Fix for Python pointer update (flickering in smoke/fire issue)
5 changed files with 158 additions and 132 deletions

View File

@ -77,6 +77,7 @@ int manta_get_frame(struct MANTA *fluid);
float manta_get_timestep(struct MANTA *fluid);
void manta_adapt_timestep(struct MANTA *fluid);
bool manta_needs_realloc(struct MANTA *fluid, struct FluidModifierData *fmd);
void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd);
/* Fluid accessors */
size_t manta_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */);

View File

@ -282,7 +282,8 @@ MANTA::MANTA(int *res, FluidModifierData *fmd) : mCurrentID(++solverID)
initColorsHigh();
}
}
updatePointers();
updatePointers(fmd);
}
void MANTA::initDomain(FluidModifierData *fmd)
@ -1823,12 +1824,18 @@ static PyObject *callPythonFunction(string varName, string functionName, bool is
/* Be sure to initialize Python before using it. */
Py_Initialize();
// Get pyobject that holds result value
/* Get pyobject that holds result value. */
if (!manta_main_module) {
PyGILState_Release(gilstate);
return nullptr;
}
/* Ensure that requested variable is present in module - avoid attribute errors later on. */
if (!PyObject_HasAttrString(manta_main_module, varName.c_str())) {
PyGILState_Release(gilstate);
return nullptr;
}
var = PyObject_GetAttrString(manta_main_module, varName.c_str());
if (!var) {
PyGILState_Release(gilstate);
@ -1911,6 +1918,11 @@ static long pyObjectToLong(PyObject *inputObject)
return result;
}
template<class T> static T *getPointer(string pyObjectName, string pyFunctionName)
{
return static_cast<T *>(pyObjectToPointer(callPythonFunction(pyObjectName, pyFunctionName)));
}
int MANTA::getFrame()
{
if (with_debug)
@ -1955,137 +1967,137 @@ void MANTA::adaptTimestep()
runPythonString(pythonCommands);
}
void MANTA::updatePointers()
void MANTA::updatePointers(FluidModifierData *fmd)
{
if (with_debug)
cout << "MANTA::updatePointers()" << endl;
FluidDomainSettings *fds = fmd->domain;
bool liquid = (fds->type == FLUID_DOMAIN_TYPE_LIQUID);
bool smoke = (fds->type == FLUID_DOMAIN_TYPE_GAS);
bool noise = smoke && fds->flags & FLUID_DOMAIN_USE_NOISE;
bool heat = smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
bool colors = smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
bool fire = smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
bool obstacle = fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
bool guiding = fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
bool invel = fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
bool outflow = fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
bool drops = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
bool bubble = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
bool floater = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
bool tracer = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
bool parts = liquid && (drops | bubble | floater | tracer);
bool mesh = liquid && fds->flags & FLUID_DOMAIN_USE_MESH;
bool meshvel = liquid && mesh && fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS;
string func = "getDataPointer";
string funcNodes = "getNodesDataPointer";
string funcTris = "getTrisDataPointer";
string id = to_string(mCurrentID);
string solver = "s" + id;
string parts = "pp" + id;
string snd = "sp" + id;
string mesh = "sm" + id;
string mesh2 = "mesh" + id;
string noise = "sn" + id;
string solver_ext = "_" + solver;
string parts_ext = "_" + parts;
string snd_ext = "_" + snd;
string mesh_ext = "_" + mesh;
string mesh_ext2 = "_" + mesh2;
string noise_ext = "_" + noise;
string s_ext = "_s" + id;
string pp_ext = "_pp" + id;
string snd_ext = "_sp" + id;
string sm_ext = "_sm" + id;
string mesh_ext = "_mesh" + id;
string sn_ext = "_sn" + id;
mFlags = (int *)pyObjectToPointer(callPythonFunction("flags" + solver_ext, func));
mPhiIn = (float *)pyObjectToPointer(callPythonFunction("phiIn" + solver_ext, func));
mPhiStaticIn = (float *)pyObjectToPointer(callPythonFunction("phiSIn" + solver_ext, func));
mVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_vel" + solver_ext, func));
mVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_vel" + solver_ext, func));
mVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_vel" + solver_ext, func));
mForceX = (float *)pyObjectToPointer(callPythonFunction("x_force" + solver_ext, func));
mForceY = (float *)pyObjectToPointer(callPythonFunction("y_force" + solver_ext, func));
mForceZ = (float *)pyObjectToPointer(callPythonFunction("z_force" + solver_ext, func));
mFlags = getPointer<int>("flags" + s_ext, func);
mPhiIn = getPointer<float>("phiIn" + s_ext, func);
mPhiStaticIn = getPointer<float>("phiSIn" + s_ext, func);
mVelocityX = getPointer<float>("x_vel" + s_ext, func);
mVelocityY = getPointer<float>("y_vel" + s_ext, func);
mVelocityZ = getPointer<float>("z_vel" + s_ext, func);
mForceX = getPointer<float>("x_force" + s_ext, func);
mForceY = getPointer<float>("y_force" + s_ext, func);
mForceZ = getPointer<float>("z_force" + s_ext, func);
if (mUsingOutflow) {
mPhiOutIn = (float *)pyObjectToPointer(callPythonFunction("phiOutIn" + solver_ext, func));
mPhiOutStaticIn = (float *)pyObjectToPointer(
callPythonFunction("phiOutSIn" + solver_ext, func));
}
if (mUsingObstacle) {
mPhiObsIn = (float *)pyObjectToPointer(callPythonFunction("phiObsIn" + solver_ext, func));
mPhiObsStaticIn = (float *)pyObjectToPointer(
callPythonFunction("phiObsSIn" + solver_ext, func));
mObVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_obvel" + solver_ext, func));
mObVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_obvel" + solver_ext, func));
mObVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_obvel" + solver_ext, func));
mNumObstacle = (float *)pyObjectToPointer(callPythonFunction("numObs" + solver_ext, func));
}
if (mUsingGuiding) {
mPhiGuideIn = (float *)pyObjectToPointer(callPythonFunction("phiGuideIn" + solver_ext, func));
mGuideVelocityX = (float *)pyObjectToPointer(
callPythonFunction("x_guidevel" + solver_ext, func));
mGuideVelocityY = (float *)pyObjectToPointer(
callPythonFunction("y_guidevel" + solver_ext, func));
mGuideVelocityZ = (float *)pyObjectToPointer(
callPythonFunction("z_guidevel" + solver_ext, func));
mNumGuide = (float *)pyObjectToPointer(callPythonFunction("numGuides" + solver_ext, func));
}
if (mUsingInvel) {
mInVelocityX = (float *)pyObjectToPointer(callPythonFunction("x_invel" + solver_ext, func));
mInVelocityY = (float *)pyObjectToPointer(callPythonFunction("y_invel" + solver_ext, func));
mInVelocityZ = (float *)pyObjectToPointer(callPythonFunction("z_invel" + solver_ext, func));
}
if (mUsingSmoke) {
mDensity = (float *)pyObjectToPointer(callPythonFunction("density" + solver_ext, func));
mDensityIn = (float *)pyObjectToPointer(callPythonFunction("densityIn" + solver_ext, func));
mShadow = (float *)pyObjectToPointer(callPythonFunction("shadow" + solver_ext, func));
mEmissionIn = (float *)pyObjectToPointer(callPythonFunction("emissionIn" + solver_ext, func));
}
if (mUsingSmoke && mUsingHeat) {
mHeat = (float *)pyObjectToPointer(callPythonFunction("heat" + solver_ext, func));
mHeatIn = (float *)pyObjectToPointer(callPythonFunction("heatIn" + solver_ext, func));
}
if (mUsingSmoke && mUsingFire) {
mFlame = (float *)pyObjectToPointer(callPythonFunction("flame" + solver_ext, func));
mFuel = (float *)pyObjectToPointer(callPythonFunction("fuel" + solver_ext, func));
mReact = (float *)pyObjectToPointer(callPythonFunction("react" + solver_ext, func));
mFuelIn = (float *)pyObjectToPointer(callPythonFunction("fuelIn" + solver_ext, func));
mReactIn = (float *)pyObjectToPointer(callPythonFunction("reactIn" + solver_ext, func));
}
if (mUsingSmoke && mUsingColors) {
mColorR = (float *)pyObjectToPointer(callPythonFunction("color_r" + solver_ext, func));
mColorG = (float *)pyObjectToPointer(callPythonFunction("color_g" + solver_ext, func));
mColorB = (float *)pyObjectToPointer(callPythonFunction("color_b" + solver_ext, func));
mColorRIn = (float *)pyObjectToPointer(callPythonFunction("color_r_in" + solver_ext, func));
mColorGIn = (float *)pyObjectToPointer(callPythonFunction("color_g_in" + solver_ext, func));
mColorBIn = (float *)pyObjectToPointer(callPythonFunction("color_b_in" + solver_ext, func));
}
if (mUsingSmoke && mUsingNoise) {
mDensityHigh = (float *)pyObjectToPointer(callPythonFunction("density" + noise_ext, func));
mTextureU = (float *)pyObjectToPointer(callPythonFunction("texture_u" + solver_ext, func));
mTextureV = (float *)pyObjectToPointer(callPythonFunction("texture_v" + solver_ext, func));
mTextureW = (float *)pyObjectToPointer(callPythonFunction("texture_w" + solver_ext, func));
mTextureU2 = (float *)pyObjectToPointer(callPythonFunction("texture_u2" + solver_ext, func));
mTextureV2 = (float *)pyObjectToPointer(callPythonFunction("texture_v2" + solver_ext, func));
mTextureW2 = (float *)pyObjectToPointer(callPythonFunction("texture_w2" + solver_ext, func));
}
if (mUsingSmoke && mUsingNoise && mUsingFire) {
mFlameHigh = (float *)pyObjectToPointer(callPythonFunction("flame" + noise_ext, func));
mFuelHigh = (float *)pyObjectToPointer(callPythonFunction("fuel" + noise_ext, func));
mReactHigh = (float *)pyObjectToPointer(callPythonFunction("react" + noise_ext, func));
}
if (mUsingSmoke && mUsingNoise && mUsingColors) {
mColorRHigh = (float *)pyObjectToPointer(callPythonFunction("color_r" + noise_ext, func));
mColorGHigh = (float *)pyObjectToPointer(callPythonFunction("color_g" + noise_ext, func));
mColorBHigh = (float *)pyObjectToPointer(callPythonFunction("color_b" + noise_ext, func));
}
if (mUsingLiquid) {
mPhi = (float *)pyObjectToPointer(callPythonFunction("phi" + solver_ext, func));
mFlipParticleData = (vector<pData> *)pyObjectToPointer(
callPythonFunction("pp" + solver_ext, func));
mFlipParticleVelocity = (vector<pVel> *)pyObjectToPointer(
callPythonFunction("pVel" + parts_ext, func));
}
if (mUsingLiquid && mUsingMesh) {
mMeshNodes = (vector<Node> *)pyObjectToPointer(
callPythonFunction("mesh" + mesh_ext, funcNodes));
mMeshTriangles = (vector<Triangle> *)pyObjectToPointer(
callPythonFunction("mesh" + mesh_ext, funcTris));
}
if (mUsingLiquid && mUsingMVel) {
mMeshVelocities = (vector<pVel> *)pyObjectToPointer(
callPythonFunction("mVel" + mesh_ext2, func));
}
if (mUsingLiquid && (mUsingDrops | mUsingBubbles | mUsingFloats | mUsingTracers)) {
mSndParticleData = (vector<pData> *)pyObjectToPointer(
callPythonFunction("ppSnd" + snd_ext, func));
mSndParticleVelocity = (vector<pVel> *)pyObjectToPointer(
callPythonFunction("pVelSnd" + parts_ext, func));
mSndParticleLife = (vector<float> *)pyObjectToPointer(
callPythonFunction("pLifeSnd" + parts_ext, func));
}
/* Outflow. */
mPhiOutIn = (outflow) ? getPointer<float>("phiOutIn" + s_ext, func) : nullptr;
mPhiOutStaticIn = (outflow) ? getPointer<float>("phiOutSIn" + s_ext, func) : nullptr;
/* Obstacles. */
mPhiObsIn = (obstacle) ? getPointer<float>("phiObsIn" + s_ext, func) : nullptr;
mPhiObsStaticIn = (obstacle) ? getPointer<float>("phiObsSIn" + s_ext, func) : nullptr;
mObVelocityX = (obstacle) ? getPointer<float>("x_obvel" + s_ext, func) : nullptr;
mObVelocityY = (obstacle) ? getPointer<float>("y_obvel" + s_ext, func) : nullptr;
mObVelocityZ = (obstacle) ? getPointer<float>("z_obvel" + s_ext, func) : nullptr;
mNumObstacle = (obstacle) ? getPointer<float>("numObs" + s_ext, func) : nullptr;
/* Guiding. */
mPhiGuideIn = (guiding) ? getPointer<float>("phiGuideIn" + s_ext, func) : nullptr;
mGuideVelocityX = (guiding) ? getPointer<float>("x_guidevel" + s_ext, func) : nullptr;
mGuideVelocityY = (guiding) ? getPointer<float>("y_guidevel" + s_ext, func) : nullptr;
mGuideVelocityZ = (guiding) ? getPointer<float>("z_guidevel" + s_ext, func) : nullptr;
mNumGuide = (guiding) ? getPointer<float>("numGuides" + s_ext, func) : nullptr;
/* Initial velocities. */
mInVelocityX = (invel) ? getPointer<float>("x_invel" + s_ext, func) : nullptr;
mInVelocityY = (invel) ? getPointer<float>("y_invel" + s_ext, func) : nullptr;
mInVelocityZ = (invel) ? getPointer<float>("z_invel" + s_ext, func) : nullptr;
/* Smoke. */
mDensity = (smoke) ? getPointer<float>("density" + s_ext, func) : nullptr;
mDensityIn = (smoke) ? getPointer<float>("densityIn" + s_ext, func) : nullptr;
mShadow = (smoke) ? getPointer<float>("shadow" + s_ext, func) : nullptr;
mEmissionIn = (smoke) ? getPointer<float>("emissionIn" + s_ext, func) : nullptr;
/* Heat. */
mHeat = (heat) ? getPointer<float>("heat" + s_ext, func) : nullptr;
mHeatIn = (heat) ? getPointer<float>("heatIn" + s_ext, func) : nullptr;
/* Fire. */
mFlame = (fire) ? getPointer<float>("flame" + s_ext, func) : nullptr;
mFuel = (fire) ? getPointer<float>("fuel" + s_ext, func) : nullptr;
mReact = (fire) ? getPointer<float>("react" + s_ext, func) : nullptr;
mFuelIn = (fire) ? getPointer<float>("fuelIn" + s_ext, func) : nullptr;
mReactIn = (fire) ? getPointer<float>("reactIn" + s_ext, func) : nullptr;
/* Colors. */
mColorR = (colors) ? getPointer<float>("color_r" + s_ext, func) : nullptr;
mColorG = (colors) ? getPointer<float>("color_g" + s_ext, func) : nullptr;
mColorB = (colors) ? getPointer<float>("color_b" + s_ext, func) : nullptr;
mColorRIn = (colors) ? getPointer<float>("color_r_in" + s_ext, func) : nullptr;
mColorGIn = (colors) ? getPointer<float>("color_g_in" + s_ext, func) : nullptr;
mColorBIn = (colors) ? getPointer<float>("color_b_in" + s_ext, func) : nullptr;
/* Noise. */
mDensityHigh = (noise) ? getPointer<float>("density" + sn_ext, func) : nullptr;
mTextureU = (noise) ? getPointer<float>("texture_u" + s_ext, func) : nullptr;
mTextureV = (noise) ? getPointer<float>("texture_v" + s_ext, func) : nullptr;
mTextureW = (noise) ? getPointer<float>("texture_w" + s_ext, func) : nullptr;
mTextureU2 = (noise) ? getPointer<float>("texture_u2" + s_ext, func) : nullptr;
mTextureV2 = (noise) ? getPointer<float>("texture_v2" + s_ext, func) : nullptr;
mTextureW2 = (noise) ? getPointer<float>("texture_w2" + s_ext, func) : nullptr;
/* Fire with noise. */
mFlameHigh = (noise && fire) ? getPointer<float>("flame" + sn_ext, func) : nullptr;
mFuelHigh = (noise && fire) ? getPointer<float>("fuel" + sn_ext, func) : nullptr;
mReactHigh = (noise && fire) ? getPointer<float>("react" + sn_ext, func) : nullptr;
/* Colors with noise. */
mColorRHigh = (noise && colors) ? getPointer<float>("color_r" + sn_ext, func) : nullptr;
mColorGHigh = (noise && colors) ? getPointer<float>("color_g" + sn_ext, func) : nullptr;
mColorBHigh = (noise && colors) ? getPointer<float>("color_b" + sn_ext, func) : nullptr;
/* Liquid. */
mPhi = (liquid) ? getPointer<float>("phi" + s_ext, func) : nullptr;
mFlipParticleData = (liquid) ? getPointer<vector<pData>>("pp" + s_ext, func) : nullptr;
mFlipParticleVelocity = (liquid) ? getPointer<vector<pVel>>("pVel" + pp_ext, func) : nullptr;
/* Mesh. */
mMeshNodes = (mesh) ? getPointer<vector<Node>>("mesh" + sm_ext, funcNodes) : nullptr;
mMeshTriangles = (mesh) ? getPointer<vector<Triangle>>("mesh" + sm_ext, funcTris) : nullptr;
/* Mesh velocities. */
mMeshVelocities = (meshvel) ? getPointer<vector<pVel>>("mVel" + mesh_ext, func) : nullptr;
/* Secondary particles. */
mSndParticleData = (parts) ? getPointer<vector<pData>>("ppSnd" + snd_ext, func) : nullptr;
mSndParticleVelocity = (parts) ? getPointer<vector<pVel>>("pVelSnd" + pp_ext, func) : nullptr;
mSndParticleLife = (parts) ? getPointer<vector<float>>("pLifeSnd" + pp_ext, func) : nullptr;
mFlipFromFile = false;
mMeshFromFile = false;

View File

@ -81,7 +81,7 @@ struct MANTA {
void initLiquidSndParts(FluidModifierData *fmd = NULL);
// Pointer transfer: Mantaflow -> Blender
void updatePointers();
void updatePointers(FluidModifierData *fmd);
// Write cache
bool writeConfiguration(FluidModifierData *fmd, int framenr);

View File

@ -42,28 +42,28 @@ void manta_ensure_obstacle(MANTA *fluid, struct FluidModifierData *fmd)
if (!fluid)
return;
fluid->initObstacle(fmd);
fluid->updatePointers();
fluid->updatePointers(fmd);
}
void manta_ensure_guiding(MANTA *fluid, struct FluidModifierData *fmd)
{
if (!fluid)
return;
fluid->initGuiding(fmd);
fluid->updatePointers();
fluid->updatePointers(fmd);
}
void manta_ensure_invelocity(MANTA *fluid, struct FluidModifierData *fmd)
{
if (!fluid)
return;
fluid->initInVelocity(fmd);
fluid->updatePointers();
fluid->updatePointers(fmd);
}
void manta_ensure_outflow(MANTA *fluid, struct FluidModifierData *fmd)
{
if (!fluid)
return;
fluid->initOutflow(fmd);
fluid->updatePointers();
fluid->updatePointers(fmd);
}
int manta_write_config(MANTA *fluid, FluidModifierData *fmd, int framenr)
@ -229,11 +229,18 @@ void manta_adapt_timestep(MANTA *fluid)
bool manta_needs_realloc(MANTA *fluid, FluidModifierData *fmd)
{
if (!fluid)
if (!fluid || !fmd)
return false;
return fluid->needsRealloc(fmd);
}
void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd)
{
if (!fluid || !fmd)
return;
fluid->updatePointers(fmd);
}
/* Fluid accessors */
size_t manta_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
{
@ -445,7 +452,7 @@ void manta_smoke_ensure_heat(MANTA *smoke, struct FluidModifierData *fmd)
{
if (smoke) {
smoke->initHeat(fmd);
smoke->updatePointers();
smoke->updatePointers(fmd);
}
}
@ -456,7 +463,7 @@ void manta_smoke_ensure_fire(MANTA *smoke, struct FluidModifierData *fmd)
if (smoke->usingNoise()) {
smoke->initFireHigh(fmd);
}
smoke->updatePointers();
smoke->updatePointers(fmd);
}
}
@ -467,7 +474,7 @@ void manta_smoke_ensure_colors(MANTA *smoke, struct FluidModifierData *fmd)
if (smoke->usingNoise()) {
smoke->initColorsHigh(fmd);
}
smoke->updatePointers();
smoke->updatePointers(fmd);
}
}
@ -649,7 +656,7 @@ void manta_liquid_ensure_sndparts(MANTA *liquid, struct FluidModifierData *fmd)
{
if (liquid) {
liquid->initLiquidSndParts(fmd);
liquid->updatePointers();
liquid->updatePointers(fmd);
}
}

View File

@ -3617,6 +3617,12 @@ static int manta_step(
fds->time_per_frame = time_per_frame;
fds->time_total = time_total;
}
/* Replay mode does not lock the UI. Ensure that fluid data is always up to date. */
if (mode_replay) {
manta_update_pointers(fds->fluid, fmd);
}
/* Total time must not exceed framecount times framelength. Correct tiny errors here. */
CLAMP(fds->time_total, fds->time_total, time_total_old + fds->frame_length);