Blender V5.0
MANTA_main.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <fstream>
11#include <iostream>
12#include <sstream>
13#include <zlib.h>
14
15#include <Python.h>
16
17#include <manta.h>
18
19#include "MANTA_main.h"
20#include "fluid_script.h"
21#include "liquid_script.h"
22#include "smoke_script.h"
23
24#include "BLI_fileops.h"
25#include "BLI_path_utils.hh"
26#include "BLI_utildefines.h"
27
28#include "DNA_fluid_types.h"
29#include "DNA_modifier_types.h"
30
31using std::cerr;
32using std::cout;
33using std::endl;
34using std::ifstream;
35using std::istringstream;
36using std::ofstream;
37using std::ostringstream;
38using std::to_string;
39
40atomic<int> MANTA::solverID(0);
42
44 : mCurrentID(++solverID), mMaxRes(fmd->domain->maxres)
45{
46 if (with_debug) {
47 cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " << res[2]
48 << ")" << endl;
49 }
50
51 FluidDomainSettings *fds = fmd->domain;
52 fds->fluid = this;
53
54 mUsingLiquid = (fds->type == FLUID_DOMAIN_TYPE_LIQUID);
55 mUsingSmoke = (fds->type == FLUID_DOMAIN_TYPE_GAS);
56 mUsingNoise = (fds->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke;
57 mUsingFractions = (fds->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid;
58 mUsingMesh = (fds->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
59 mUsingDiffusion = (fds->flags & FLUID_DOMAIN_USE_DIFFUSION) && mUsingLiquid;
60 mUsingViscosity = (fds->flags & FLUID_DOMAIN_USE_VISCOSITY) && mUsingLiquid;
61 mUsingMVel = (fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
62 mUsingGuiding = (fds->flags & FLUID_DOMAIN_USE_GUIDE);
63 mUsingDrops = (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid;
64 mUsingBubbles = (fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid;
65 mUsingFloats = (fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid;
66 mUsingTracers = (fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid;
67
68 mUsingHeat = (fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke;
69 mUsingFire = (fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke;
70 mUsingColors = (fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke;
71 mUsingObstacle = (fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE);
72 mUsingInvel = (fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
73 mUsingOutflow = (fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
74
75 /* Simulation constants */
76 mResX = res[0]; /* Current size of domain (will adjust with adaptive domain). */
77 mResY = res[1];
78 mResZ = res[2];
79 mTotalCells = mResX * mResY * mResZ;
80 mResGuiding = fds->res;
81
82 /* Smoke low res grids. */
83 mDensity = nullptr;
84 mShadow = nullptr;
85 mHeat = nullptr;
86 mVelocityX = nullptr;
87 mVelocityY = nullptr;
88 mVelocityZ = nullptr;
89 mForceX = nullptr;
90 mForceY = nullptr;
91 mForceZ = nullptr;
92 mFlame = nullptr;
93 mFuel = nullptr;
94 mReact = nullptr;
95 mColorR = nullptr;
96 mColorG = nullptr;
97 mColorB = nullptr;
98 mFlags = nullptr;
99 mDensityIn = nullptr;
100 mHeatIn = nullptr;
101 mColorRIn = nullptr;
102 mColorGIn = nullptr;
103 mColorBIn = nullptr;
104 mFuelIn = nullptr;
105 mReactIn = nullptr;
106 mEmissionIn = nullptr;
107 mPressure = nullptr;
108
109 /* Smoke high res grids. */
110 mDensityHigh = nullptr;
111 mFlameHigh = nullptr;
112 mFuelHigh = nullptr;
113 mReactHigh = nullptr;
114 mColorRHigh = nullptr;
115 mColorGHigh = nullptr;
116 mColorBHigh = nullptr;
117 mTextureU = nullptr;
118 mTextureV = nullptr;
119 mTextureW = nullptr;
120 mTextureU2 = nullptr;
121 mTextureV2 = nullptr;
122 mTextureW2 = nullptr;
123
124 /* Fluid low res grids. */
125 mPhiIn = nullptr;
126 mPhiStaticIn = nullptr;
127 mPhiOutIn = nullptr;
128 mPhiOutStaticIn = nullptr;
129 mPhi = nullptr;
130
131 /* Mesh. */
132 mMeshNodes = nullptr;
133 mMeshTriangles = nullptr;
134 mMeshVelocities = nullptr;
135
136 /* Fluid obstacle. */
137 mPhiObsIn = nullptr;
138 mPhiObsStaticIn = nullptr;
139 mNumObstacle = nullptr;
140 mObVelocityX = nullptr;
141 mObVelocityY = nullptr;
142 mObVelocityZ = nullptr;
143
144 /* Fluid guiding. */
145 mPhiGuideIn = nullptr;
146 mNumGuide = nullptr;
147 mGuideVelocityX = nullptr;
148 mGuideVelocityY = nullptr;
149 mGuideVelocityZ = nullptr;
150
151 /* Fluid initial velocity. */
152 mInVelocityX = nullptr;
153 mInVelocityY = nullptr;
154 mInVelocityZ = nullptr;
155
156 /* Secondary particles. */
157 mFlipParticleData = nullptr;
158 mFlipParticleVelocity = nullptr;
159 mParticleData = nullptr;
160 mParticleVelocity = nullptr;
161 mParticleLife = nullptr;
162
163 /* Cache read success indicators. */
164 mFlipFromFile = false;
165 mMeshFromFile = false;
166 mParticlesFromFile = false;
167
168 /* Setup Mantaflow in Python. */
169 initializeMantaflow();
170
171 /* Initializa RNA map with values that Python will need. */
172 initializeRNAMap(fmd);
173
174 bool initSuccess = true;
175 /* Initialize Mantaflow variables in Python. */
176 /* Liquid. */
177 if (mUsingLiquid) {
178 initSuccess &= initDomain();
179 initSuccess &= initLiquid();
180 if (mUsingObstacle) {
181 initSuccess &= initObstacle();
182 }
183 if (mUsingInvel) {
184 initSuccess &= initInVelocity();
185 }
186 if (mUsingOutflow) {
187 initSuccess &= initOutflow();
188 }
189
190 if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) {
191 mUpresParticle = fds->particle_scale;
192 mResXParticle = mUpresParticle * mResX;
193 mResYParticle = mUpresParticle * mResY;
194 mResZParticle = mUpresParticle * mResZ;
195 mTotalCellsParticles = mResXParticle * mResYParticle * mResZParticle;
196
197 initSuccess &= initSndParts();
198 initSuccess &= initLiquidSndParts();
199 }
200
201 if (mUsingMesh) {
202 mUpresMesh = fds->mesh_scale;
203 mResXMesh = mUpresMesh * mResX;
204 mResYMesh = mUpresMesh * mResY;
205 mResZMesh = mUpresMesh * mResZ;
206 mTotalCellsMesh = mResXMesh * mResYMesh * mResZMesh;
207
208 /* Initialize Mantaflow variables in Python. */
209 initSuccess &= initMesh();
210 initSuccess &= initLiquidMesh();
211 }
212
213 if (mUsingViscosity) {
214 initSuccess &= initLiquidViscosity();
215 }
216
217 if (mUsingDiffusion) {
218 initSuccess &= initCurvature();
219 }
220
221 if (mUsingGuiding) {
222 mResGuiding = (fds->guide_parent) ? fds->guide_res : fds->res;
223 initSuccess &= initGuiding();
224 }
225 if (mUsingFractions) {
226 initSuccess &= initFractions();
227 }
228 }
229
230 /* Smoke. */
231 if (mUsingSmoke) {
232 initSuccess &= initDomain();
233 initSuccess &= initSmoke();
234 if (mUsingHeat) {
235 initSuccess &= initHeat();
236 }
237 if (mUsingFire) {
238 initSuccess &= initFire();
239 }
240 if (mUsingColors) {
241 initSuccess &= initColors();
242 }
243 if (mUsingObstacle) {
244 initSuccess &= initObstacle();
245 }
246 if (mUsingInvel) {
247 initSuccess &= initInVelocity();
248 }
249 if (mUsingOutflow) {
250 initSuccess &= initOutflow();
251 }
252
253 if (mUsingGuiding) {
254 mResGuiding = (fds->guide_parent) ? fds->guide_res : fds->res;
255 initSuccess &= initGuiding();
256 }
257
258 if (mUsingNoise) {
259 int amplify = fds->noise_scale;
260 mResXNoise = amplify * mResX;
261 mResYNoise = amplify * mResY;
262 mResZNoise = amplify * mResZ;
263 mTotalCellsHigh = mResXNoise * mResYNoise * mResZNoise;
264
265 /* Initialize Mantaflow variables in Python. */
266 initSuccess &= initNoise();
267 initSuccess &= initSmokeNoise();
268 if (mUsingFire) {
269 initSuccess &= initFireHigh();
270 }
271 if (mUsingColors) {
272 initSuccess &= initColorsHigh();
273 }
274 }
275 }
276 /* All requested initializations must not fail in constructor. */
277 BLI_assert(initSuccess);
278 (void)initSuccess; /* Ignored in release. */
279
280 updatePointers(fmd);
281}
282
283bool MANTA::initDomain(FluidModifierData *fmd)
284{
285 /* Vector will hold all python commands that are to be executed. */
286 vector<string> pythonCommands;
287
288 /* Set manta debug level first. */
289 pythonCommands.push_back(manta_import + manta_debuglevel);
290
291 ostringstream ss;
292 ss << "set_manta_debuglevel(" << with_debug << ")";
293 pythonCommands.push_back(ss.str());
294
295 /* Now init basic fluid domain. */
296 string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper +
297 fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise +
298 fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding +
299 fluid_file_import + fluid_file_export + fluid_pre_step + fluid_post_step +
300 fluid_adapt_time_step + fluid_time_stepping;
301 string finalString = parseScript(tmpString, fmd);
302 pythonCommands.push_back(finalString);
303 return runPythonString(pythonCommands);
304}
305
306bool MANTA::initNoise(FluidModifierData *fmd)
307{
308 vector<string> pythonCommands;
309 string tmpString = fluid_variables_noise + fluid_solver_noise;
310 string finalString = parseScript(tmpString, fmd);
311 pythonCommands.push_back(finalString);
312
313 return runPythonString(pythonCommands);
314}
315
316bool MANTA::initSmoke(FluidModifierData *fmd)
317{
318 vector<string> pythonCommands;
319 string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data +
320 smoke_load_data + smoke_step;
321 string finalString = parseScript(tmpString, fmd);
322 pythonCommands.push_back(finalString);
323
324 return runPythonString(pythonCommands);
325}
326
327bool MANTA::initSmokeNoise(FluidModifierData *fmd)
328{
329 vector<string> pythonCommands;
331 smoke_save_noise + smoke_load_noise + smoke_step_noise;
332 string finalString = parseScript(tmpString, fmd);
333 pythonCommands.push_back(finalString);
334
335 mUsingNoise = true;
336 return runPythonString(pythonCommands);
337}
338
340{
341 if (!mHeat) {
342 vector<string> pythonCommands;
343 string tmpString = smoke_alloc_heat + smoke_with_heat;
344 string finalString = parseScript(tmpString, fmd);
345 pythonCommands.push_back(finalString);
346
347 mUsingHeat = true;
348 return runPythonString(pythonCommands);
349 }
350 return false;
351}
352
354{
355 if (!mFuel) {
356 vector<string> pythonCommands;
357 string tmpString = smoke_alloc_fire + smoke_with_fire;
358 string finalString = parseScript(tmpString, fmd);
359 pythonCommands.push_back(finalString);
360
361 mUsingFire = true;
362 return runPythonString(pythonCommands);
363 }
364 return false;
365}
366
368{
369 if (!mFuelHigh) {
370 vector<string> pythonCommands;
371 string tmpString = smoke_alloc_fire_noise + smoke_with_fire;
372 string finalString = parseScript(tmpString, fmd);
373 pythonCommands.push_back(finalString);
374
375 mUsingFire = true;
376 return runPythonString(pythonCommands);
377 }
378 return false;
379}
380
382{
383 if (!mColorR) {
384 vector<string> pythonCommands;
386 string finalString = parseScript(tmpString, fmd);
387 pythonCommands.push_back(finalString);
388
389 mUsingColors = true;
390 return runPythonString(pythonCommands);
391 }
392 return false;
393}
394
396{
397 if (!mColorRHigh) {
398 vector<string> pythonCommands;
400 string finalString = parseScript(tmpString, fmd);
401 pythonCommands.push_back(finalString);
402
403 mUsingColors = true;
404 return runPythonString(pythonCommands);
405 }
406 return false;
407}
408
410{
411 if (!mPhiIn) {
412 vector<string> pythonCommands;
413 string tmpString = liquid_variables + liquid_alloc + liquid_init_phi + liquid_save_data +
414 liquid_load_data + liquid_adaptive_step + liquid_step;
415 string finalString = parseScript(tmpString, fmd);
416 pythonCommands.push_back(finalString);
417
418 mUsingLiquid = true;
419 return runPythonString(pythonCommands);
420 }
421 return false;
422}
423
424bool MANTA::initMesh(FluidModifierData *fmd)
425{
426 vector<string> pythonCommands;
427 string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh;
428 string finalString = parseScript(tmpString, fmd);
429 pythonCommands.push_back(finalString);
430
431 mUsingMesh = true;
432 return runPythonString(pythonCommands);
433}
434
436{
437 vector<string> pythonCommands;
438 string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh;
439 string finalString = parseScript(tmpString, fmd);
440 pythonCommands.push_back(finalString);
441
442 mUsingMesh = true;
443 return runPythonString(pythonCommands);
444}
445
447{
448 vector<string> pythonCommands;
450 string finalString = parseScript(tmpString, fmd);
451 pythonCommands.push_back(finalString);
452
453 mUsingViscosity = true;
454 return runPythonString(pythonCommands);
455}
456
458{
459 std::vector<std::string> pythonCommands;
460 std::string finalString = parseScript(liquid_alloc_curvature, fmd);
461 pythonCommands.push_back(finalString);
462
463 mUsingDiffusion = true;
464 return runPythonString(pythonCommands);
465}
466
468{
469 if (!mPhiObsIn) {
470 vector<string> pythonCommands;
471 string tmpString = fluid_alloc_obstacle + fluid_with_obstacle;
472 string finalString = parseScript(tmpString, fmd);
473 pythonCommands.push_back(finalString);
474
475 return (mUsingObstacle = runPythonString(pythonCommands));
476 }
477 return false;
478}
479
481{
482 if (!mPhiGuideIn) {
483 vector<string> pythonCommands;
484 string tmpString = fluid_variables_guiding + fluid_solver_guiding + fluid_alloc_guiding +
485 fluid_save_guiding + fluid_load_vel + fluid_load_guiding;
486 string finalString = parseScript(tmpString, fmd);
487 pythonCommands.push_back(finalString);
488
489 return (mUsingGuiding = runPythonString(pythonCommands));
490 }
491 return false;
492}
493
495{
496 vector<string> pythonCommands;
497 string tmpString = fluid_alloc_fractions + fluid_with_fractions;
498 string finalString = parseScript(tmpString, fmd);
499 pythonCommands.push_back(finalString);
500
501 return (mUsingFractions = runPythonString(pythonCommands));
502}
503
505{
506 if (!mInVelocityX) {
507 vector<string> pythonCommands;
508 string tmpString = fluid_alloc_invel + fluid_with_invel;
509 string finalString = parseScript(tmpString, fmd);
510 pythonCommands.push_back(finalString);
511
512 return (mUsingInvel = runPythonString(pythonCommands));
513 }
514 return false;
515}
516
518{
519 if (!mPhiOutIn) {
520 vector<string> pythonCommands;
521 string tmpString = fluid_alloc_outflow + fluid_with_outflow;
522 string finalString = parseScript(tmpString, fmd);
523 pythonCommands.push_back(finalString);
524
525 return (mUsingOutflow = runPythonString(pythonCommands));
526 }
527 return false;
528}
529
531{
532 vector<string> pythonCommands;
534 string finalString = parseScript(tmpString, fmd);
535 pythonCommands.push_back(finalString);
536
537 return runPythonString(pythonCommands);
538}
539
541{
542 if (!mParticleData) {
543 vector<string> pythonCommands;
545 liquid_step_particles + fluid_with_sndparts + liquid_load_particles +
546 liquid_save_particles;
547 string finalString = parseScript(tmpString, fmd);
548 pythonCommands.push_back(finalString);
549
550 return runPythonString(pythonCommands);
551 }
552 return false;
553}
554
556{
557 if (with_debug) {
558 cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " << mResZ
559 << ")" << endl;
560 }
561
562 /* Destruction string for Python. */
563 string tmpString;
564 vector<string> pythonCommands;
565 bool result = false;
566
567 tmpString += manta_import;
568 tmpString += fluid_delete_all;
569
570 /* Initializa RNA map with values that Python will need. */
571 initializeRNAMap();
572
573 /* Leave out fmd argument in parseScript since only looking up IDs. */
574 string finalString = parseScript(tmpString);
575 pythonCommands.push_back(finalString);
576 result = runPythonString(pythonCommands);
577
578 /* WARNING: this causes crash on exit in the `cycles_volume_cpu/smoke_color` test,
579 * freeing a single modifier ends up clearing the shared module.
580 * For this to be handled properly there would need to be a initialize/free
581 * function for global data. */
582#if 0
583 MANTA::terminateMantaflow();
584#endif
585
588}
589
596static PyObject *manta_python_main_module_create(const char *filename)
597{
598 PyObject *builtins = PyEval_GetBuiltins();
599 PyObject *mod_main = PyModule_New("__main__");
600 PyModule_AddStringConstant(mod_main, "__name__", "__main__");
601 if (filename) {
602 /* __file__ mainly for nice UI'ness
603 * NOTE: this won't map to a real file when executing text-blocks and buttons. */
604 PyModule_AddObject(mod_main, "__file__", PyUnicode_InternFromString(filename));
605 }
606 PyModule_AddObjectRef(mod_main, "__builtins__", builtins);
607 return mod_main;
608}
609
610static void manta_python_main_module_activate(PyObject *mod_main)
611{
612 PyObject *modules = PyImport_GetModuleDict();
613 PyObject *main_mod_cmp = PyDict_GetItemString(modules, "__main__");
614 if (mod_main == main_mod_cmp) {
615 return;
616 }
617 /* NOTE: we could remove the reference to `mod_main` here, but as it's know to be removed
618 * accept that there is temporarily an extra reference. */
619 PyDict_SetItemString(modules, "__main__", mod_main);
620}
621
622static void manta_python_main_module_backup(PyObject **r_main_mod)
623{
624 PyObject *modules = PyImport_GetModuleDict();
625 *r_main_mod = PyDict_GetItemString(modules, "__main__");
626 Py_XINCREF(*r_main_mod); /* don't free */
627}
628
629static void manta_python_main_module_restore(PyObject *main_mod)
630{
631 PyObject *modules = PyImport_GetModuleDict();
632 PyDict_SetItemString(modules, "__main__", main_mod);
633 Py_XDECREF(main_mod);
634}
635
643static PyObject *manta_main_module = nullptr;
644
646{
647 if (manta_main_module) {
649 manta_main_module = nullptr;
650 }
651}
652
654{
655 if (!manta_main_module) {
657 }
658 return manta_main_module;
659}
660
661bool MANTA::runPythonString(vector<string> commands)
662{
663 bool success = true;
664 PyGILState_STATE gilstate = PyGILState_Ensure();
665
666 /* Temporarily set `sys.modules["__main__"]` as some Python modules expect this. */
667 PyObject *main_mod_backup;
668 manta_python_main_module_backup(&main_mod_backup);
669
670 /* If we never want to run this when the module isn't initialize,
671 * assign with `manta_python_main_module_ensure()`. */
672 BLI_assert(manta_main_module != nullptr);
674
675 for (vector<string>::iterator it = commands.begin(); it != commands.end(); ++it) {
676 string command = *it;
677
678 PyObject *globals_dict = PyModule_GetDict(manta_main_module);
679 PyObject *return_value = PyRun_String(
680 command.c_str(), Py_file_input, globals_dict, globals_dict);
681
682 if (return_value == nullptr) {
683 success = false;
684 if (PyErr_Occurred()) {
685 PyErr_Print();
686 }
687 }
688 else {
689 Py_DECREF(return_value);
690 }
691 }
692
693 manta_python_main_module_restore(main_mod_backup);
694
695 PyGILState_Release(gilstate);
696
697 BLI_assert(success);
698 return success;
699}
700
701void MANTA::initializeMantaflow()
702{
703 if (with_debug) {
704 cout << "Fluid: Initializing Mantaflow framework" << endl;
705 }
706
707 string filename = "manta_scene_" + to_string(mCurrentID) + ".py";
708 vector<string> fill = vector<string>();
709
710 /* Initialize extension classes and wrappers. */
711 srand(0);
712 PyGILState_STATE gilstate = PyGILState_Ensure();
713
715 PyObject *globals_dict = PyModule_GetDict(manta_main_module);
716 Pb::setup(false, filename, fill, globals_dict); /* Namespace from Mantaflow (registry). */
717 PyGILState_Release(gilstate);
718}
719
720void MANTA::terminateMantaflow()
721{
722 if (with_debug) {
723 cout << "Fluid: Releasing Mantaflow framework" << endl;
724 }
725
726 PyGILState_STATE gilstate = PyGILState_Ensure();
727 Pb::finalize(false); /* Namespace from Mantaflow (registry). */
729 PyGILState_Release(gilstate);
730}
731
732static string getCacheFileEnding(char cache_format)
733{
734 if (MANTA::with_debug) {
735 cout << "MANTA::getCacheFileEnding()" << endl;
736 }
737
738 switch (cache_format) {
749 default:
750 cerr << "Fluid Error -- Could not find file extension. Using default file extension."
751 << endl;
753 }
754}
755
756static string getBooleanString(int value)
757{
758 return (value) ? "True" : "False";
759}
760
761void MANTA::initializeRNAMap(FluidModifierData *fmd)
762{
763 if (with_debug) {
764 cout << "MANTA::initializeRNAMap()" << endl;
765 }
766
767 mRNAMap["ID"] = to_string(mCurrentID);
768
769 if (!fmd) {
770 if (with_debug) {
771 cout << "Fluid: No modifier data given in RNA map setup - returning early" << endl;
772 }
773 return;
774 }
775
776 FluidDomainSettings *fds = fmd->domain;
777 bool is2D = (fds->solver_res == 2);
778
779 string borderCollisions;
781 borderCollisions += "x";
782 }
784 borderCollisions += "X";
785 }
787 borderCollisions += "y";
788 }
790 borderCollisions += "Y";
791 }
793 borderCollisions += "z";
794 }
795 if ((fds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) {
796 borderCollisions += "Z";
797 }
798
799 string particleTypesStr;
801 particleTypesStr += "PtypeSpray";
802 }
804 if (!particleTypesStr.empty()) {
805 particleTypesStr += "|";
806 }
807 particleTypesStr += "PtypeBubble";
808 }
810 if (!particleTypesStr.empty()) {
811 particleTypesStr += "|";
812 }
813 particleTypesStr += "PtypeFoam";
814 }
816 if (!particleTypesStr.empty()) {
817 particleTypesStr += "|";
818 }
819 particleTypesStr += "PtypeTracer";
820 }
821 if (particleTypesStr.empty()) {
822 particleTypesStr = "0";
823 }
824
827
828 string cacheDirectory(fds->cache_directory);
829
830 float viscosity = fds->viscosity_base * pow(10.0f, -fds->viscosity_exponent);
831 float domainSize = std::max({fds->global_size[0], fds->global_size[1], fds->global_size[2]});
832
833 string vdbCompressionMethod = "Compression_None";
835 vdbCompressionMethod = "Compression_None";
836 }
837 else if (fds->openvdb_compression == VDB_COMPRESSION_ZIP) {
838 vdbCompressionMethod = "Compression_Zip";
839 }
841 vdbCompressionMethod = "Compression_Blosc";
842 }
843
844 string vdbPrecisionHalf = "Precision_Half";
846 vdbPrecisionHalf = "Precision_Full";
847 }
849 vdbPrecisionHalf = "Precision_Half";
850 }
852 vdbPrecisionHalf = "Precision_Mini";
853 }
854
855 mRNAMap["USING_SMOKE"] = getBooleanString(fds->type == FLUID_DOMAIN_TYPE_GAS);
856 mRNAMap["USING_LIQUID"] = getBooleanString(fds->type == FLUID_DOMAIN_TYPE_LIQUID);
857 mRNAMap["USING_COLORS"] = getBooleanString(fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS);
858 mRNAMap["USING_HEAT"] = getBooleanString(fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT);
859 mRNAMap["USING_FIRE"] = getBooleanString(fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE);
860 mRNAMap["USING_NOISE"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_NOISE);
861 mRNAMap["USING_OBSTACLE"] = getBooleanString(fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE);
862 mRNAMap["USING_GUIDING"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_GUIDE);
863 mRNAMap["USING_INVEL"] = getBooleanString(fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
864 mRNAMap["USING_OUTFLOW"] = getBooleanString(fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
865 mRNAMap["USING_LOG_DISSOLVE"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG);
866 mRNAMap["USING_DISSOLVE"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_DISSOLVE);
867 mRNAMap["DOMAIN_CLOSED"] = getBooleanString(borderCollisions.compare("") == 0);
868 mRNAMap["CACHE_RESUMABLE"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE);
869 mRNAMap["USING_ADAPTIVETIME"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME);
870 mRNAMap["USING_SPEEDVECTORS"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS);
871 mRNAMap["USING_FRACTIONS"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_FRACTIONS);
872 mRNAMap["DELETE_IN_OBSTACLE"] = getBooleanString(fds->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE);
873 mRNAMap["USING_DIFFUSION"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_DIFFUSION);
874 mRNAMap["USING_MESH"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_MESH);
875 mRNAMap["USING_IMPROVED_MESH"] = getBooleanString(fds->mesh_generator ==
877 mRNAMap["USING_SNDPARTS"] = getBooleanString(fds->particle_type & particleTypes);
878 mRNAMap["SNDPARTICLE_BOUNDARY_DELETE"] = getBooleanString(fds->sndparticle_boundary ==
880 mRNAMap["SNDPARTICLE_BOUNDARY_PUSHOUT"] = getBooleanString(fds->sndparticle_boundary ==
882
883 mRNAMap["SOLVER_DIM"] = to_string(fds->solver_res);
884 mRNAMap["BOUND_CONDITIONS"] = borderCollisions;
885 mRNAMap["BOUNDARY_WIDTH"] = to_string(fds->boundary_width);
886 mRNAMap["RES"] = to_string(mMaxRes);
887 mRNAMap["RESX"] = to_string(mResX);
888 mRNAMap["RESY"] = (is2D) ? to_string(mResZ) : to_string(mResY);
889 mRNAMap["RESZ"] = (is2D) ? to_string(1) : to_string(mResZ);
890 mRNAMap["TIME_SCALE"] = to_string(fds->time_scale);
891 mRNAMap["FRAME_LENGTH"] = to_string(fds->frame_length);
892 mRNAMap["CFL"] = to_string(fds->cfl_condition);
893 mRNAMap["DT"] = to_string(fds->dt);
894 mRNAMap["TIMESTEPS_MIN"] = to_string(fds->timesteps_minimum);
895 mRNAMap["TIMESTEPS_MAX"] = to_string(fds->timesteps_maximum);
896 mRNAMap["TIME_TOTAL"] = to_string(fds->time_total);
897 mRNAMap["TIME_PER_FRAME"] = to_string(fds->time_per_frame);
898 mRNAMap["VORTICITY"] = to_string(fds->vorticity);
899 mRNAMap["FLAME_VORTICITY"] = to_string(fds->flame_vorticity);
900 mRNAMap["NOISE_SCALE"] = to_string(fds->noise_scale);
901 mRNAMap["MESH_SCALE"] = to_string(fds->mesh_scale);
902 mRNAMap["PARTICLE_SCALE"] = to_string(fds->particle_scale);
903 mRNAMap["NOISE_RESX"] = to_string(mResXNoise);
904 mRNAMap["NOISE_RESY"] = (is2D) ? to_string(mResZNoise) : to_string(mResYNoise);
905 mRNAMap["NOISE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZNoise);
906 mRNAMap["MESH_RESX"] = to_string(mResXMesh);
907 mRNAMap["MESH_RESY"] = (is2D) ? to_string(mResZMesh) : to_string(mResYMesh);
908 mRNAMap["MESH_RESZ"] = (is2D) ? to_string(1) : to_string(mResZMesh);
909 mRNAMap["PARTICLE_RESX"] = to_string(mResXParticle);
910 mRNAMap["PARTICLE_RESY"] = (is2D) ? to_string(mResZParticle) : to_string(mResYParticle);
911 mRNAMap["PARTICLE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZParticle);
912 mRNAMap["GUIDING_RESX"] = to_string(mResGuiding[0]);
913 mRNAMap["GUIDING_RESY"] = (is2D) ? to_string(mResGuiding[2]) : to_string(mResGuiding[1]);
914 mRNAMap["GUIDING_RESZ"] = (is2D) ? to_string(1) : to_string(mResGuiding[2]);
915 mRNAMap["MIN_RESX"] = to_string(fds->res_min[0]);
916 mRNAMap["MIN_RESY"] = to_string(fds->res_min[1]);
917 mRNAMap["MIN_RESZ"] = to_string(fds->res_min[2]);
918 mRNAMap["BASE_RESX"] = to_string(fds->base_res[0]);
919 mRNAMap["BASE_RESY"] = to_string(fds->base_res[1]);
920 mRNAMap["BASE_RESZ"] = to_string(fds->base_res[2]);
921 mRNAMap["WLT_STR"] = to_string(fds->noise_strength);
922 mRNAMap["NOISE_POSSCALE"] = to_string(fds->noise_pos_scale);
923 mRNAMap["NOISE_TIMEANIM"] = to_string(fds->noise_time_anim);
924 mRNAMap["COLOR_R"] = to_string(fds->active_color[0]);
925 mRNAMap["COLOR_G"] = to_string(fds->active_color[1]);
926 mRNAMap["COLOR_B"] = to_string(fds->active_color[2]);
927 mRNAMap["BUOYANCY_ALPHA"] = to_string(fds->alpha);
928 mRNAMap["BUOYANCY_BETA"] = to_string(fds->beta);
929 mRNAMap["DISSOLVE_SPEED"] = to_string(fds->diss_speed);
930 mRNAMap["BURNING_RATE"] = to_string(fds->burning_rate);
931 mRNAMap["FLAME_SMOKE"] = to_string(fds->flame_smoke);
932 mRNAMap["IGNITION_TEMP"] = to_string(fds->flame_ignition);
933 mRNAMap["MAX_TEMP"] = to_string(fds->flame_max_temp);
934 mRNAMap["FLAME_SMOKE_COLOR_X"] = to_string(fds->flame_smoke_color[0]);
935 mRNAMap["FLAME_SMOKE_COLOR_Y"] = to_string(fds->flame_smoke_color[1]);
936 mRNAMap["FLAME_SMOKE_COLOR_Z"] = to_string(fds->flame_smoke_color[2]);
937 mRNAMap["CURRENT_FRAME"] = to_string(int(fmd->time));
938 mRNAMap["START_FRAME"] = to_string(fds->cache_frame_start);
939 mRNAMap["END_FRAME"] = to_string(fds->cache_frame_end);
940 mRNAMap["CACHE_DATA_FORMAT"] = getCacheFileEnding(fds->cache_data_format);
941 mRNAMap["CACHE_MESH_FORMAT"] = getCacheFileEnding(fds->cache_mesh_format);
942 mRNAMap["CACHE_NOISE_FORMAT"] = getCacheFileEnding(fds->cache_noise_format);
943 mRNAMap["CACHE_PARTICLE_FORMAT"] = getCacheFileEnding(fds->cache_particle_format);
944 mRNAMap["USING_APIC"] = getBooleanString(fds->simulation_method == FLUID_DOMAIN_METHOD_APIC);
945 mRNAMap["FLIP_RATIO"] = to_string(fds->flip_ratio);
946 mRNAMap["PARTICLE_RANDOMNESS"] = to_string(fds->particle_randomness);
947 mRNAMap["PARTICLE_NUMBER"] = to_string(fds->particle_number);
948 mRNAMap["PARTICLE_MINIMUM"] = to_string(fds->particle_minimum);
949 mRNAMap["PARTICLE_MAXIMUM"] = to_string(fds->particle_maximum);
950 mRNAMap["PARTICLE_RADIUS"] = to_string(fds->particle_radius);
951 mRNAMap["FRACTIONS_THRESHOLD"] = to_string(fds->fractions_threshold);
952 mRNAMap["FRACTIONS_DISTANCE"] = to_string(fds->fractions_distance);
953 mRNAMap["MESH_CONCAVE_UPPER"] = to_string(fds->mesh_concave_upper);
954 mRNAMap["MESH_CONCAVE_LOWER"] = to_string(fds->mesh_concave_lower);
955 mRNAMap["MESH_PARTICLE_RADIUS"] = to_string(fds->mesh_particle_radius);
956 mRNAMap["MESH_SMOOTHEN_POS"] = to_string(fds->mesh_smoothen_pos);
957 mRNAMap["MESH_SMOOTHEN_NEG"] = to_string(fds->mesh_smoothen_neg);
958 mRNAMap["PARTICLE_BAND_WIDTH"] = to_string(fds->particle_band_width);
959 mRNAMap["SNDPARTICLE_TAU_MIN_WC"] = to_string(fds->sndparticle_tau_min_wc);
960 mRNAMap["SNDPARTICLE_TAU_MAX_WC"] = to_string(fds->sndparticle_tau_max_wc);
961 mRNAMap["SNDPARTICLE_TAU_MIN_TA"] = to_string(fds->sndparticle_tau_min_ta);
962 mRNAMap["SNDPARTICLE_TAU_MAX_TA"] = to_string(fds->sndparticle_tau_max_ta);
963 mRNAMap["SNDPARTICLE_TAU_MIN_K"] = to_string(fds->sndparticle_tau_min_k);
964 mRNAMap["SNDPARTICLE_TAU_MAX_K"] = to_string(fds->sndparticle_tau_max_k);
965 mRNAMap["SNDPARTICLE_K_WC"] = to_string(fds->sndparticle_k_wc);
966 mRNAMap["SNDPARTICLE_K_TA"] = to_string(fds->sndparticle_k_ta);
967 mRNAMap["SNDPARTICLE_K_B"] = to_string(fds->sndparticle_k_b);
968 mRNAMap["SNDPARTICLE_K_D"] = to_string(fds->sndparticle_k_d);
969 mRNAMap["SNDPARTICLE_L_MIN"] = to_string(fds->sndparticle_l_min);
970 mRNAMap["SNDPARTICLE_L_MAX"] = to_string(fds->sndparticle_l_max);
971 mRNAMap["SNDPARTICLE_POTENTIAL_RADIUS"] = to_string(fds->sndparticle_potential_radius);
972 mRNAMap["SNDPARTICLE_UPDATE_RADIUS"] = to_string(fds->sndparticle_update_radius);
973 mRNAMap["LIQUID_SURFACE_TENSION"] = to_string(fds->surface_tension);
974 mRNAMap["FLUID_VISCOSITY"] = to_string(viscosity);
975 mRNAMap["FLUID_DOMAIN_SIZE"] = to_string(domainSize);
976 mRNAMap["FLUID_DOMAIN_SIZE_X"] = to_string(fds->global_size[0]);
977 mRNAMap["FLUID_DOMAIN_SIZE_Y"] = to_string(fds->global_size[1]);
978 mRNAMap["FLUID_DOMAIN_SIZE_Z"] = to_string(fds->global_size[2]);
979 mRNAMap["SNDPARTICLE_TYPES"] = particleTypesStr;
980 mRNAMap["GUIDING_ALPHA"] = to_string(fds->guide_alpha);
981 mRNAMap["GUIDING_BETA"] = to_string(fds->guide_beta);
982 mRNAMap["GUIDING_FACTOR"] = to_string(fds->guide_vel_factor);
983 mRNAMap["GRAVITY_X"] = to_string(fds->gravity_final[0]);
984 mRNAMap["GRAVITY_Y"] = to_string(fds->gravity_final[1]);
985 mRNAMap["GRAVITY_Z"] = to_string(fds->gravity_final[2]);
986 mRNAMap["CACHE_DIR"] = cacheDirectory;
987 mRNAMap["COMPRESSION_OPENVDB"] = vdbCompressionMethod;
988 mRNAMap["PRECISION_OPENVDB"] = vdbPrecisionHalf;
989 mRNAMap["CLIP_OPENVDB"] = to_string(fds->clipping);
990 mRNAMap["PP_PARTICLE_MAXIMUM"] = to_string(fds->sys_particle_maximum);
991 mRNAMap["USING_VISCOSITY"] = getBooleanString(fds->flags & FLUID_DOMAIN_USE_VISCOSITY);
992 mRNAMap["VISCOSITY_VALUE"] = to_string(fds->viscosity_value);
993
994 /* Fluid object names. */
995 mRNAMap["NAME_FLAGS"] = FLUID_NAME_FLAGS;
996 mRNAMap["NAME_VELOCITY"] = FLUID_NAME_VELOCITY;
997 mRNAMap["NAME_VELOCITYTMP"] = FLUID_NAME_VELOCITYTMP;
998 mRNAMap["NAME_VELOCITY_X"] = FLUID_NAME_VELOCITYX;
999 mRNAMap["NAME_VELOCITY_Y"] = FLUID_NAME_VELOCITYY;
1000 mRNAMap["NAME_VELOCITY_Z"] = FLUID_NAME_VELOCITYZ;
1001 mRNAMap["NAME_PRESSURE"] = FLUID_NAME_PRESSURE;
1002 mRNAMap["NAME_PHIOBS"] = FLUID_NAME_PHIOBS;
1003 mRNAMap["NAME_PHISIN"] = FLUID_NAME_PHISIN;
1004 mRNAMap["NAME_PHIIN"] = FLUID_NAME_PHIIN;
1005 mRNAMap["NAME_PHIOUT"] = FLUID_NAME_PHIOUT;
1006 mRNAMap["NAME_FORCES"] = FLUID_NAME_FORCES;
1007 mRNAMap["NAME_FORCES_X"] = FLUID_NAME_FORCE_X;
1008 mRNAMap["NAME_FORCES_Y"] = FLUID_NAME_FORCE_Y;
1009 mRNAMap["NAME_FORCES_Z"] = FLUID_NAME_FORCE_Z;
1010 mRNAMap["NAME_NUMOBS"] = FLUID_NAME_NUMOBS;
1011 mRNAMap["NAME_PHIOBSSIN"] = FLUID_NAME_PHIOBSSIN;
1012 mRNAMap["NAME_PHIOBSIN"] = FLUID_NAME_PHIOBSIN;
1013 mRNAMap["NAME_OBVEL"] = FLUID_NAME_OBVEL;
1014 mRNAMap["NAME_OBVELC"] = FLUID_NAME_OBVELC;
1015 mRNAMap["NAME_OBVEL_X"] = FLUID_NAME_OBVEL_X;
1016 mRNAMap["NAME_OBVEL_Y"] = FLUID_NAME_OBVEL_Y;
1017 mRNAMap["NAME_OBVEL_Z"] = FLUID_NAME_OBVEL_Z;
1018 mRNAMap["NAME_FRACTIONS"] = FLUID_NAME_FRACTIONS;
1019 mRNAMap["NAME_INVELC"] = FLUID_NAME_INVELC;
1020 mRNAMap["NAME_INVEL_X"] = FLUID_NAME_INVEL_X;
1021 mRNAMap["NAME_INVEL_Y"] = FLUID_NAME_INVEL_Y;
1022 mRNAMap["NAME_INVEL_Z"] = FLUID_NAME_INVEL_Z;
1023 mRNAMap["NAME_PHIOUTSIN"] = FLUID_NAME_PHIOUTSIN;
1024 mRNAMap["NAME_PHIOUTIN"] = FLUID_NAME_PHIOUTIN;
1025
1026 /* Smoke object names. */
1027 mRNAMap["NAME_SHADOW"] = FLUID_NAME_SHADOW;
1028 mRNAMap["NAME_EMISSION"] = FLUID_NAME_EMISSION;
1029 mRNAMap["NAME_EMISSIONIN"] = FLUID_NAME_EMISSIONIN;
1030 mRNAMap["NAME_DENSITY"] = FLUID_NAME_DENSITY;
1031 mRNAMap["NAME_DENSITYIN"] = FLUID_NAME_DENSITYIN;
1032 mRNAMap["NAME_HEAT"] = FLUID_NAME_HEAT;
1033 mRNAMap["NAME_HEATIN"] = FLUID_NAME_HEATIN;
1034 mRNAMap["NAME_TEMPERATURE"] = FLUID_NAME_TEMPERATURE;
1035 mRNAMap["NAME_TEMPERATUREIN"] = FLUID_NAME_TEMPERATUREIN;
1036 mRNAMap["NAME_COLORR"] = FLUID_NAME_COLORR;
1037 mRNAMap["NAME_COLORG"] = FLUID_NAME_COLORG;
1038 mRNAMap["NAME_COLORB"] = FLUID_NAME_COLORB;
1039 mRNAMap["NAME_COLORRIN"] = FLUID_NAME_COLORRIN;
1040 mRNAMap["NAME_COLORGIN"] = FLUID_NAME_COLORGIN;
1041 mRNAMap["NAME_COLORBIN"] = FLUID_NAME_COLORBIN;
1042 mRNAMap["NAME_FLAME"] = FLUID_NAME_FLAME;
1043 mRNAMap["NAME_FUEL"] = FLUID_NAME_FUEL;
1044 mRNAMap["NAME_REACT"] = FLUID_NAME_REACT;
1045 mRNAMap["NAME_FUELIN"] = FLUID_NAME_FUELIN;
1046 mRNAMap["NAME_REACTIN"] = FLUID_NAME_REACTIN;
1047
1048 /* Liquid object names. */
1049 mRNAMap["NAME_PHIPARTS"] = FLUID_NAME_PHIPARTS;
1050 mRNAMap["NAME_PHI"] = FLUID_NAME_PHI;
1051 mRNAMap["NAME_PHITMP"] = FLUID_NAME_PHITMP;
1052 mRNAMap["NAME_VELOLD"] = FLUID_NAME_VELOCITYOLD;
1053 mRNAMap["NAME_VELPARTS"] = FLUID_NAME_VELOCITYPARTS;
1054 mRNAMap["NAME_MAPWEIGHTS"] = FLUID_NAME_MAPWEIGHTS;
1055 mRNAMap["NAME_PP"] = FLUID_NAME_PP;
1056 mRNAMap["NAME_PVEL"] = FLUID_NAME_PVEL;
1057 mRNAMap["NAME_PARTS"] = FLUID_NAME_PARTS;
1058 mRNAMap["NAME_PARTSVELOCITY"] = FLUID_NAME_PARTSVELOCITY;
1059 mRNAMap["NAME_PINDEX"] = FLUID_NAME_PINDEX;
1060 mRNAMap["NAME_GPI"] = FLUID_NAME_GPI;
1061 mRNAMap["NAME_CURVATURE"] = FLUID_NAME_CURVATURE;
1062
1063 /* Noise object names. */
1064 mRNAMap["NAME_VELOCITY_NOISE"] = FLUID_NAME_VELOCITY_NOISE;
1065 mRNAMap["NAME_DENSITY_NOISE"] = FLUID_NAME_DENSITY_NOISE;
1066 mRNAMap["NAME_PHIIN_NOISE"] = FLUID_NAME_PHIIN_NOISE;
1067 mRNAMap["NAME_PHIOUT_NOISE"] = FLUID_NAME_PHIOUT_NOISE;
1068 mRNAMap["NAME_PHIOBS_NOISE"] = FLUID_NAME_PHIOBS_NOISE;
1069 mRNAMap["NAME_FLAGS_NOISE"] = FLUID_NAME_FLAGS_NOISE;
1070 mRNAMap["NAME_TMPIN_NOISE"] = FLUID_NAME_TMPIN_NOISE;
1071 mRNAMap["NAME_EMISSIONIN_NOISE"] = FLUID_NAME_EMISSIONIN_NOISE;
1072 mRNAMap["NAME_ENERGY"] = FLUID_NAME_ENERGY;
1073 mRNAMap["NAME_TMPFLAGS"] = FLUID_NAME_TMPFLAGS;
1074 mRNAMap["NAME_TEXTURE_U"] = FLUID_NAME_TEXTURE_U;
1075 mRNAMap["NAME_TEXTURE_V"] = FLUID_NAME_TEXTURE_V;
1076 mRNAMap["NAME_TEXTURE_W"] = FLUID_NAME_TEXTURE_W;
1077 mRNAMap["NAME_TEXTURE_U2"] = FLUID_NAME_TEXTURE_U2;
1078 mRNAMap["NAME_TEXTURE_V2"] = FLUID_NAME_TEXTURE_V2;
1079 mRNAMap["NAME_TEXTURE_W2"] = FLUID_NAME_TEXTURE_W2;
1080 mRNAMap["NAME_UV0"] = FLUID_NAME_UV0;
1081 mRNAMap["NAME_UV1"] = FLUID_NAME_UV1;
1082 mRNAMap["NAME_COLORR_NOISE"] = FLUID_NAME_COLORR_NOISE;
1083 mRNAMap["NAME_COLORG_NOISE"] = FLUID_NAME_COLORG_NOISE;
1084 mRNAMap["NAME_COLORB_NOISE"] = FLUID_NAME_COLORB_NOISE;
1085 mRNAMap["NAME_FLAME_NOISE"] = FLUID_NAME_FLAME_NOISE;
1086 mRNAMap["NAME_FUEL_NOISE"] = FLUID_NAME_FUEL_NOISE;
1087 mRNAMap["NAME_REACT_NOISE"] = FLUID_NAME_REACT_NOISE;
1088
1089 /* Mesh object names. */
1090 mRNAMap["NAME_PHIPARTS_MESH"] = FLUID_NAME_PHIPARTS_MESH;
1091 mRNAMap["NAME_PHI_MESH"] = FLUID_NAME_PHI_MESH;
1092 mRNAMap["NAME_PP_MESH"] = FLUID_NAME_PP_MESH;
1093 mRNAMap["NAME_FLAGS_MESH"] = FLUID_NAME_FLAGS_MESH;
1094 mRNAMap["NAME_LMESH"] = FLUID_NAME_LMESH;
1095 mRNAMap["NAME_VELOCITYVEC_MESH"] = FLUID_NAME_VELOCITYVEC_MESH;
1096 mRNAMap["NAME_VELOCITY_MESH"] = FLUID_NAME_VELOCITY_MESH;
1097 mRNAMap["NAME_PINDEX_MESH"] = FLUID_NAME_PINDEX_MESH;
1098 mRNAMap["NAME_GPI_MESH"] = FLUID_NAME_GPI_MESH;
1099
1100 /* Particles object names. */
1101 mRNAMap["NAME_PP_PARTICLES"] = FLUID_NAME_PP_PARTICLES;
1102 mRNAMap["NAME_PVEL_PARTICLES"] = FLUID_NAME_PVEL_PARTICLES;
1103 mRNAMap["NAME_PFORCE_PARTICLES"] = FLUID_NAME_PFORCE_PARTICLES;
1104 mRNAMap["NAME_PLIFE_PARTICLES"] = FLUID_NAME_PLIFE_PARTICLES;
1105 mRNAMap["NAME_PARTS_PARTICLES"] = FLUID_NAME_PARTS_PARTICLES;
1106 mRNAMap["NAME_PARTSVEL_PARTICLES"] = FLUID_NAME_PARTSVEL_PARTICLES;
1107 mRNAMap["NAME_PARTSFORCE_PARTICLES"] = FLUID_NAME_PARTSFORCE_PARTICLES;
1108 mRNAMap["NAME_PARTSLIFE_PARTICLES"] = FLUID_NAME_PARTSLIFE_PARTICLES;
1109 mRNAMap["NAME_VELOCITY_PARTICLES"] = FLUID_NAME_VELOCITY_PARTICLES;
1110 mRNAMap["NAME_FLAGS_PARTICLES"] = FLUID_NAME_FLAGS_PARTICLES;
1111 mRNAMap["NAME_PHI_PARTICLES"] = FLUID_NAME_PHI_PARTICLES;
1112 mRNAMap["NAME_PHIOBS_PARTICLES"] = FLUID_NAME_PHIOBS_PARTICLES;
1113 mRNAMap["NAME_PHIOUT_PARTICLES"] = FLUID_NAME_PHIOUT_PARTICLES;
1114 mRNAMap["NAME_NORMAL_PARTICLES"] = FLUID_NAME_NORMAL_PARTICLES;
1115 mRNAMap["NAME_NEIGHBORRATIO_PARTICLES"] = FLUID_NAME_NEIGHBORRATIO_PARTICLES;
1116 mRNAMap["NAME_TRAPPEDAIR_PARTICLES"] = FLUID_NAME_TRAPPEDAIR_PARTICLES;
1117 mRNAMap["NAME_WAVECREST_PARTICLES"] = FLUID_NAME_WAVECREST_PARTICLES;
1118 mRNAMap["NAME_KINETICENERGY_PARTICLES"] = FLUID_NAME_KINETICENERGY_PARTICLES;
1119
1120 /* Guiding object names. */
1121 mRNAMap["NAME_VELT"] = FLUID_NAME_VELT;
1122 mRNAMap["NAME_WEIGHTGUIDE"] = FLUID_NAME_WEIGHTGUIDE;
1123 mRNAMap["NAME_NUMGUIDES"] = FLUID_NAME_NUMGUIDES;
1124 mRNAMap["NAME_PHIGUIDEIN"] = FLUID_NAME_PHIGUIDEIN;
1125 mRNAMap["NAME_GUIDEVELC"] = FLUID_NAME_GUIDEVELC;
1126 mRNAMap["NAME_GUIDEVEL_X"] = FLUID_NAME_GUIDEVEL_X;
1127 mRNAMap["NAME_GUIDEVEL_Y"] = FLUID_NAME_GUIDEVEL_Y;
1128 mRNAMap["NAME_GUIDEVEL_Z"] = FLUID_NAME_GUIDEVEL_Z;
1129 mRNAMap["NAME_VELOCITY_GUIDE"] = FLUID_NAME_VELOCITY_GUIDE;
1130
1131 /* Cache file names. */
1132 mRNAMap["NAME_CONFIG"] = FLUID_NAME_CONFIG;
1133 mRNAMap["NAME_DATA"] = FLUID_NAME_DATA;
1134 mRNAMap["NAME_NOISE"] = FLUID_NAME_NOISE;
1135 mRNAMap["NAME_MESH"] = FLUID_NAME_MESH;
1136 mRNAMap["NAME_PARTICLES"] = FLUID_NAME_PARTICLES;
1137 mRNAMap["NAME_GUIDING"] = FLUID_NAME_GUIDING;
1138}
1139
1140string MANTA::getRealValue(const string &varName)
1141{
1142 unordered_map<string, string>::iterator it;
1143 it = mRNAMap.find(varName);
1144
1145 if (it == mRNAMap.end()) {
1146 cerr << "Fluid Error -- variable " << varName << " not found in RNA map" << endl;
1147 return "";
1148 }
1149
1150 return it->second;
1151}
1152
1153string MANTA::parseLine(const string &line)
1154{
1155 if (line.size() == 0) {
1156 return "";
1157 }
1158 string res;
1159 int currPos = 0, start_del = 0, end_del = -1;
1160 bool readingVar = false;
1161 const char delimiter = '$';
1162 while (currPos < line.size()) {
1163 if (line[currPos] == delimiter && !readingVar) {
1164 readingVar = true;
1165 start_del = currPos + 1;
1166 res += line.substr(end_del + 1, currPos - end_del - 1);
1167 }
1168 else if (line[currPos] == delimiter && readingVar) {
1169 readingVar = false;
1170 end_del = currPos;
1171 res += getRealValue(line.substr(start_del, currPos - start_del));
1172 }
1173 currPos++;
1174 }
1175 res += line.substr(end_del + 1, line.size() - end_del);
1176 return res;
1177}
1178
1179string MANTA::parseScript(const string &setup_string, FluidModifierData *fmd)
1180{
1181 if (MANTA::with_debug) {
1182 cout << "MANTA::parseScript()" << endl;
1183 }
1184
1185 istringstream f(setup_string);
1186 ostringstream res;
1187 string line;
1188
1189 /* Update RNA map if modifier data is handed over. */
1190 if (fmd) {
1191 initializeRNAMap(fmd);
1192 }
1193 while (getline(f, line)) {
1194 res << parseLine(line) << "\n";
1195 }
1196 return res.str();
1197}
1198
1200static string escapePath(string const &s)
1201{
1202 string result;
1203 for (char c : s) {
1204 if (c == '\\') {
1205 result += "\\\\";
1206 }
1207 else if (c == '\'') {
1208 result += "\\\'";
1209 }
1210 else {
1211 result += c;
1212 }
1213 }
1214 return result;
1215}
1216
1218{
1219 if (with_debug) {
1220 cout << "MANTA::writeConfiguration()" << endl;
1221 }
1222
1223 FluidDomainSettings *fds = fmd->domain;
1224
1225 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_CONFIG);
1227 string file = getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, format, framenr);
1228
1229 /* Create 'config' subdir if it does not exist already. */
1230 BLI_dir_create_recursive(directory.c_str());
1231
1232 /* Open new file with some compression. */
1233 gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "wb1");
1234 if (!gzf) {
1235 cerr << "Fluid Error -- Cannot open file " << file << endl;
1236 return false;
1237 }
1238
1239 gzwrite(gzf, &fds->active_fields, sizeof(int));
1240 gzwrite(gzf, &fds->res, 3 * sizeof(int));
1241 gzwrite(gzf, &fds->dx, sizeof(float));
1242 gzwrite(gzf, &fds->dt, sizeof(float));
1243 gzwrite(gzf, &fds->p0, 3 * sizeof(float));
1244 gzwrite(gzf, &fds->p1, 3 * sizeof(float));
1245 gzwrite(gzf, &fds->dp0, 3 * sizeof(float));
1246 gzwrite(gzf, &fds->shift, 3 * sizeof(int));
1247 gzwrite(gzf, &fds->obj_shift_f, 3 * sizeof(float));
1248 gzwrite(gzf, &fds->obmat, 16 * sizeof(float));
1249 gzwrite(gzf, &fds->base_res, 3 * sizeof(int));
1250 gzwrite(gzf, &fds->res_min, 3 * sizeof(int));
1251 gzwrite(gzf, &fds->res_max, 3 * sizeof(int));
1252 gzwrite(gzf, &fds->active_color, 3 * sizeof(float));
1253 gzwrite(gzf, &fds->time_total, sizeof(int));
1254 gzwrite(gzf, &FLUID_CACHE_VERSION, 4 * sizeof(char));
1255
1256 return (gzclose(gzf) == Z_OK);
1257}
1258
1260{
1261 if (with_debug) {
1262 cout << "MANTA::writeData()" << endl;
1263 }
1264
1265 ostringstream ss;
1266 vector<string> pythonCommands;
1267 FluidDomainSettings *fds = fmd->domain;
1268
1269 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_DATA);
1270 string volume_format = getCacheFileEnding(fds->cache_data_format);
1271 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1272
1273 if (mUsingSmoke) {
1274 ss.str("");
1275 ss << "smoke_save_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1276 << ", '" << volume_format << "', " << resumable_cache << ")";
1277 pythonCommands.push_back(ss.str());
1278 }
1279 if (mUsingLiquid) {
1280 ss.str("");
1281 ss << "liquid_save_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1282 << ", '" << volume_format << "', " << resumable_cache << ")";
1283 pythonCommands.push_back(ss.str());
1284 }
1285 return runPythonString(pythonCommands);
1286}
1287
1289{
1290 if (with_debug) {
1291 cout << "MANTA::writeNoise()" << endl;
1292 }
1293
1294 ostringstream ss;
1295 vector<string> pythonCommands;
1296 FluidDomainSettings *fds = fmd->domain;
1297
1298 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_NOISE);
1299 string volume_format = getCacheFileEnding(fds->cache_data_format);
1300 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1301
1302 if (mUsingSmoke && mUsingNoise) {
1303 ss.str("");
1304 ss << "smoke_save_noise_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1305 << ", '" << volume_format << "', " << resumable_cache << ")";
1306 pythonCommands.push_back(ss.str());
1307 }
1308 return runPythonString(pythonCommands);
1309}
1310
1312{
1313 if (with_debug) {
1314 cout << "MANTA::readConfiguration()" << endl;
1315 }
1316
1317 FluidDomainSettings *fds = fmd->domain;
1318 float dummy;
1319
1320 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_CONFIG);
1322 string file = getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, format, framenr);
1323
1324 if (!hasConfig(fmd, framenr)) {
1325 return false;
1326 }
1327
1328 gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); /* Do some compression. */
1329 if (!gzf) {
1330 cerr << "Fluid Error -- Cannot open file " << file << endl;
1331 return false;
1332 }
1333
1334 gzread(gzf, &fds->active_fields, sizeof(int));
1335 gzread(gzf, &fds->res, 3 * sizeof(int));
1336 gzread(gzf, &fds->dx, sizeof(float));
1337 gzread(gzf, &dummy, sizeof(float)); /* dt not needed right now. */
1338 gzread(gzf, &fds->p0, 3 * sizeof(float));
1339 gzread(gzf, &fds->p1, 3 * sizeof(float));
1340 gzread(gzf, &fds->dp0, 3 * sizeof(float));
1341 gzread(gzf, &fds->shift, 3 * sizeof(int));
1342 gzread(gzf, &fds->obj_shift_f, 3 * sizeof(float));
1343 gzread(gzf, &fds->obmat, 16 * sizeof(float));
1344 gzread(gzf, &fds->base_res, 3 * sizeof(int));
1345 gzread(gzf, &fds->res_min, 3 * sizeof(int));
1346 gzread(gzf, &fds->res_max, 3 * sizeof(int));
1347 gzread(gzf, &fds->active_color, 3 * sizeof(float));
1348 gzread(gzf, &fds->time_total, sizeof(int));
1349 gzread(gzf, &fds->cache_id, 4 * sizeof(char)); /* Older caches might have no id. */
1350
1351 fds->total_cells = fds->res[0] * fds->res[1] * fds->res[2];
1352
1353 return (gzclose(gzf) == Z_OK);
1354}
1355
1356bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable)
1357{
1358 if (with_debug) {
1359 cout << "MANTA::readData()" << endl;
1360 }
1361
1362 if (!mUsingSmoke && !mUsingLiquid) {
1363 return false;
1364 }
1365
1366 ostringstream ss;
1367 vector<string> pythonCommands;
1368 FluidDomainSettings *fds = fmd->domain;
1369 bool result = true;
1370
1371 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_DATA);
1372 string volume_format = getCacheFileEnding(fds->cache_data_format);
1373 string resumable_cache = (!resumable) ? "False" : "True";
1374
1375 /* Sanity check: Are cache files present? */
1376 if (!hasData(fmd, framenr)) {
1377 return false;
1378 }
1379
1380 if (mUsingSmoke) {
1381 ss.str("");
1382 ss << "smoke_load_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1383 << ", '" << volume_format << "', " << resumable_cache << ")";
1384 pythonCommands.push_back(ss.str());
1385 result &= runPythonString(pythonCommands);
1386 return (mSmokeFromFile = result);
1387 }
1388 if (mUsingLiquid) {
1389 ss.str("");
1390 ss << "liquid_load_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1391 << ", '" << volume_format << "', " << resumable_cache << ")";
1392 pythonCommands.push_back(ss.str());
1393 result &= runPythonString(pythonCommands);
1394 return (mFlipFromFile = result);
1395 }
1396 return result;
1397}
1398
1399bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable)
1400{
1401 if (with_debug) {
1402 cout << "MANTA::readNoise()" << endl;
1403 }
1404
1405 if (!mUsingSmoke || !mUsingNoise) {
1406 return false;
1407 }
1408
1409 ostringstream ss;
1410 vector<string> pythonCommands;
1411 FluidDomainSettings *fds = fmd->domain;
1412
1413 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_NOISE);
1414 string resumable_cache = (!resumable) ? "False" : "True";
1415
1416 /* Support older caches which had more granular file format control. */
1417 char format = (!strcmp(fds->cache_id, FLUID_CACHE_VERSION)) ? fds->cache_data_format :
1418 fds->cache_noise_format;
1419 string volume_format = getCacheFileEnding(format);
1420
1421 /* Sanity check: Are cache files present? */
1422 if (!hasNoise(fmd, framenr)) {
1423 return false;
1424 }
1425
1426 ss.str("");
1427 ss << "smoke_load_noise_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1428 << ", '" << volume_format << "', " << resumable_cache << ")";
1429 pythonCommands.push_back(ss.str());
1430
1431 return (mNoiseFromFile = runPythonString(pythonCommands));
1432}
1433
1434bool MANTA::readMesh(FluidModifierData *fmd, int framenr)
1435{
1436 if (with_debug) {
1437 cout << "MANTA::readMesh()" << endl;
1438 }
1439
1440 if (!mUsingLiquid || !mUsingMesh) {
1441 return false;
1442 }
1443
1444 ostringstream ss;
1445 vector<string> pythonCommands;
1446 FluidDomainSettings *fds = fmd->domain;
1447
1448 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_MESH);
1449 string mesh_format = getCacheFileEnding(fds->cache_mesh_format);
1450 string volume_format = getCacheFileEnding(fds->cache_data_format);
1451
1452 /* Sanity check: Are cache files present? */
1453 if (!hasMesh(fmd, framenr)) {
1454 return false;
1455 }
1456
1457 ss.str("");
1458 ss << "liquid_load_mesh_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1459 << ", '" << mesh_format << "')";
1460 pythonCommands.push_back(ss.str());
1461
1462 if (mUsingMVel) {
1463 ss.str("");
1464 ss << "liquid_load_meshvel_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1465 << ", '" << volume_format << "')";
1466 pythonCommands.push_back(ss.str());
1467 }
1468
1469 return (mMeshFromFile = runPythonString(pythonCommands));
1470}
1471
1472bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable)
1473{
1474 if (with_debug) {
1475 cout << "MANTA::readParticles()" << endl;
1476 }
1477
1478 if (!mUsingLiquid) {
1479 return false;
1480 }
1481 if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) {
1482 return false;
1483 }
1484
1485 ostringstream ss;
1486 vector<string> pythonCommands;
1487 FluidDomainSettings *fds = fmd->domain;
1488
1489 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_PARTICLES);
1490 string resumable_cache = (!resumable) ? "False" : "True";
1491
1492 /* Support older caches which had more granular file format control. */
1493 char format = (!strcmp(fds->cache_id, FLUID_CACHE_VERSION)) ? fds->cache_data_format :
1495 string volume_format = getCacheFileEnding(format);
1496
1497 /* Sanity check: Are cache files present? */
1498 if (!hasParticles(fmd, framenr)) {
1499 return false;
1500 }
1501
1502 ss.str("");
1503 ss << "liquid_load_particles_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1504 << ", '" << volume_format << "', " << resumable_cache << ")";
1505 pythonCommands.push_back(ss.str());
1506
1507 return (mParticlesFromFile = runPythonString(pythonCommands));
1508}
1509
1510bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
1511{
1512 if (with_debug) {
1513 cout << "MANTA::readGuiding()" << endl;
1514 }
1515
1516 if (!mUsingGuiding) {
1517 return false;
1518 }
1519 if (!fmd) {
1520 return false;
1521 }
1522
1523 ostringstream ss;
1524 vector<string> pythonCommands;
1525 FluidDomainSettings *fds = fmd->domain;
1526
1527 string directory = (sourceDomain) ? getDirectory(fmd, FLUID_DOMAIN_DIR_DATA) :
1528 getDirectory(fmd, FLUID_DOMAIN_DIR_GUIDE);
1529 string volume_format = getCacheFileEnding(fds->cache_data_format);
1530
1531 /* Sanity check: Are cache files present? */
1532 if (!hasGuiding(fmd, framenr, sourceDomain)) {
1533 return false;
1534 }
1535
1536 if (sourceDomain) {
1537 ss.str("");
1538 ss << "fluid_load_vel_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1539 << ", '" << volume_format << "')";
1540 }
1541 else {
1542 ss.str("");
1543 ss << "fluid_load_guiding_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1544 << ", '" << volume_format << "')";
1545 }
1546 pythonCommands.push_back(ss.str());
1547
1548 return runPythonString(pythonCommands);
1549}
1550
1551bool MANTA::bakeData(FluidModifierData *fmd, int framenr)
1552{
1553 if (with_debug) {
1554 cout << "MANTA::bakeData()" << endl;
1555 }
1556
1557 ostringstream ss;
1558 vector<string> pythonCommands;
1559 FluidDomainSettings *fds = fmd->domain;
1560
1561 char cacheDirData[FILE_MAX], cacheDirGuiding[FILE_MAX];
1562 cacheDirData[0] = '\0';
1563 cacheDirGuiding[0] = '\0';
1564
1565 string volume_format = getCacheFileEnding(fds->cache_data_format);
1566
1567 BLI_path_join(cacheDirData, sizeof(cacheDirData), fds->cache_directory, FLUID_DOMAIN_DIR_DATA);
1569 cacheDirGuiding, sizeof(cacheDirGuiding), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE);
1570 BLI_path_make_safe(cacheDirData);
1571 BLI_path_make_safe(cacheDirGuiding);
1572
1573 ss.str("");
1574 ss << "bake_fluid_data_" << mCurrentID << "('" << escapePath(cacheDirData) << "', " << framenr
1575 << ", '" << volume_format << "')";
1576 pythonCommands.push_back(ss.str());
1577
1578 return runPythonString(pythonCommands);
1579}
1580
1582{
1583 if (with_debug) {
1584 cout << "MANTA::bakeNoise()" << endl;
1585 }
1586
1587 ostringstream ss;
1588 vector<string> pythonCommands;
1589 FluidDomainSettings *fds = fmd->domain;
1590
1591 char cacheDirNoise[FILE_MAX];
1592 cacheDirNoise[0] = '\0';
1593
1594 string volume_format = getCacheFileEnding(fds->cache_data_format);
1595
1597 cacheDirNoise, sizeof(cacheDirNoise), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE);
1598 BLI_path_make_safe(cacheDirNoise);
1599
1600 ss.str("");
1601 ss << "bake_noise_" << mCurrentID << "('" << escapePath(cacheDirNoise) << "', " << framenr
1602 << ", '" << volume_format << "')";
1603 pythonCommands.push_back(ss.str());
1604
1605 return runPythonString(pythonCommands);
1606}
1607
1608bool MANTA::bakeMesh(FluidModifierData *fmd, int framenr)
1609{
1610 if (with_debug) {
1611 cout << "MANTA::bakeMesh()" << endl;
1612 }
1613
1614 ostringstream ss;
1615 vector<string> pythonCommands;
1616 FluidDomainSettings *fds = fmd->domain;
1617
1618 char cacheDirMesh[FILE_MAX];
1619 cacheDirMesh[0] = '\0';
1620
1621 string volume_format = getCacheFileEnding(fds->cache_data_format);
1622 string mesh_format = getCacheFileEnding(fds->cache_mesh_format);
1623
1624 BLI_path_join(cacheDirMesh, sizeof(cacheDirMesh), fds->cache_directory, FLUID_DOMAIN_DIR_MESH);
1625 BLI_path_make_safe(cacheDirMesh);
1626
1627 ss.str("");
1628 ss << "bake_mesh_" << mCurrentID << "('" << escapePath(cacheDirMesh) << "', " << framenr << ", '"
1629 << volume_format << "', '" << mesh_format << "')";
1630 pythonCommands.push_back(ss.str());
1631
1632 return runPythonString(pythonCommands);
1633}
1634
1636{
1637 if (with_debug) {
1638 cout << "MANTA::bakeParticles()" << endl;
1639 }
1640
1641 ostringstream ss;
1642 vector<string> pythonCommands;
1643 FluidDomainSettings *fds = fmd->domain;
1644
1645 char cacheDirParticles[FILE_MAX];
1646 cacheDirParticles[0] = '\0';
1647
1648 string volume_format = getCacheFileEnding(fds->cache_data_format);
1649 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1650
1651 BLI_path_join(cacheDirParticles,
1652 sizeof(cacheDirParticles),
1653 fds->cache_directory,
1655 BLI_path_make_safe(cacheDirParticles);
1656
1657 ss.str("");
1658 ss << "bake_particles_" << mCurrentID << "('" << escapePath(cacheDirParticles) << "', "
1659 << framenr << ", '" << volume_format << "', " << resumable_cache << ")";
1660 pythonCommands.push_back(ss.str());
1661
1662 return runPythonString(pythonCommands);
1663}
1664
1666{
1667 if (with_debug) {
1668 cout << "MANTA::bakeGuiding()" << endl;
1669 }
1670
1671 ostringstream ss;
1672 vector<string> pythonCommands;
1673 FluidDomainSettings *fds = fmd->domain;
1674
1675 char cacheDirGuiding[FILE_MAX];
1676 cacheDirGuiding[0] = '\0';
1677
1678 string volume_format = getCacheFileEnding(fds->cache_data_format);
1679 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1680
1682 cacheDirGuiding, sizeof(cacheDirGuiding), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE);
1683 BLI_path_make_safe(cacheDirGuiding);
1684
1685 ss.str("");
1686 ss << "bake_guiding_" << mCurrentID << "('" << escapePath(cacheDirGuiding) << "', " << framenr
1687 << ", '" << volume_format << "', " << resumable_cache << ")";
1688 pythonCommands.push_back(ss.str());
1689
1690 return runPythonString(pythonCommands);
1691}
1692
1694{
1695 string tmpString, finalString;
1696 vector<string> pythonCommands;
1697
1698 tmpString += fluid_variables;
1699 if (mUsingSmoke) {
1700 tmpString += smoke_variables;
1701 }
1702 if (mUsingLiquid) {
1703 tmpString += liquid_variables;
1704 }
1705 if (mUsingGuiding) {
1706 tmpString += fluid_variables_guiding;
1707 }
1708 if (mUsingNoise) {
1709 tmpString += fluid_variables_noise;
1710 tmpString += smoke_variables_noise;
1711 tmpString += smoke_wavelet_noise;
1712 }
1713 if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) {
1714 tmpString += fluid_variables_particles;
1715 tmpString += liquid_variables_particles;
1716 }
1717 if (mUsingMesh) {
1718 tmpString += fluid_variables_mesh;
1719 }
1720
1721 finalString = parseScript(tmpString, fmd);
1722 pythonCommands.push_back(finalString);
1723
1724 return runPythonString(pythonCommands);
1725}
1726
1728{
1729 if (with_debug) {
1730 cout << "MANTA::exportSmokeScript()" << endl;
1731 }
1732
1733 char cacheDir[FILE_MAX] = "\0";
1734 char cacheDirScript[FILE_MAX] = "\0";
1735
1736 FluidDomainSettings *fds = fmd->domain;
1737
1738 BLI_path_join(cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT);
1739 BLI_path_make_safe(cacheDir);
1740 /* Create 'script' subdir if it does not exist already */
1741 BLI_dir_create_recursive(cacheDir);
1742 BLI_path_join(cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_SMOKE_SCRIPT);
1743 BLI_path_make_safe(cacheDir);
1744
1745 bool noise = fds->flags & FLUID_DOMAIN_USE_NOISE;
1746 bool heat = fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
1747 bool colors = fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
1748 bool fire = fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
1749 bool obstacle = fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
1750 bool guiding = fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
1751 bool invel = fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
1752 bool outflow = fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
1753
1754 string manta_script;
1755
1756 /* Libraries. */
1757 manta_script += header_libraries + manta_import;
1758
1759 /* Variables. */
1760 manta_script += header_variables + fluid_variables + smoke_variables;
1761 if (noise) {
1763 }
1764 if (guiding) {
1765 manta_script += fluid_variables_guiding;
1766 }
1767
1768 /* Solvers. */
1769 manta_script += header_solvers + fluid_solver;
1770 if (noise) {
1771 manta_script += fluid_solver_noise;
1772 }
1773 if (guiding) {
1774 manta_script += fluid_solver_guiding;
1775 }
1776
1777 /* Grids. */
1778 manta_script += header_grids + fluid_alloc + smoke_alloc;
1779 if (noise) {
1780 manta_script += smoke_alloc_noise;
1781 if (colors) {
1782 manta_script += smoke_alloc_colors_noise;
1783 }
1784 if (fire) {
1785 manta_script += smoke_alloc_fire_noise;
1786 }
1787 }
1788 if (heat) {
1789 manta_script += smoke_alloc_heat;
1790 }
1791 if (colors) {
1792 manta_script += smoke_alloc_colors;
1793 }
1794 if (fire) {
1795 manta_script += smoke_alloc_fire;
1796 }
1797 if (guiding) {
1798 manta_script += fluid_alloc_guiding;
1799 }
1800 if (obstacle) {
1801 manta_script += fluid_alloc_obstacle;
1802 }
1803 if (invel) {
1804 manta_script += fluid_alloc_invel;
1805 }
1806 if (outflow) {
1807 manta_script += fluid_alloc_outflow;
1808 }
1809
1810 /* Noise field. */
1811 if (noise) {
1812 manta_script += smoke_wavelet_noise;
1813 }
1814
1815 /* Time. */
1816 manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step;
1817
1818 /* Import. */
1819 manta_script += header_import + fluid_file_import + fluid_cache_helper + smoke_load_data;
1820 if (noise) {
1821 manta_script += smoke_load_noise;
1822 }
1823 if (guiding) {
1824 manta_script += fluid_load_guiding;
1825 }
1826
1827 /* Pre/Post Steps. */
1828 manta_script += header_prepost + fluid_pre_step + fluid_post_step;
1829
1830 /* Steps. */
1831 manta_script += header_steps + smoke_adaptive_step + smoke_step;
1832 if (noise) {
1833 manta_script += smoke_step_noise;
1834 }
1835
1836 /* Main. */
1837 manta_script += header_main + smoke_standalone + fluid_standalone;
1838
1839 /* Fill in missing variables in script. */
1840 string final_script = MANTA::parseScript(manta_script, fmd);
1841
1842 /* Write script. */
1843 ofstream myfile;
1844 myfile.open(cacheDirScript);
1845 myfile << final_script;
1846 myfile.close();
1847 if (!myfile) {
1848 cerr << "Fluid Error -- Could not export standalone Mantaflow smoke domain script";
1849 return false;
1850 }
1851 return true;
1852}
1853
1855{
1856 if (with_debug) {
1857 cout << "MANTA::exportLiquidScript()" << endl;
1858 }
1859
1860 char cacheDir[FILE_MAX] = "\0";
1861 char cacheDirScript[FILE_MAX] = "\0";
1862
1863 FluidDomainSettings *fds = fmd->domain;
1864
1865 BLI_path_join(cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT);
1866 BLI_path_make_safe(cacheDir);
1867 /* Create 'script' subdir if it does not exist already */
1868 BLI_dir_create_recursive(cacheDir);
1869 BLI_path_join(cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_LIQUID_SCRIPT);
1870 BLI_path_make_safe(cacheDirScript);
1871
1872 bool mesh = fds->flags & FLUID_DOMAIN_USE_MESH;
1873 bool drops = fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
1874 bool bubble = fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
1875 bool floater = fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
1876 bool tracer = fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
1877 bool obstacle = fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
1878 bool fractions = fds->flags & FLUID_DOMAIN_USE_FRACTIONS;
1879 bool guiding = fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
1880 bool invel = fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
1881 bool outflow = fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
1882 bool viscosity = fds->flags & FLUID_DOMAIN_USE_VISCOSITY;
1883
1884 string manta_script;
1885
1886 /* Libraries. */
1887 manta_script += header_libraries + manta_import;
1888
1889 /* Variables. */
1890 manta_script += header_variables + fluid_variables + liquid_variables;
1891 if (mesh) {
1892 manta_script += fluid_variables_mesh;
1893 }
1894 if (drops || bubble || floater || tracer) {
1896 }
1897 if (guiding) {
1898 manta_script += fluid_variables_guiding;
1899 }
1900 if (viscosity) {
1901 manta_script += fluid_variables_viscosity;
1902 }
1903
1904 /* Solvers. */
1905 manta_script += header_solvers + fluid_solver;
1906 if (mesh) {
1907 manta_script += fluid_solver_mesh;
1908 }
1909 if (drops || bubble || floater || tracer) {
1910 manta_script += fluid_solver_particles;
1911 }
1912 if (guiding) {
1913 manta_script += fluid_solver_guiding;
1914 }
1915 if (viscosity) {
1916 manta_script += fluid_solver_viscosity;
1917 }
1918
1919 /* Grids. */
1920 manta_script += header_grids + fluid_alloc + liquid_alloc;
1921 if (mesh) {
1922 manta_script += liquid_alloc_mesh;
1923 }
1924 if (drops || bubble || floater || tracer) {
1925 manta_script += liquid_alloc_particles;
1926 }
1927 if (guiding) {
1928 manta_script += fluid_alloc_guiding;
1929 }
1930 if (obstacle) {
1931 manta_script += fluid_alloc_obstacle;
1932 }
1933 if (fractions) {
1934 manta_script += fluid_alloc_fractions;
1935 }
1936 if (invel) {
1937 manta_script += fluid_alloc_invel;
1938 }
1939 if (outflow) {
1940 manta_script += fluid_alloc_outflow;
1941 }
1942 if (viscosity) {
1943 manta_script += liquid_alloc_viscosity;
1944 }
1945
1946 /* Domain init. */
1947 manta_script += header_gridinit + liquid_init_phi;
1948
1949 /* Time. */
1950 manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step;
1951
1952 /* Import. */
1953 manta_script += header_import + fluid_file_import + fluid_cache_helper + liquid_load_data;
1954 if (mesh) {
1955 manta_script += liquid_load_mesh;
1956 }
1957 if (drops || bubble || floater || tracer) {
1958 manta_script += liquid_load_particles;
1959 }
1960 if (guiding) {
1961 manta_script += fluid_load_guiding;
1962 }
1963
1964 /* Pre/Post Steps. */
1965 manta_script += header_prepost + fluid_pre_step + fluid_post_step;
1966
1967 /* Steps. */
1968 manta_script += header_steps + liquid_adaptive_step + liquid_step;
1969 if (mesh) {
1970 manta_script += liquid_step_mesh;
1971 }
1972 if (drops || bubble || floater || tracer) {
1973 manta_script += liquid_step_particles;
1974 }
1975
1976 /* Main. */
1977 manta_script += header_main + liquid_standalone + fluid_standalone;
1978
1979 /* Fill in missing variables in script. */
1980 string final_script = MANTA::parseScript(manta_script, fmd);
1981
1982 /* Write script. */
1983 ofstream myfile;
1984 myfile.open(cacheDirScript);
1985 myfile << final_script;
1986 myfile.close();
1987 if (!myfile) {
1988 cerr << "Fluid Error -- Could not export standalone Mantaflow liquid domain script";
1989 return false;
1990 }
1991 return true;
1992}
1993
1994/* Call Mantaflow Python functions through this function. Use isAttribute for object attributes,
1995 * e.g. s.cfl (here 's' is varname, 'cfl' functionName, and isAttribute true) or
1996 * grid.getDataPointer (here 's' is varname, 'getDataPointer' functionName, and isAttribute
1997 * false)
1998 *
1999 * Important! Return value: New reference or nullptr
2000 * Caller of this function needs to handle reference count of returned object. */
2001static PyObject *callPythonFunction(string varName, string functionName, bool isAttribute = false)
2002{
2003 if ((varName == "") || (functionName == "")) {
2004 if (MANTA::with_debug) {
2005 cout << "Fluid: Missing Python variable name and/or function name -- name is: " << varName
2006 << ", function name is: " << functionName << endl;
2007 }
2008 return nullptr;
2009 }
2010
2011 PyGILState_STATE gilstate = PyGILState_Ensure();
2012 PyObject *var = nullptr, *func = nullptr, *returnedValue = nullptr;
2013
2014 /* Be sure to initialize Python before using it. */
2015 Py_Initialize();
2016
2017 /* Get pyobject that holds result value. */
2018 if (!manta_main_module) {
2019 PyGILState_Release(gilstate);
2020 return nullptr;
2021 }
2022
2023 /* Ensure that requested variable is present in module - avoid attribute errors later on. */
2024 if (!PyObject_HasAttrString(manta_main_module, varName.c_str())) {
2025 PyGILState_Release(gilstate);
2026 return nullptr;
2027 }
2028
2029 var = PyObject_GetAttrString(manta_main_module, varName.c_str());
2030 if (!var) {
2031 PyErr_Clear();
2032 PyGILState_Release(gilstate);
2033 return nullptr;
2034 }
2035
2036 func = PyObject_GetAttrString(var, functionName.c_str());
2037
2038 Py_DECREF(var);
2039 if (!func) {
2040 PyErr_Clear();
2041 PyGILState_Release(gilstate);
2042 return nullptr;
2043 }
2044
2045 if (!isAttribute) {
2046 returnedValue = PyObject_CallObject(func, nullptr);
2047 if (returnedValue == nullptr) {
2048 /* Print any unexpected errors, also clear them. */
2049 PyErr_Print();
2050 }
2051 Py_DECREF(func);
2052 }
2053
2054 PyGILState_Release(gilstate);
2055 return (!isAttribute) ? returnedValue : func;
2056}
2057
2058/* Argument of this function may be a nullptr.
2059 * If it's not function will handle the reference count decrement of that argument. */
2060static void *pyObjectToPointer(PyObject *inputObject)
2061{
2062 if (!inputObject) {
2063 return nullptr;
2064 }
2065
2066 PyGILState_STATE gilstate = PyGILState_Ensure();
2067
2068 PyObject *encoded = PyUnicode_AsUTF8String(inputObject);
2069 char *result = PyBytes_AsString(encoded);
2070
2071 Py_DECREF(inputObject);
2072
2073 string str(result);
2074 istringstream in(str);
2075 void *dataPointer = nullptr;
2076 in >> dataPointer;
2077
2078 Py_DECREF(encoded);
2079
2080 PyGILState_Release(gilstate);
2081 return dataPointer;
2082}
2083
2084/* Argument of this function may be a nullptr.
2085 * If it's not function will handle the reference count decrement of that argument. */
2086static double pyObjectToDouble(PyObject *inputObject)
2087{
2088 if (!inputObject) {
2089 return 0.0;
2090 }
2091
2092 PyGILState_STATE gilstate = PyGILState_Ensure();
2093
2094 /* Cannot use PyFloat_AsDouble() since its error check crashes.
2095 * Likely because of typedef 'Real' for 'float' types in Mantaflow. */
2096 double result = PyFloat_AS_DOUBLE(inputObject);
2097 Py_DECREF(inputObject);
2098
2099 PyGILState_Release(gilstate);
2100 return result;
2101}
2102
2103/* Argument of this function may be a nullptr.
2104 * If it's not function will handle the reference count decrement of that argument. */
2105static long pyObjectToLong(PyObject *inputObject)
2106{
2107 if (!inputObject) {
2108 return 0;
2109 }
2110
2111 PyGILState_STATE gilstate = PyGILState_Ensure();
2112
2113 long result = PyLong_AsLong(inputObject);
2114 Py_DECREF(inputObject);
2115
2116 PyGILState_Release(gilstate);
2117 return result;
2118}
2119
2120template<class T> static T *getPointer(string pyObjectName, string pyFunctionName)
2121{
2122 return static_cast<T *>(pyObjectToPointer(callPythonFunction(pyObjectName, pyFunctionName)));
2123}
2124
2126{
2127 if (with_debug) {
2128 cout << "MANTA::getFrame()" << endl;
2129 }
2130
2131 string func = "frame";
2132 string id = to_string(mCurrentID);
2133 string solver = "s" + id;
2134
2135 return pyObjectToLong(callPythonFunction(solver, func, true));
2136}
2137
2139{
2140 if (with_debug) {
2141 cout << "MANTA::getTimestep()" << endl;
2142 }
2143
2144 string func = "timestep";
2145 string id = to_string(mCurrentID);
2146 string solver = "s" + id;
2147
2148 return (float)pyObjectToDouble(callPythonFunction(solver, func, true));
2149}
2150
2152{
2153 FluidDomainSettings *fds = fmd->domain;
2154 return ((fds->res_max[0] - fds->res_min[0]) != mResX ||
2155 (fds->res_max[1] - fds->res_min[1]) != mResY ||
2156 (fds->res_max[2] - fds->res_min[2]) != mResZ);
2157}
2158
2160{
2161 if (with_debug) {
2162 cout << "MANTA::adaptTimestep()" << endl;
2163 }
2164
2165 vector<string> pythonCommands;
2166 ostringstream ss;
2167
2168 ss << "fluid_adapt_time_step_" << mCurrentID << "()";
2169 pythonCommands.push_back(ss.str());
2170
2171 runPythonString(pythonCommands);
2172}
2173
2175{
2176 if (with_debug) {
2177 cout << "MANTA::updatePointers()" << endl;
2178 }
2179
2180 FluidDomainSettings *fds = fmd->domain;
2181
2182 bool liquid = !flush && (fds->type == FLUID_DOMAIN_TYPE_LIQUID);
2183 bool smoke = !flush && (fds->type == FLUID_DOMAIN_TYPE_GAS);
2184 bool noise = !flush && smoke && fds->flags & FLUID_DOMAIN_USE_NOISE;
2185 bool heat = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
2186 bool colors = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
2187 bool fire = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
2188 bool obstacle = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
2189 bool guiding = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
2190 bool invel = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
2191 bool outflow = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
2192 bool drops = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
2193 bool bubble = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
2194 bool floater = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
2195 bool tracer = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
2196 bool parts = !flush && liquid && (drops | bubble | floater | tracer);
2197 bool mesh = !flush && liquid && fds->flags & FLUID_DOMAIN_USE_MESH;
2198 bool meshvel = !flush && liquid && mesh && fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS;
2199
2200 string func = "getDataPointer";
2201 string funcNodes = "getNodesDataPointer";
2202 string funcTris = "getTrisDataPointer";
2203
2204 string id = to_string(mCurrentID);
2205 string s_ext = "_s" + id;
2206 string pp_ext = "_pp" + id;
2207 string snd_ext = "_sp" + id;
2208 string sm_ext = "_sm" + id;
2209 string mesh_ext = "_mesh" + id;
2210 string sn_ext = "_sn" + id;
2211
2212 mFlags = (smoke || liquid) ? getPointer<int>("flags" + s_ext, func) : nullptr;
2213 mPhiIn = (smoke || liquid) ? getPointer<float>("phiIn" + s_ext, func) : nullptr;
2214 mPhiStaticIn = (smoke || liquid) ? getPointer<float>("phiSIn" + s_ext, func) : nullptr;
2215 mVelocityX = (smoke || liquid) ? getPointer<float>("x_vel" + s_ext, func) : nullptr;
2216 mVelocityY = (smoke || liquid) ? getPointer<float>("y_vel" + s_ext, func) : nullptr;
2217 mVelocityZ = (smoke || liquid) ? getPointer<float>("z_vel" + s_ext, func) : nullptr;
2218 mForceX = (smoke || liquid) ? getPointer<float>("x_force" + s_ext, func) : nullptr;
2219 mForceY = (smoke || liquid) ? getPointer<float>("y_force" + s_ext, func) : nullptr;
2220 mForceZ = (smoke || liquid) ? getPointer<float>("z_force" + s_ext, func) : nullptr;
2221 mPressure = (smoke || liquid) ? getPointer<float>("pressure" + s_ext, func) : nullptr;
2222
2223 /* Outflow. */
2224 mPhiOutIn = (outflow) ? getPointer<float>("phiOutIn" + s_ext, func) : nullptr;
2225 mPhiOutStaticIn = (outflow) ? getPointer<float>("phiOutSIn" + s_ext, func) : nullptr;
2226
2227 /* Obstacles. */
2228 mPhiObsIn = (obstacle) ? getPointer<float>("phiObsIn" + s_ext, func) : nullptr;
2229 mPhiObsStaticIn = (obstacle) ? getPointer<float>("phiObsSIn" + s_ext, func) : nullptr;
2230 mObVelocityX = (obstacle) ? getPointer<float>("x_obvel" + s_ext, func) : nullptr;
2231 mObVelocityY = (obstacle) ? getPointer<float>("y_obvel" + s_ext, func) : nullptr;
2232 mObVelocityZ = (obstacle) ? getPointer<float>("z_obvel" + s_ext, func) : nullptr;
2233 mNumObstacle = (obstacle) ? getPointer<float>("numObs" + s_ext, func) : nullptr;
2234
2235 /* Guiding. */
2236 mPhiGuideIn = (guiding) ? getPointer<float>("phiGuideIn" + s_ext, func) : nullptr;
2237 mGuideVelocityX = (guiding) ? getPointer<float>("x_guidevel" + s_ext, func) : nullptr;
2238 mGuideVelocityY = (guiding) ? getPointer<float>("y_guidevel" + s_ext, func) : nullptr;
2239 mGuideVelocityZ = (guiding) ? getPointer<float>("z_guidevel" + s_ext, func) : nullptr;
2240 mNumGuide = (guiding) ? getPointer<float>("numGuides" + s_ext, func) : nullptr;
2241
2242 /* Initial velocities. */
2243 mInVelocityX = (invel) ? getPointer<float>("x_invel" + s_ext, func) : nullptr;
2244 mInVelocityY = (invel) ? getPointer<float>("y_invel" + s_ext, func) : nullptr;
2245 mInVelocityZ = (invel) ? getPointer<float>("z_invel" + s_ext, func) : nullptr;
2246
2247 /* Smoke. */
2248 mDensity = (smoke) ? getPointer<float>("density" + s_ext, func) : nullptr;
2249 mDensityIn = (smoke) ? getPointer<float>("densityIn" + s_ext, func) : nullptr;
2250 mShadow = (smoke) ? getPointer<float>("shadow" + s_ext, func) : nullptr;
2251 mEmissionIn = (smoke) ? getPointer<float>("emissionIn" + s_ext, func) : nullptr;
2252
2253 /* Heat. */
2254 mHeat = (heat) ? getPointer<float>("heat" + s_ext, func) : nullptr;
2255 mHeatIn = (heat) ? getPointer<float>("heatIn" + s_ext, func) : nullptr;
2256
2257 /* Fire. */
2258 mFlame = (fire) ? getPointer<float>("flame" + s_ext, func) : nullptr;
2259 mFuel = (fire) ? getPointer<float>("fuel" + s_ext, func) : nullptr;
2260 mReact = (fire) ? getPointer<float>("react" + s_ext, func) : nullptr;
2261 mFuelIn = (fire) ? getPointer<float>("fuelIn" + s_ext, func) : nullptr;
2262 mReactIn = (fire) ? getPointer<float>("reactIn" + s_ext, func) : nullptr;
2263
2264 /* Colors. */
2265 mColorR = (colors) ? getPointer<float>("color_r" + s_ext, func) : nullptr;
2266 mColorG = (colors) ? getPointer<float>("color_g" + s_ext, func) : nullptr;
2267 mColorB = (colors) ? getPointer<float>("color_b" + s_ext, func) : nullptr;
2268 mColorRIn = (colors) ? getPointer<float>("color_r_in" + s_ext, func) : nullptr;
2269 mColorGIn = (colors) ? getPointer<float>("color_g_in" + s_ext, func) : nullptr;
2270 mColorBIn = (colors) ? getPointer<float>("color_b_in" + s_ext, func) : nullptr;
2271
2272 /* Noise. */
2273 mDensityHigh = (noise) ? getPointer<float>("density" + sn_ext, func) : nullptr;
2274 mTextureU = (noise) ? getPointer<float>("texture_u" + s_ext, func) : nullptr;
2275 mTextureV = (noise) ? getPointer<float>("texture_v" + s_ext, func) : nullptr;
2276 mTextureW = (noise) ? getPointer<float>("texture_w" + s_ext, func) : nullptr;
2277 mTextureU2 = (noise) ? getPointer<float>("texture_u2" + s_ext, func) : nullptr;
2278 mTextureV2 = (noise) ? getPointer<float>("texture_v2" + s_ext, func) : nullptr;
2279 mTextureW2 = (noise) ? getPointer<float>("texture_w2" + s_ext, func) : nullptr;
2280
2281 /* Fire with noise. */
2282 mFlameHigh = (noise && fire) ? getPointer<float>("flame" + sn_ext, func) : nullptr;
2283 mFuelHigh = (noise && fire) ? getPointer<float>("fuel" + sn_ext, func) : nullptr;
2284 mReactHigh = (noise && fire) ? getPointer<float>("react" + sn_ext, func) : nullptr;
2285
2286 /* Colors with noise. */
2287 mColorRHigh = (noise && colors) ? getPointer<float>("color_r" + sn_ext, func) : nullptr;
2288 mColorGHigh = (noise && colors) ? getPointer<float>("color_g" + sn_ext, func) : nullptr;
2289 mColorBHigh = (noise && colors) ? getPointer<float>("color_b" + sn_ext, func) : nullptr;
2290
2291 /* Liquid. */
2292 mPhi = (liquid) ? getPointer<float>("phi" + s_ext, func) : nullptr;
2293 mFlipParticleData = (liquid) ? getPointer<vector<pData>>("pp" + s_ext, func) : nullptr;
2294 mFlipParticleVelocity = (liquid) ? getPointer<vector<pVel>>("pVel" + pp_ext, func) : nullptr;
2295
2296 /* Mesh. */
2297 mMeshNodes = (mesh) ? getPointer<vector<Node>>("mesh" + sm_ext, funcNodes) : nullptr;
2298 mMeshTriangles = (mesh) ? getPointer<vector<Triangle>>("mesh" + sm_ext, funcTris) : nullptr;
2299
2300 /* Mesh velocities. */
2301 mMeshVelocities = (meshvel) ? getPointer<vector<pVel>>("mVel" + mesh_ext, func) : nullptr;
2302
2303 /* Secondary particles. */
2304 mParticleData = (parts) ? getPointer<vector<pData>>("ppSnd" + snd_ext, func) : nullptr;
2305 mParticleVelocity = (parts) ? getPointer<vector<pVel>>("pVelSnd" + pp_ext, func) : nullptr;
2306 mParticleLife = (parts) ? getPointer<vector<float>>("pLifeSnd" + pp_ext, func) : nullptr;
2307
2308 mFlipFromFile = false;
2309 mMeshFromFile = false;
2310 mParticlesFromFile = false;
2311 mSmokeFromFile = false;
2312 mNoiseFromFile = false;
2313}
2314
2316{
2317 string extension = FLUID_DOMAIN_EXTENSION_UNI;
2318 return BLI_exists(
2319 getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, extension, framenr).c_str());
2320}
2321
2322bool MANTA::hasData(FluidModifierData *fmd, int framenr)
2323{
2324 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2325 bool exists = BLI_exists(
2326 getFile(fmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_DATA, extension, framenr).c_str());
2327
2328 /* Check single file naming. */
2329 if (!exists) {
2330 string filename = (mUsingSmoke) ? FLUID_NAME_DENSITY : FLUID_NAME_PP;
2331 exists = BLI_exists(getFile(fmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str());
2332 }
2333 if (with_debug) {
2334 cout << "Fluid: Has Data: " << exists << endl;
2335 }
2336
2337 return exists;
2338}
2339
2340bool MANTA::hasNoise(FluidModifierData *fmd, int framenr)
2341{
2342 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2343 bool exists = BLI_exists(
2344 getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_NOISE, extension, framenr).c_str());
2345
2346 /* Check single file naming. */
2347 if (!exists) {
2348 extension = getCacheFileEnding(fmd->domain->cache_data_format);
2349 exists = BLI_exists(
2350 getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr)
2351 .c_str());
2352 }
2353 /* Check single file naming with deprecated extension. */
2354 if (!exists) {
2355 extension = getCacheFileEnding(fmd->domain->cache_noise_format);
2356 exists = BLI_exists(
2357 getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr)
2358 .c_str());
2359 }
2360 if (with_debug) {
2361 cout << "Fluid: Has Noise: " << exists << endl;
2362 }
2363
2364 return exists;
2365}
2366
2367bool MANTA::hasMesh(FluidModifierData *fmd, int framenr)
2368{
2369 string extension = getCacheFileEnding(fmd->domain->cache_mesh_format);
2370 bool exists = BLI_exists(
2371 getFile(fmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_MESH, extension, framenr).c_str());
2372
2373 /* Check old file naming. */
2374 if (!exists) {
2375 exists = BLI_exists(
2376 getFile(fmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_LMESH, extension, framenr).c_str());
2377 }
2378 if (with_debug) {
2379 cout << "Fluid: Has Mesh: " << exists << endl;
2380 }
2381
2382 return exists;
2383}
2384
2386{
2387 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2388 bool exists = BLI_exists(
2389 getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PARTICLES, extension, framenr).c_str());
2390
2391 /* Check single file naming. */
2392 if (!exists) {
2393 extension = getCacheFileEnding(fmd->domain->cache_data_format);
2394 exists = BLI_exists(
2395 getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr)
2396 .c_str());
2397 }
2398 /* Check single file naming with deprecated extension. */
2399 if (!exists) {
2401 exists = BLI_exists(
2402 getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr)
2403 .c_str());
2404 }
2405 if (with_debug) {
2406 cout << "Fluid: Has Particles: " << exists << endl;
2407 }
2408
2409 return exists;
2410}
2411
2412bool MANTA::hasGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
2413{
2414 string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE;
2415 string filename = (sourceDomain) ? FLUID_NAME_DATA : FLUID_NAME_GUIDING;
2416 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2417 bool exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str());
2418
2419 /* Check old file naming. */
2420 if (!exists) {
2421 filename = (sourceDomain) ? FLUID_NAME_VEL : FLUID_NAME_GUIDEVEL;
2422 exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str());
2423 }
2424
2425 if (with_debug) {
2426 cout << "Fluid: Has Guiding: " << exists << endl;
2427 }
2428
2429 return exists;
2430}
2431
2432string MANTA::getDirectory(FluidModifierData *fmd, string subdirectory)
2433{
2434 char directory[FILE_MAX];
2435 BLI_path_join(directory, sizeof(directory), fmd->domain->cache_directory, subdirectory.c_str());
2436 BLI_path_make_safe(directory);
2437 return directory;
2438}
2439
2440string MANTA::getFile(
2441 FluidModifierData *fmd, string subdirectory, string fname, string extension, int framenr)
2442{
2443 char targetFile[FILE_MAX];
2444 string path = getDirectory(fmd, subdirectory);
2445 string filename = fname + "_####" + extension;
2446 BLI_path_join(targetFile, sizeof(targetFile), path.c_str(), filename.c_str());
2447 BLI_path_frame(targetFile, sizeof(targetFile), framenr, 0);
2448 return targetFile;
2449}
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
void * BLI_gzopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:360
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
Definition fileops_c.cc:414
bool BLI_path_make_safe(char *path) ATTR_NONNULL(1)
#define FILE_MAX
#define BLI_path_join(...)
bool BLI_path_frame(char *path, size_t path_maxncpy, int frame, int digits) ATTR_NONNULL(1)
#define UNUSED_VARS(...)
#define FLUID_DOMAIN_LIQUID_SCRIPT
#define FLUID_NAME_EMISSION
#define FLUID_NAME_TRAPPEDAIR_PARTICLES
#define FLUID_CACHE_VERSION
#define FLUID_NAME_FUEL_NOISE
#define FLUID_NAME_COLORG_NOISE
#define FLUID_NAME_COLORB_NOISE
#define FLUID_NAME_FLAGS_MESH
#define FLUID_NAME_NOISE
#define FLUID_DOMAIN_DIR_DATA
#define FLUID_NAME_PHIPARTS_MESH
#define FLUID_NAME_DATA
#define FLUID_DOMAIN_DIR_PARTICLES
#define FLUID_NAME_PP
#define FLUID_NAME_TMPFLAGS
@ FLUID_DOMAIN_BORDER_BOTTOM
@ FLUID_DOMAIN_BORDER_LEFT
@ FLUID_DOMAIN_BORDER_RIGHT
@ FLUID_DOMAIN_BORDER_FRONT
@ FLUID_DOMAIN_BORDER_TOP
@ FLUID_DOMAIN_BORDER_BACK
@ FLUID_DOMAIN_MESH_IMPROVED
#define FLUID_NAME_PHIOBS_PARTICLES
#define FLUID_NAME_FORCES
#define FLUID_NAME_PHIIN_NOISE
#define FLUID_NAME_WAVECREST_PARTICLES
#define FLUID_NAME_VELOCITY_PARTICLES
#define FLUID_NAME_EMISSIONIN
#define FLUID_NAME_PHIGUIDEIN
#define FLUID_NAME_PLIFE_PARTICLES
#define FLUID_NAME_PFORCE_PARTICLES
#define FLUID_NAME_PHITMP
#define FLUID_NAME_VELOCITYOLD
#define FLUID_NAME_PHIOBSSIN
#define FLUID_NAME_VEL
#define FLUID_NAME_PP_PARTICLES
#define FLUID_NAME_KINETICENERGY_PARTICLES
#define FLUID_NAME_FORCE_Y
#define FLUID_NAME_PINDEX
#define FLUID_NAME_PVEL
#define FLUID_NAME_FUELIN
#define FLUID_NAME_PARTICLES
#define FLUID_DOMAIN_EXTENSION_BINOBJ
#define FLUID_NAME_FORCE_Z
#define FLUID_NAME_UV0
#define FLUID_DOMAIN_SMOKE_SCRIPT
#define FLUID_NAME_HEAT
@ VDB_COMPRESSION_NONE
@ VDB_COMPRESSION_ZIP
@ VDB_COMPRESSION_BLOSC
#define FLUID_NAME_GUIDEVEL_Z
#define FLUID_NAME_PVEL_PARTICLES
@ SNDPARTICLE_BOUNDARY_DELETE
@ SNDPARTICLE_BOUNDARY_PUSHOUT
#define FLUID_NAME_LMESH
#define FLUID_NAME_GUIDEVEL_X
#define FLUID_NAME_TEXTURE_U
#define FLUID_DOMAIN_DIR_MESH
#define FLUID_DOMAIN_DIR_GUIDE
#define FLUID_NAME_PHIIN
#define FLUID_DOMAIN_DIR_SCRIPT
#define FLUID_NAME_PARTSVEL_PARTICLES
#define FLUID_NAME_TMPIN_NOISE
#define FLUID_NAME_PHI
#define FLUID_NAME_OBVEL_X
#define FLUID_NAME_PHIOBS
#define FLUID_NAME_CONFIG
#define FLUID_NAME_COLORR_NOISE
#define FLUID_DOMAIN_EXTENSION_OPENVDB
#define FLUID_NAME_GPI_MESH
#define FLUID_NAME_VELOCITYZ
#define FLUID_NAME_GUIDEVELC
#define FLUID_NAME_VELOCITYTMP
#define FLUID_NAME_VELOCITYY
#define FLUID_NAME_PINDEX_MESH
#define FLUID_NAME_PHIOUT_PARTICLES
#define FLUID_NAME_CURVATURE
#define FLUID_NAME_PHISIN
@ FLUID_DOMAIN_TYPE_GAS
@ FLUID_DOMAIN_TYPE_LIQUID
#define FLUID_NAME_VELOCITY_MESH
#define FLUID_NAME_MESH
#define FLUID_DOMAIN_EXTENSION_OBJ
#define FLUID_NAME_INVEL_Z
#define FLUID_NAME_INVELC
#define FLUID_NAME_FLAGS_NOISE
#define FLUID_NAME_PARTSLIFE_PARTICLES
#define FLUID_NAME_COLORR
#define FLUID_NAME_TEXTURE_U2
#define FLUID_NAME_PHIOUT
#define FLUID_NAME_TEXTURE_V2
#define FLUID_NAME_EMISSIONIN_NOISE
#define FLUID_NAME_GUIDEVEL_Y
#define FLUID_NAME_TEXTURE_W2
#define FLUID_NAME_FUEL
#define FLUID_NAME_DENSITY_NOISE
@ VDB_PRECISION_MINI_FLOAT
@ VDB_PRECISION_FULL_FLOAT
@ VDB_PRECISION_HALF_FLOAT
#define FLUID_NAME_VELT
#define FLUID_NAME_PHIOUTIN
#define FLUID_NAME_NUMOBS
#define FLUID_NAME_COLORG
#define FLUID_NAME_PHIOUTSIN
#define FLUID_NAME_GUIDEVEL
#define FLUID_NAME_VELOCITYPARTS
#define FLUID_DOMAIN_DIR_CONFIG
#define FLUID_NAME_PHIOBS_NOISE
#define FLUID_NAME_INVEL_Y
#define FLUID_NAME_SHADOW
#define FLUID_NAME_PARTSVELOCITY
#define FLUID_NAME_OBVEL_Y
#define FLUID_NAME_VELOCITYVEC_MESH
#define FLUID_NAME_COLORB
#define FLUID_NAME_OBVELC
#define FLUID_NAME_COLORGIN
#define FLUID_NAME_VELOCITY
#define FLUID_NAME_PHIOBSIN
#define FLUID_NAME_PHI_PARTICLES
#define FLUID_NAME_FORCE_X
#define FLUID_NAME_NEIGHBORRATIO_PARTICLES
#define FLUID_NAME_PARTS_PARTICLES
#define FLUID_NAME_COLORBIN
@ FLUID_DOMAIN_METHOD_APIC
#define FLUID_NAME_GUIDING
#define FLUID_NAME_DENSITY
#define FLUID_NAME_PARTSFORCE_PARTICLES
#define FLUID_NAME_REACT
#define FLUID_NAME_VELOCITY_GUIDE
#define FLUID_DOMAIN_EXTENSION_UNI
#define FLUID_NAME_TEMPERATUREIN
#define FLUID_NAME_INVEL_X
#define FLUID_NAME_GPI
#define FLUID_NAME_FLAME
#define FLUID_NAME_FLAGS
#define FLUID_NAME_REACTIN
struct FluidDomainSettings FluidDomainSettings
#define FLUID_NAME_PRESSURE
#define FLUID_NAME_MAPWEIGHTS
#define FLUID_NAME_FLAME_NOISE
@ FLUID_DOMAIN_ACTIVE_COLORS
@ FLUID_DOMAIN_ACTIVE_FIRE
@ FLUID_DOMAIN_ACTIVE_INVEL
@ FLUID_DOMAIN_ACTIVE_GUIDE
@ FLUID_DOMAIN_ACTIVE_OUTFLOW
@ FLUID_DOMAIN_ACTIVE_HEAT
@ FLUID_DOMAIN_ACTIVE_OBSTACLE
#define FLUID_NAME_PHIOUT_NOISE
#define FLUID_NAME_VELOCITY_NOISE
#define FLUID_NAME_TEXTURE_W
#define FLUID_NAME_PP_MESH
@ FLUID_DOMAIN_FILE_BIN_OBJECT
@ FLUID_DOMAIN_FILE_RAW
@ FLUID_DOMAIN_FILE_OBJECT
@ FLUID_DOMAIN_FILE_UNI
@ FLUID_DOMAIN_FILE_OPENVDB
#define FLUID_DOMAIN_DIR_NOISE
#define FLUID_NAME_OBVEL_Z
@ FLUID_DOMAIN_USE_MESH
@ FLUID_DOMAIN_DELETE_IN_OBSTACLE
@ FLUID_DOMAIN_USE_RESUMABLE_CACHE
@ FLUID_DOMAIN_USE_DISSOLVE_LOG
@ FLUID_DOMAIN_USE_DIFFUSION
@ FLUID_DOMAIN_USE_ADAPTIVE_TIME
@ FLUID_DOMAIN_USE_GUIDE
@ FLUID_DOMAIN_USE_VISCOSITY
@ FLUID_DOMAIN_USE_SPEED_VECTORS
@ FLUID_DOMAIN_USE_NOISE
@ FLUID_DOMAIN_USE_FRACTIONS
@ FLUID_DOMAIN_USE_DISSOLVE
#define FLUID_NAME_PHIPARTS
#define FLUID_NAME_NUMGUIDES
#define FLUID_NAME_OBVEL
#define FLUID_NAME_HEATIN
#define FLUID_NAME_UV1
#define FLUID_NAME_FLAGS_PARTICLES
#define FLUID_NAME_TEMPERATURE
#define FLUID_NAME_PHI_MESH
#define FLUID_NAME_FRACTIONS
#define FLUID_NAME_REACT_NOISE
#define FLUID_NAME_TEXTURE_V
#define FLUID_NAME_PARTS
#define FLUID_NAME_COLORRIN
@ FLUID_DOMAIN_PARTICLE_SPRAY
@ FLUID_DOMAIN_PARTICLE_FOAM
@ FLUID_DOMAIN_PARTICLE_TRACER
@ FLUID_DOMAIN_PARTICLE_BUBBLE
#define FLUID_NAME_ENERGY
#define FLUID_NAME_VELOCITYX
#define FLUID_NAME_DENSITYIN
#define FLUID_NAME_NORMAL_PARTICLES
#define FLUID_NAME_WEIGHTGUIDE
#define FLUID_DOMAIN_EXTENSION_RAW
static string getBooleanString(int value)
static PyObject * callPythonFunction(string varName, string functionName, bool isAttribute=false)
static string getCacheFileEnding(char cache_format)
static PyObject * manta_python_main_module_create(const char *filename)
static PyObject * manta_main_module
static T * getPointer(string pyObjectName, string pyFunctionName)
static string escapePath(string const &s)
static void manta_python_main_module_restore(PyObject *main_mod)
static void * pyObjectToPointer(PyObject *inputObject)
static void manta_python_main_module_clear()
static void manta_python_main_module_backup(PyObject **r_main_mod)
static PyObject * manta_python_main_module_ensure()
static void manta_python_main_module_activate(PyObject *mod_main)
static double pyObjectToDouble(PyObject *inputObject)
static long pyObjectToLong(PyObject *inputObject)
#define str(s)
const std::string fluid_with_outflow
const std::string fluid_variables_noise
const std::string fluid_with_fractions
const std::string fluid_solver_viscosity
const std::string fluid_variables_particles
const std::string fluid_with_invel
const std::string fluid_solver_particles
const std::string fluid_solver_mesh
const std::string manta_import
const std::string manta_debuglevel
const std::string fluid_with_sndparts
const std::string fluid_variables
const std::string fluid_solver_noise
const std::string fluid_variables_viscosity
const std::string fluid_time_stepping
const std::string fluid_solver
const std::string fluid_solver_guiding
const std::string fluid_variables_guiding
const std::string fluid_variables_mesh
const std::string fluid_with_obstacle
static const char * to_string(const Interpolation &interp)
Definition gl_shader.cc:103
#define in
#define pow
const std::string liquid_alloc_viscosity
const std::string liquid_variables
const std::string liquid_variables_particles
const std::string liquid_alloc_particles
const std::string liquid_alloc
const std::string liquid_alloc_curvature
const std::string liquid_alloc_mesh
const std::string liquid_init_phi
format
#define T
static float noise(int n)
Py_DECREF(oname)
const std::string smoke_alloc_noise
const std::string smoke_alloc_heat
const std::string smoke_alloc_colors
const std::string smoke_alloc_fire_noise
const std::string smoke_with_colors
const std::string smoke_with_fire
const std::string smoke_with_heat
const std::string smoke_variables
const std::string smoke_variables_noise
const std::string smoke_alloc_colors_noise
const std::string smoke_init_colors_noise
const std::string smoke_init_colors
const std::string smoke_wavelet_noise
const std::string smoke_alloc_fire
const std::string smoke_alloc
struct Object * guide_parent
struct FluidDomainSettings * domain
bool exportSmokeScript(struct FluidModifierData *fmd)
bool bakeNoise(FluidModifierData *fmd, int framenr)
bool writeNoise(FluidModifierData *fmd, int framenr)
bool initFireHigh(struct FluidModifierData *fmd=nullptr)
bool hasNoise(FluidModifierData *fmd, int framenr)
bool exportLiquidScript(struct FluidModifierData *fmd)
bool readData(FluidModifierData *fmd, int framenr, bool resumable)
bool initOutflow(FluidModifierData *fmd=nullptr)
bool writeConfiguration(FluidModifierData *fmd, int framenr)
bool initFire(struct FluidModifierData *fmd=nullptr)
bool writeData(FluidModifierData *fmd, int framenr)
static int with_debug
Definition MANTA_main.h:406
bool needsRealloc(FluidModifierData *fmd)
bool readParticles(FluidModifierData *fmd, int framenr, bool resumable)
bool readMesh(FluidModifierData *fmd, int framenr)
bool readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
bool initLiquidViscosity(FluidModifierData *fmd=nullptr)
bool bakeMesh(FluidModifierData *fmd, int framenr)
bool initLiquid(FluidModifierData *fmd=nullptr)
bool initFractions(FluidModifierData *fmd=nullptr)
bool initLiquidMesh(FluidModifierData *fmd=nullptr)
bool hasMesh(FluidModifierData *fmd, int framenr)
bool initGuiding(FluidModifierData *fmd=nullptr)
bool readConfiguration(FluidModifierData *fmd, int framenr)
virtual ~MANTA()
bool bakeGuiding(FluidModifierData *fmd, int framenr)
static atomic< int > solverID
Definition MANTA_main.h:405
bool hasParticles(FluidModifierData *fmd, int framenr)
bool initColorsHigh(struct FluidModifierData *fmd=nullptr)
bool initObstacle(FluidModifierData *fmd=nullptr)
float getTimestep()
bool initColors(struct FluidModifierData *fmd=nullptr)
bool readNoise(FluidModifierData *fmd, int framenr, bool resumable)
bool initSndParts(FluidModifierData *fmd=nullptr)
bool initCurvature(FluidModifierData *fmd=nullptr)
bool hasGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
bool initHeat(struct FluidModifierData *fmd=nullptr)
bool bakeParticles(FluidModifierData *fmd, int framenr)
MANTA(int *res, struct FluidModifierData *fmd)
bool bakeData(FluidModifierData *fmd, int framenr)
bool initInVelocity(FluidModifierData *fmd=nullptr)
void adaptTimestep()
int getFrame()
void updatePointers(FluidModifierData *fmd, bool flush=false)
bool hasData(FluidModifierData *fmd, int framenr)
bool updateVariables(FluidModifierData *fmd)
bool hasConfig(FluidModifierData *fmd, int framenr)
bool initLiquidSndParts(FluidModifierData *fmd=nullptr)