Blender V4.5
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) {
648 Py_DECREF(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 " << it->second
1147 << endl;
1148 return "";
1149 }
1150
1151 return it->second;
1152}
1153
1154string MANTA::parseLine(const string &line)
1155{
1156 if (line.size() == 0) {
1157 return "";
1158 }
1159 string res;
1160 int currPos = 0, start_del = 0, end_del = -1;
1161 bool readingVar = false;
1162 const char delimiter = '$';
1163 while (currPos < line.size()) {
1164 if (line[currPos] == delimiter && !readingVar) {
1165 readingVar = true;
1166 start_del = currPos + 1;
1167 res += line.substr(end_del + 1, currPos - end_del - 1);
1168 }
1169 else if (line[currPos] == delimiter && readingVar) {
1170 readingVar = false;
1171 end_del = currPos;
1172 res += getRealValue(line.substr(start_del, currPos - start_del));
1173 }
1174 currPos++;
1175 }
1176 res += line.substr(end_del + 1, line.size() - end_del);
1177 return res;
1178}
1179
1180string MANTA::parseScript(const string &setup_string, FluidModifierData *fmd)
1181{
1182 if (MANTA::with_debug) {
1183 cout << "MANTA::parseScript()" << endl;
1184 }
1185
1186 istringstream f(setup_string);
1187 ostringstream res;
1188 string line;
1189
1190 /* Update RNA map if modifier data is handed over. */
1191 if (fmd) {
1192 initializeRNAMap(fmd);
1193 }
1194 while (getline(f, line)) {
1195 res << parseLine(line) << "\n";
1196 }
1197 return res.str();
1198}
1199
1201static string escapePath(string const &s)
1202{
1203 string result;
1204 for (char c : s) {
1205 if (c == '\\') {
1206 result += "\\\\";
1207 }
1208 else if (c == '\'') {
1209 result += "\\\'";
1210 }
1211 else {
1212 result += c;
1213 }
1214 }
1215 return result;
1216}
1217
1219{
1220 if (with_debug) {
1221 cout << "MANTA::writeConfiguration()" << endl;
1222 }
1223
1224 FluidDomainSettings *fds = fmd->domain;
1225
1226 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_CONFIG);
1228 string file = getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, format, framenr);
1229
1230 /* Create 'config' subdir if it does not exist already. */
1231 BLI_dir_create_recursive(directory.c_str());
1232
1233 /* Open new file with some compression. */
1234 gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "wb1");
1235 if (!gzf) {
1236 cerr << "Fluid Error -- Cannot open file " << file << endl;
1237 return false;
1238 }
1239
1240 gzwrite(gzf, &fds->active_fields, sizeof(int));
1241 gzwrite(gzf, &fds->res, 3 * sizeof(int));
1242 gzwrite(gzf, &fds->dx, sizeof(float));
1243 gzwrite(gzf, &fds->dt, sizeof(float));
1244 gzwrite(gzf, &fds->p0, 3 * sizeof(float));
1245 gzwrite(gzf, &fds->p1, 3 * sizeof(float));
1246 gzwrite(gzf, &fds->dp0, 3 * sizeof(float));
1247 gzwrite(gzf, &fds->shift, 3 * sizeof(int));
1248 gzwrite(gzf, &fds->obj_shift_f, 3 * sizeof(float));
1249 gzwrite(gzf, &fds->obmat, 16 * sizeof(float));
1250 gzwrite(gzf, &fds->base_res, 3 * sizeof(int));
1251 gzwrite(gzf, &fds->res_min, 3 * sizeof(int));
1252 gzwrite(gzf, &fds->res_max, 3 * sizeof(int));
1253 gzwrite(gzf, &fds->active_color, 3 * sizeof(float));
1254 gzwrite(gzf, &fds->time_total, sizeof(int));
1255 gzwrite(gzf, &FLUID_CACHE_VERSION, 4 * sizeof(char));
1256
1257 return (gzclose(gzf) == Z_OK);
1258}
1259
1261{
1262 if (with_debug) {
1263 cout << "MANTA::writeData()" << endl;
1264 }
1265
1266 ostringstream ss;
1267 vector<string> pythonCommands;
1268 FluidDomainSettings *fds = fmd->domain;
1269
1270 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_DATA);
1271 string volume_format = getCacheFileEnding(fds->cache_data_format);
1272 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1273
1274 if (mUsingSmoke) {
1275 ss.str("");
1276 ss << "smoke_save_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1277 << ", '" << volume_format << "', " << resumable_cache << ")";
1278 pythonCommands.push_back(ss.str());
1279 }
1280 if (mUsingLiquid) {
1281 ss.str("");
1282 ss << "liquid_save_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1283 << ", '" << volume_format << "', " << resumable_cache << ")";
1284 pythonCommands.push_back(ss.str());
1285 }
1286 return runPythonString(pythonCommands);
1287}
1288
1290{
1291 if (with_debug) {
1292 cout << "MANTA::writeNoise()" << endl;
1293 }
1294
1295 ostringstream ss;
1296 vector<string> pythonCommands;
1297 FluidDomainSettings *fds = fmd->domain;
1298
1299 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_NOISE);
1300 string volume_format = getCacheFileEnding(fds->cache_data_format);
1301 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1302
1303 if (mUsingSmoke && mUsingNoise) {
1304 ss.str("");
1305 ss << "smoke_save_noise_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1306 << ", '" << volume_format << "', " << resumable_cache << ")";
1307 pythonCommands.push_back(ss.str());
1308 }
1309 return runPythonString(pythonCommands);
1310}
1311
1313{
1314 if (with_debug) {
1315 cout << "MANTA::readConfiguration()" << endl;
1316 }
1317
1318 FluidDomainSettings *fds = fmd->domain;
1319 float dummy;
1320
1321 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_CONFIG);
1323 string file = getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, format, framenr);
1324
1325 if (!hasConfig(fmd, framenr)) {
1326 return false;
1327 }
1328
1329 gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); /* Do some compression. */
1330 if (!gzf) {
1331 cerr << "Fluid Error -- Cannot open file " << file << endl;
1332 return false;
1333 }
1334
1335 gzread(gzf, &fds->active_fields, sizeof(int));
1336 gzread(gzf, &fds->res, 3 * sizeof(int));
1337 gzread(gzf, &fds->dx, sizeof(float));
1338 gzread(gzf, &dummy, sizeof(float)); /* dt not needed right now. */
1339 gzread(gzf, &fds->p0, 3 * sizeof(float));
1340 gzread(gzf, &fds->p1, 3 * sizeof(float));
1341 gzread(gzf, &fds->dp0, 3 * sizeof(float));
1342 gzread(gzf, &fds->shift, 3 * sizeof(int));
1343 gzread(gzf, &fds->obj_shift_f, 3 * sizeof(float));
1344 gzread(gzf, &fds->obmat, 16 * sizeof(float));
1345 gzread(gzf, &fds->base_res, 3 * sizeof(int));
1346 gzread(gzf, &fds->res_min, 3 * sizeof(int));
1347 gzread(gzf, &fds->res_max, 3 * sizeof(int));
1348 gzread(gzf, &fds->active_color, 3 * sizeof(float));
1349 gzread(gzf, &fds->time_total, sizeof(int));
1350 gzread(gzf, &fds->cache_id, 4 * sizeof(char)); /* Older caches might have no id. */
1351
1352 fds->total_cells = fds->res[0] * fds->res[1] * fds->res[2];
1353
1354 return (gzclose(gzf) == Z_OK);
1355}
1356
1357bool MANTA::readData(FluidModifierData *fmd, int framenr, bool resumable)
1358{
1359 if (with_debug) {
1360 cout << "MANTA::readData()" << endl;
1361 }
1362
1363 if (!mUsingSmoke && !mUsingLiquid) {
1364 return false;
1365 }
1366
1367 ostringstream ss;
1368 vector<string> pythonCommands;
1369 FluidDomainSettings *fds = fmd->domain;
1370 bool result = true;
1371
1372 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_DATA);
1373 string volume_format = getCacheFileEnding(fds->cache_data_format);
1374 string resumable_cache = (!resumable) ? "False" : "True";
1375
1376 /* Sanity check: Are cache files present? */
1377 if (!hasData(fmd, framenr)) {
1378 return false;
1379 }
1380
1381 if (mUsingSmoke) {
1382 ss.str("");
1383 ss << "smoke_load_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1384 << ", '" << volume_format << "', " << resumable_cache << ")";
1385 pythonCommands.push_back(ss.str());
1386 result &= runPythonString(pythonCommands);
1387 return (mSmokeFromFile = result);
1388 }
1389 if (mUsingLiquid) {
1390 ss.str("");
1391 ss << "liquid_load_data_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1392 << ", '" << volume_format << "', " << resumable_cache << ")";
1393 pythonCommands.push_back(ss.str());
1394 result &= runPythonString(pythonCommands);
1395 return (mFlipFromFile = result);
1396 }
1397 return result;
1398}
1399
1400bool MANTA::readNoise(FluidModifierData *fmd, int framenr, bool resumable)
1401{
1402 if (with_debug) {
1403 cout << "MANTA::readNoise()" << endl;
1404 }
1405
1406 if (!mUsingSmoke || !mUsingNoise) {
1407 return false;
1408 }
1409
1410 ostringstream ss;
1411 vector<string> pythonCommands;
1412 FluidDomainSettings *fds = fmd->domain;
1413
1414 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_NOISE);
1415 string resumable_cache = (!resumable) ? "False" : "True";
1416
1417 /* Support older caches which had more granular file format control. */
1418 char format = (!strcmp(fds->cache_id, FLUID_CACHE_VERSION)) ? fds->cache_data_format :
1419 fds->cache_noise_format;
1420 string volume_format = getCacheFileEnding(format);
1421
1422 /* Sanity check: Are cache files present? */
1423 if (!hasNoise(fmd, framenr)) {
1424 return false;
1425 }
1426
1427 ss.str("");
1428 ss << "smoke_load_noise_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1429 << ", '" << volume_format << "', " << resumable_cache << ")";
1430 pythonCommands.push_back(ss.str());
1431
1432 return (mNoiseFromFile = runPythonString(pythonCommands));
1433}
1434
1435bool MANTA::readMesh(FluidModifierData *fmd, int framenr)
1436{
1437 if (with_debug) {
1438 cout << "MANTA::readMesh()" << endl;
1439 }
1440
1441 if (!mUsingLiquid || !mUsingMesh) {
1442 return false;
1443 }
1444
1445 ostringstream ss;
1446 vector<string> pythonCommands;
1447 FluidDomainSettings *fds = fmd->domain;
1448
1449 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_MESH);
1450 string mesh_format = getCacheFileEnding(fds->cache_mesh_format);
1451 string volume_format = getCacheFileEnding(fds->cache_data_format);
1452
1453 /* Sanity check: Are cache files present? */
1454 if (!hasMesh(fmd, framenr)) {
1455 return false;
1456 }
1457
1458 ss.str("");
1459 ss << "liquid_load_mesh_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1460 << ", '" << mesh_format << "')";
1461 pythonCommands.push_back(ss.str());
1462
1463 if (mUsingMVel) {
1464 ss.str("");
1465 ss << "liquid_load_meshvel_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1466 << ", '" << volume_format << "')";
1467 pythonCommands.push_back(ss.str());
1468 }
1469
1470 return (mMeshFromFile = runPythonString(pythonCommands));
1471}
1472
1473bool MANTA::readParticles(FluidModifierData *fmd, int framenr, bool resumable)
1474{
1475 if (with_debug) {
1476 cout << "MANTA::readParticles()" << endl;
1477 }
1478
1479 if (!mUsingLiquid) {
1480 return false;
1481 }
1482 if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) {
1483 return false;
1484 }
1485
1486 ostringstream ss;
1487 vector<string> pythonCommands;
1488 FluidDomainSettings *fds = fmd->domain;
1489
1490 string directory = getDirectory(fmd, FLUID_DOMAIN_DIR_PARTICLES);
1491 string resumable_cache = (!resumable) ? "False" : "True";
1492
1493 /* Support older caches which had more granular file format control. */
1494 char format = (!strcmp(fds->cache_id, FLUID_CACHE_VERSION)) ? fds->cache_data_format :
1496 string volume_format = getCacheFileEnding(format);
1497
1498 /* Sanity check: Are cache files present? */
1499 if (!hasParticles(fmd, framenr)) {
1500 return false;
1501 }
1502
1503 ss.str("");
1504 ss << "liquid_load_particles_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1505 << ", '" << volume_format << "', " << resumable_cache << ")";
1506 pythonCommands.push_back(ss.str());
1507
1508 return (mParticlesFromFile = runPythonString(pythonCommands));
1509}
1510
1511bool MANTA::readGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
1512{
1513 if (with_debug) {
1514 cout << "MANTA::readGuiding()" << endl;
1515 }
1516
1517 if (!mUsingGuiding) {
1518 return false;
1519 }
1520 if (!fmd) {
1521 return false;
1522 }
1523
1524 ostringstream ss;
1525 vector<string> pythonCommands;
1526 FluidDomainSettings *fds = fmd->domain;
1527
1528 string directory = (sourceDomain) ? getDirectory(fmd, FLUID_DOMAIN_DIR_DATA) :
1529 getDirectory(fmd, FLUID_DOMAIN_DIR_GUIDE);
1530 string volume_format = getCacheFileEnding(fds->cache_data_format);
1531
1532 /* Sanity check: Are cache files present? */
1533 if (!hasGuiding(fmd, framenr, sourceDomain)) {
1534 return false;
1535 }
1536
1537 if (sourceDomain) {
1538 ss.str("");
1539 ss << "fluid_load_vel_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1540 << ", '" << volume_format << "')";
1541 }
1542 else {
1543 ss.str("");
1544 ss << "fluid_load_guiding_" << mCurrentID << "('" << escapePath(directory) << "', " << framenr
1545 << ", '" << volume_format << "')";
1546 }
1547 pythonCommands.push_back(ss.str());
1548
1549 return runPythonString(pythonCommands);
1550}
1551
1552bool MANTA::bakeData(FluidModifierData *fmd, int framenr)
1553{
1554 if (with_debug) {
1555 cout << "MANTA::bakeData()" << endl;
1556 }
1557
1558 ostringstream ss;
1559 vector<string> pythonCommands;
1560 FluidDomainSettings *fds = fmd->domain;
1561
1562 char cacheDirData[FILE_MAX], cacheDirGuiding[FILE_MAX];
1563 cacheDirData[0] = '\0';
1564 cacheDirGuiding[0] = '\0';
1565
1566 string volume_format = getCacheFileEnding(fds->cache_data_format);
1567
1568 BLI_path_join(cacheDirData, sizeof(cacheDirData), fds->cache_directory, FLUID_DOMAIN_DIR_DATA);
1570 cacheDirGuiding, sizeof(cacheDirGuiding), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE);
1571 BLI_path_make_safe(cacheDirData);
1572 BLI_path_make_safe(cacheDirGuiding);
1573
1574 ss.str("");
1575 ss << "bake_fluid_data_" << mCurrentID << "('" << escapePath(cacheDirData) << "', " << framenr
1576 << ", '" << volume_format << "')";
1577 pythonCommands.push_back(ss.str());
1578
1579 return runPythonString(pythonCommands);
1580}
1581
1583{
1584 if (with_debug) {
1585 cout << "MANTA::bakeNoise()" << endl;
1586 }
1587
1588 ostringstream ss;
1589 vector<string> pythonCommands;
1590 FluidDomainSettings *fds = fmd->domain;
1591
1592 char cacheDirNoise[FILE_MAX];
1593 cacheDirNoise[0] = '\0';
1594
1595 string volume_format = getCacheFileEnding(fds->cache_data_format);
1596
1598 cacheDirNoise, sizeof(cacheDirNoise), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE);
1599 BLI_path_make_safe(cacheDirNoise);
1600
1601 ss.str("");
1602 ss << "bake_noise_" << mCurrentID << "('" << escapePath(cacheDirNoise) << "', " << framenr
1603 << ", '" << volume_format << "')";
1604 pythonCommands.push_back(ss.str());
1605
1606 return runPythonString(pythonCommands);
1607}
1608
1609bool MANTA::bakeMesh(FluidModifierData *fmd, int framenr)
1610{
1611 if (with_debug) {
1612 cout << "MANTA::bakeMesh()" << endl;
1613 }
1614
1615 ostringstream ss;
1616 vector<string> pythonCommands;
1617 FluidDomainSettings *fds = fmd->domain;
1618
1619 char cacheDirMesh[FILE_MAX];
1620 cacheDirMesh[0] = '\0';
1621
1622 string volume_format = getCacheFileEnding(fds->cache_data_format);
1623 string mesh_format = getCacheFileEnding(fds->cache_mesh_format);
1624
1625 BLI_path_join(cacheDirMesh, sizeof(cacheDirMesh), fds->cache_directory, FLUID_DOMAIN_DIR_MESH);
1626 BLI_path_make_safe(cacheDirMesh);
1627
1628 ss.str("");
1629 ss << "bake_mesh_" << mCurrentID << "('" << escapePath(cacheDirMesh) << "', " << framenr << ", '"
1630 << volume_format << "', '" << mesh_format << "')";
1631 pythonCommands.push_back(ss.str());
1632
1633 return runPythonString(pythonCommands);
1634}
1635
1637{
1638 if (with_debug) {
1639 cout << "MANTA::bakeParticles()" << endl;
1640 }
1641
1642 ostringstream ss;
1643 vector<string> pythonCommands;
1644 FluidDomainSettings *fds = fmd->domain;
1645
1646 char cacheDirParticles[FILE_MAX];
1647 cacheDirParticles[0] = '\0';
1648
1649 string volume_format = getCacheFileEnding(fds->cache_data_format);
1650 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1651
1652 BLI_path_join(cacheDirParticles,
1653 sizeof(cacheDirParticles),
1654 fds->cache_directory,
1656 BLI_path_make_safe(cacheDirParticles);
1657
1658 ss.str("");
1659 ss << "bake_particles_" << mCurrentID << "('" << escapePath(cacheDirParticles) << "', "
1660 << framenr << ", '" << volume_format << "', " << resumable_cache << ")";
1661 pythonCommands.push_back(ss.str());
1662
1663 return runPythonString(pythonCommands);
1664}
1665
1667{
1668 if (with_debug) {
1669 cout << "MANTA::bakeGuiding()" << endl;
1670 }
1671
1672 ostringstream ss;
1673 vector<string> pythonCommands;
1674 FluidDomainSettings *fds = fmd->domain;
1675
1676 char cacheDirGuiding[FILE_MAX];
1677 cacheDirGuiding[0] = '\0';
1678
1679 string volume_format = getCacheFileEnding(fds->cache_data_format);
1680 string resumable_cache = !(fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE) ? "False" : "True";
1681
1683 cacheDirGuiding, sizeof(cacheDirGuiding), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE);
1684 BLI_path_make_safe(cacheDirGuiding);
1685
1686 ss.str("");
1687 ss << "bake_guiding_" << mCurrentID << "('" << escapePath(cacheDirGuiding) << "', " << framenr
1688 << ", '" << volume_format << "', " << resumable_cache << ")";
1689 pythonCommands.push_back(ss.str());
1690
1691 return runPythonString(pythonCommands);
1692}
1693
1695{
1696 string tmpString, finalString;
1697 vector<string> pythonCommands;
1698
1699 tmpString += fluid_variables;
1700 if (mUsingSmoke) {
1701 tmpString += smoke_variables;
1702 }
1703 if (mUsingLiquid) {
1704 tmpString += liquid_variables;
1705 }
1706 if (mUsingGuiding) {
1707 tmpString += fluid_variables_guiding;
1708 }
1709 if (mUsingNoise) {
1710 tmpString += fluid_variables_noise;
1711 tmpString += smoke_variables_noise;
1712 tmpString += smoke_wavelet_noise;
1713 }
1714 if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) {
1715 tmpString += fluid_variables_particles;
1716 tmpString += liquid_variables_particles;
1717 }
1718 if (mUsingMesh) {
1719 tmpString += fluid_variables_mesh;
1720 }
1721
1722 finalString = parseScript(tmpString, fmd);
1723 pythonCommands.push_back(finalString);
1724
1725 return runPythonString(pythonCommands);
1726}
1727
1729{
1730 if (with_debug) {
1731 cout << "MANTA::exportSmokeScript()" << endl;
1732 }
1733
1734 char cacheDir[FILE_MAX] = "\0";
1735 char cacheDirScript[FILE_MAX] = "\0";
1736
1737 FluidDomainSettings *fds = fmd->domain;
1738
1739 BLI_path_join(cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT);
1740 BLI_path_make_safe(cacheDir);
1741 /* Create 'script' subdir if it does not exist already */
1742 BLI_dir_create_recursive(cacheDir);
1743 BLI_path_join(cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_SMOKE_SCRIPT);
1744 BLI_path_make_safe(cacheDir);
1745
1746 bool noise = fds->flags & FLUID_DOMAIN_USE_NOISE;
1747 bool heat = fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
1748 bool colors = fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
1749 bool fire = fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
1750 bool obstacle = fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
1751 bool guiding = fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
1752 bool invel = fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
1753 bool outflow = fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
1754
1755 string manta_script;
1756
1757 /* Libraries. */
1758 manta_script += header_libraries + manta_import;
1759
1760 /* Variables. */
1761 manta_script += header_variables + fluid_variables + smoke_variables;
1762 if (noise) {
1764 }
1765 if (guiding) {
1766 manta_script += fluid_variables_guiding;
1767 }
1768
1769 /* Solvers. */
1770 manta_script += header_solvers + fluid_solver;
1771 if (noise) {
1772 manta_script += fluid_solver_noise;
1773 }
1774 if (guiding) {
1775 manta_script += fluid_solver_guiding;
1776 }
1777
1778 /* Grids. */
1779 manta_script += header_grids + fluid_alloc + smoke_alloc;
1780 if (noise) {
1781 manta_script += smoke_alloc_noise;
1782 if (colors) {
1783 manta_script += smoke_alloc_colors_noise;
1784 }
1785 if (fire) {
1786 manta_script += smoke_alloc_fire_noise;
1787 }
1788 }
1789 if (heat) {
1790 manta_script += smoke_alloc_heat;
1791 }
1792 if (colors) {
1793 manta_script += smoke_alloc_colors;
1794 }
1795 if (fire) {
1796 manta_script += smoke_alloc_fire;
1797 }
1798 if (guiding) {
1799 manta_script += fluid_alloc_guiding;
1800 }
1801 if (obstacle) {
1802 manta_script += fluid_alloc_obstacle;
1803 }
1804 if (invel) {
1805 manta_script += fluid_alloc_invel;
1806 }
1807 if (outflow) {
1808 manta_script += fluid_alloc_outflow;
1809 }
1810
1811 /* Noise field. */
1812 if (noise) {
1813 manta_script += smoke_wavelet_noise;
1814 }
1815
1816 /* Time. */
1817 manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step;
1818
1819 /* Import. */
1820 manta_script += header_import + fluid_file_import + fluid_cache_helper + smoke_load_data;
1821 if (noise) {
1822 manta_script += smoke_load_noise;
1823 }
1824 if (guiding) {
1825 manta_script += fluid_load_guiding;
1826 }
1827
1828 /* Pre/Post Steps. */
1829 manta_script += header_prepost + fluid_pre_step + fluid_post_step;
1830
1831 /* Steps. */
1832 manta_script += header_steps + smoke_adaptive_step + smoke_step;
1833 if (noise) {
1834 manta_script += smoke_step_noise;
1835 }
1836
1837 /* Main. */
1838 manta_script += header_main + smoke_standalone + fluid_standalone;
1839
1840 /* Fill in missing variables in script. */
1841 string final_script = MANTA::parseScript(manta_script, fmd);
1842
1843 /* Write script. */
1844 ofstream myfile;
1845 myfile.open(cacheDirScript);
1846 myfile << final_script;
1847 myfile.close();
1848 if (!myfile) {
1849 cerr << "Fluid Error -- Could not export standalone Mantaflow smoke domain script";
1850 return false;
1851 }
1852 return true;
1853}
1854
1856{
1857 if (with_debug) {
1858 cout << "MANTA::exportLiquidScript()" << endl;
1859 }
1860
1861 char cacheDir[FILE_MAX] = "\0";
1862 char cacheDirScript[FILE_MAX] = "\0";
1863
1864 FluidDomainSettings *fds = fmd->domain;
1865
1866 BLI_path_join(cacheDir, sizeof(cacheDir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT);
1867 BLI_path_make_safe(cacheDir);
1868 /* Create 'script' subdir if it does not exist already */
1869 BLI_dir_create_recursive(cacheDir);
1870 BLI_path_join(cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_LIQUID_SCRIPT);
1871 BLI_path_make_safe(cacheDirScript);
1872
1873 bool mesh = fds->flags & FLUID_DOMAIN_USE_MESH;
1874 bool drops = fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
1875 bool bubble = fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
1876 bool floater = fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
1877 bool tracer = fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
1878 bool obstacle = fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
1879 bool fractions = fds->flags & FLUID_DOMAIN_USE_FRACTIONS;
1880 bool guiding = fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
1881 bool invel = fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
1882 bool outflow = fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
1883 bool viscosity = fds->flags & FLUID_DOMAIN_USE_VISCOSITY;
1884
1885 string manta_script;
1886
1887 /* Libraries. */
1888 manta_script += header_libraries + manta_import;
1889
1890 /* Variables. */
1891 manta_script += header_variables + fluid_variables + liquid_variables;
1892 if (mesh) {
1893 manta_script += fluid_variables_mesh;
1894 }
1895 if (drops || bubble || floater || tracer) {
1897 }
1898 if (guiding) {
1899 manta_script += fluid_variables_guiding;
1900 }
1901 if (viscosity) {
1902 manta_script += fluid_variables_viscosity;
1903 }
1904
1905 /* Solvers. */
1906 manta_script += header_solvers + fluid_solver;
1907 if (mesh) {
1908 manta_script += fluid_solver_mesh;
1909 }
1910 if (drops || bubble || floater || tracer) {
1911 manta_script += fluid_solver_particles;
1912 }
1913 if (guiding) {
1914 manta_script += fluid_solver_guiding;
1915 }
1916 if (viscosity) {
1917 manta_script += fluid_solver_viscosity;
1918 }
1919
1920 /* Grids. */
1921 manta_script += header_grids + fluid_alloc + liquid_alloc;
1922 if (mesh) {
1923 manta_script += liquid_alloc_mesh;
1924 }
1925 if (drops || bubble || floater || tracer) {
1926 manta_script += liquid_alloc_particles;
1927 }
1928 if (guiding) {
1929 manta_script += fluid_alloc_guiding;
1930 }
1931 if (obstacle) {
1932 manta_script += fluid_alloc_obstacle;
1933 }
1934 if (fractions) {
1935 manta_script += fluid_alloc_fractions;
1936 }
1937 if (invel) {
1938 manta_script += fluid_alloc_invel;
1939 }
1940 if (outflow) {
1941 manta_script += fluid_alloc_outflow;
1942 }
1943 if (viscosity) {
1944 manta_script += liquid_alloc_viscosity;
1945 }
1946
1947 /* Domain init. */
1948 manta_script += header_gridinit + liquid_init_phi;
1949
1950 /* Time. */
1951 manta_script += header_time + fluid_time_stepping + fluid_adapt_time_step;
1952
1953 /* Import. */
1954 manta_script += header_import + fluid_file_import + fluid_cache_helper + liquid_load_data;
1955 if (mesh) {
1956 manta_script += liquid_load_mesh;
1957 }
1958 if (drops || bubble || floater || tracer) {
1959 manta_script += liquid_load_particles;
1960 }
1961 if (guiding) {
1962 manta_script += fluid_load_guiding;
1963 }
1964
1965 /* Pre/Post Steps. */
1966 manta_script += header_prepost + fluid_pre_step + fluid_post_step;
1967
1968 /* Steps. */
1969 manta_script += header_steps + liquid_adaptive_step + liquid_step;
1970 if (mesh) {
1971 manta_script += liquid_step_mesh;
1972 }
1973 if (drops || bubble || floater || tracer) {
1974 manta_script += liquid_step_particles;
1975 }
1976
1977 /* Main. */
1978 manta_script += header_main + liquid_standalone + fluid_standalone;
1979
1980 /* Fill in missing variables in script. */
1981 string final_script = MANTA::parseScript(manta_script, fmd);
1982
1983 /* Write script. */
1984 ofstream myfile;
1985 myfile.open(cacheDirScript);
1986 myfile << final_script;
1987 myfile.close();
1988 if (!myfile) {
1989 cerr << "Fluid Error -- Could not export standalone Mantaflow liquid domain script";
1990 return false;
1991 }
1992 return true;
1993}
1994
1995/* Call Mantaflow Python functions through this function. Use isAttribute for object attributes,
1996 * e.g. s.cfl (here 's' is varname, 'cfl' functionName, and isAttribute true) or
1997 * grid.getDataPointer (here 's' is varname, 'getDataPointer' functionName, and isAttribute
1998 * false)
1999 *
2000 * Important! Return value: New reference or nullptr
2001 * Caller of this function needs to handle reference count of returned object. */
2002static PyObject *callPythonFunction(string varName, string functionName, bool isAttribute = false)
2003{
2004 if ((varName == "") || (functionName == "")) {
2005 if (MANTA::with_debug) {
2006 cout << "Fluid: Missing Python variable name and/or function name -- name is: " << varName
2007 << ", function name is: " << functionName << endl;
2008 }
2009 return nullptr;
2010 }
2011
2012 PyGILState_STATE gilstate = PyGILState_Ensure();
2013 PyObject *var = nullptr, *func = nullptr, *returnedValue = nullptr;
2014
2015 /* Be sure to initialize Python before using it. */
2016 Py_Initialize();
2017
2018 /* Get pyobject that holds result value. */
2019 if (!manta_main_module) {
2020 PyGILState_Release(gilstate);
2021 return nullptr;
2022 }
2023
2024 /* Ensure that requested variable is present in module - avoid attribute errors later on. */
2025 if (!PyObject_HasAttrString(manta_main_module, varName.c_str())) {
2026 PyGILState_Release(gilstate);
2027 return nullptr;
2028 }
2029
2030 var = PyObject_GetAttrString(manta_main_module, varName.c_str());
2031 if (!var) {
2032 PyErr_Clear();
2033 PyGILState_Release(gilstate);
2034 return nullptr;
2035 }
2036
2037 func = PyObject_GetAttrString(var, functionName.c_str());
2038
2039 Py_DECREF(var);
2040 if (!func) {
2041 PyErr_Clear();
2042 PyGILState_Release(gilstate);
2043 return nullptr;
2044 }
2045
2046 if (!isAttribute) {
2047 returnedValue = PyObject_CallObject(func, nullptr);
2048 if (returnedValue == nullptr) {
2049 /* Print any unexpected errors, also clear them. */
2050 PyErr_Print();
2051 }
2052 Py_DECREF(func);
2053 }
2054
2055 PyGILState_Release(gilstate);
2056 return (!isAttribute) ? returnedValue : func;
2057}
2058
2059/* Argument of this function may be a nullptr.
2060 * If it's not function will handle the reference count decrement of that argument. */
2061static void *pyObjectToPointer(PyObject *inputObject)
2062{
2063 if (!inputObject) {
2064 return nullptr;
2065 }
2066
2067 PyGILState_STATE gilstate = PyGILState_Ensure();
2068
2069 PyObject *encoded = PyUnicode_AsUTF8String(inputObject);
2070 char *result = PyBytes_AsString(encoded);
2071
2072 Py_DECREF(inputObject);
2073
2074 string str(result);
2075 istringstream in(str);
2076 void *dataPointer = nullptr;
2077 in >> dataPointer;
2078
2079 Py_DECREF(encoded);
2080
2081 PyGILState_Release(gilstate);
2082 return dataPointer;
2083}
2084
2085/* Argument of this function may be a nullptr.
2086 * If it's not function will handle the reference count decrement of that argument. */
2087static double pyObjectToDouble(PyObject *inputObject)
2088{
2089 if (!inputObject) {
2090 return 0.0;
2091 }
2092
2093 PyGILState_STATE gilstate = PyGILState_Ensure();
2094
2095 /* Cannot use PyFloat_AsDouble() since its error check crashes.
2096 * Likely because of typedef 'Real' for 'float' types in Mantaflow. */
2097 double result = PyFloat_AS_DOUBLE(inputObject);
2098 Py_DECREF(inputObject);
2099
2100 PyGILState_Release(gilstate);
2101 return result;
2102}
2103
2104/* Argument of this function may be a nullptr.
2105 * If it's not function will handle the reference count decrement of that argument. */
2106static long pyObjectToLong(PyObject *inputObject)
2107{
2108 if (!inputObject) {
2109 return 0;
2110 }
2111
2112 PyGILState_STATE gilstate = PyGILState_Ensure();
2113
2114 long result = PyLong_AsLong(inputObject);
2115 Py_DECREF(inputObject);
2116
2117 PyGILState_Release(gilstate);
2118 return result;
2119}
2120
2121template<class T> static T *getPointer(string pyObjectName, string pyFunctionName)
2122{
2123 return static_cast<T *>(pyObjectToPointer(callPythonFunction(pyObjectName, pyFunctionName)));
2124}
2125
2127{
2128 if (with_debug) {
2129 cout << "MANTA::getFrame()" << endl;
2130 }
2131
2132 string func = "frame";
2133 string id = to_string(mCurrentID);
2134 string solver = "s" + id;
2135
2136 return pyObjectToLong(callPythonFunction(solver, func, true));
2137}
2138
2140{
2141 if (with_debug) {
2142 cout << "MANTA::getTimestep()" << endl;
2143 }
2144
2145 string func = "timestep";
2146 string id = to_string(mCurrentID);
2147 string solver = "s" + id;
2148
2149 return (float)pyObjectToDouble(callPythonFunction(solver, func, true));
2150}
2151
2153{
2154 FluidDomainSettings *fds = fmd->domain;
2155 return ((fds->res_max[0] - fds->res_min[0]) != mResX ||
2156 (fds->res_max[1] - fds->res_min[1]) != mResY ||
2157 (fds->res_max[2] - fds->res_min[2]) != mResZ);
2158}
2159
2161{
2162 if (with_debug) {
2163 cout << "MANTA::adaptTimestep()" << endl;
2164 }
2165
2166 vector<string> pythonCommands;
2167 ostringstream ss;
2168
2169 ss << "fluid_adapt_time_step_" << mCurrentID << "()";
2170 pythonCommands.push_back(ss.str());
2171
2172 runPythonString(pythonCommands);
2173}
2174
2176{
2177 if (with_debug) {
2178 cout << "MANTA::updatePointers()" << endl;
2179 }
2180
2181 FluidDomainSettings *fds = fmd->domain;
2182
2183 bool liquid = !flush && (fds->type == FLUID_DOMAIN_TYPE_LIQUID);
2184 bool smoke = !flush && (fds->type == FLUID_DOMAIN_TYPE_GAS);
2185 bool noise = !flush && smoke && fds->flags & FLUID_DOMAIN_USE_NOISE;
2186 bool heat = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT;
2187 bool colors = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS;
2188 bool fire = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE;
2189 bool obstacle = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
2190 bool guiding = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
2191 bool invel = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
2192 bool outflow = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
2193 bool drops = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY;
2194 bool bubble = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE;
2195 bool floater = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM;
2196 bool tracer = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER;
2197 bool parts = !flush && liquid && (drops | bubble | floater | tracer);
2198 bool mesh = !flush && liquid && fds->flags & FLUID_DOMAIN_USE_MESH;
2199 bool meshvel = !flush && liquid && mesh && fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS;
2200
2201 string func = "getDataPointer";
2202 string funcNodes = "getNodesDataPointer";
2203 string funcTris = "getTrisDataPointer";
2204
2205 string id = to_string(mCurrentID);
2206 string s_ext = "_s" + id;
2207 string pp_ext = "_pp" + id;
2208 string snd_ext = "_sp" + id;
2209 string sm_ext = "_sm" + id;
2210 string mesh_ext = "_mesh" + id;
2211 string sn_ext = "_sn" + id;
2212
2213 mFlags = (smoke || liquid) ? getPointer<int>("flags" + s_ext, func) : nullptr;
2214 mPhiIn = (smoke || liquid) ? getPointer<float>("phiIn" + s_ext, func) : nullptr;
2215 mPhiStaticIn = (smoke || liquid) ? getPointer<float>("phiSIn" + s_ext, func) : nullptr;
2216 mVelocityX = (smoke || liquid) ? getPointer<float>("x_vel" + s_ext, func) : nullptr;
2217 mVelocityY = (smoke || liquid) ? getPointer<float>("y_vel" + s_ext, func) : nullptr;
2218 mVelocityZ = (smoke || liquid) ? getPointer<float>("z_vel" + s_ext, func) : nullptr;
2219 mForceX = (smoke || liquid) ? getPointer<float>("x_force" + s_ext, func) : nullptr;
2220 mForceY = (smoke || liquid) ? getPointer<float>("y_force" + s_ext, func) : nullptr;
2221 mForceZ = (smoke || liquid) ? getPointer<float>("z_force" + s_ext, func) : nullptr;
2222 mPressure = (smoke || liquid) ? getPointer<float>("pressure" + s_ext, func) : nullptr;
2223
2224 /* Outflow. */
2225 mPhiOutIn = (outflow) ? getPointer<float>("phiOutIn" + s_ext, func) : nullptr;
2226 mPhiOutStaticIn = (outflow) ? getPointer<float>("phiOutSIn" + s_ext, func) : nullptr;
2227
2228 /* Obstacles. */
2229 mPhiObsIn = (obstacle) ? getPointer<float>("phiObsIn" + s_ext, func) : nullptr;
2230 mPhiObsStaticIn = (obstacle) ? getPointer<float>("phiObsSIn" + s_ext, func) : nullptr;
2231 mObVelocityX = (obstacle) ? getPointer<float>("x_obvel" + s_ext, func) : nullptr;
2232 mObVelocityY = (obstacle) ? getPointer<float>("y_obvel" + s_ext, func) : nullptr;
2233 mObVelocityZ = (obstacle) ? getPointer<float>("z_obvel" + s_ext, func) : nullptr;
2234 mNumObstacle = (obstacle) ? getPointer<float>("numObs" + s_ext, func) : nullptr;
2235
2236 /* Guiding. */
2237 mPhiGuideIn = (guiding) ? getPointer<float>("phiGuideIn" + s_ext, func) : nullptr;
2238 mGuideVelocityX = (guiding) ? getPointer<float>("x_guidevel" + s_ext, func) : nullptr;
2239 mGuideVelocityY = (guiding) ? getPointer<float>("y_guidevel" + s_ext, func) : nullptr;
2240 mGuideVelocityZ = (guiding) ? getPointer<float>("z_guidevel" + s_ext, func) : nullptr;
2241 mNumGuide = (guiding) ? getPointer<float>("numGuides" + s_ext, func) : nullptr;
2242
2243 /* Initial velocities. */
2244 mInVelocityX = (invel) ? getPointer<float>("x_invel" + s_ext, func) : nullptr;
2245 mInVelocityY = (invel) ? getPointer<float>("y_invel" + s_ext, func) : nullptr;
2246 mInVelocityZ = (invel) ? getPointer<float>("z_invel" + s_ext, func) : nullptr;
2247
2248 /* Smoke. */
2249 mDensity = (smoke) ? getPointer<float>("density" + s_ext, func) : nullptr;
2250 mDensityIn = (smoke) ? getPointer<float>("densityIn" + s_ext, func) : nullptr;
2251 mShadow = (smoke) ? getPointer<float>("shadow" + s_ext, func) : nullptr;
2252 mEmissionIn = (smoke) ? getPointer<float>("emissionIn" + s_ext, func) : nullptr;
2253
2254 /* Heat. */
2255 mHeat = (heat) ? getPointer<float>("heat" + s_ext, func) : nullptr;
2256 mHeatIn = (heat) ? getPointer<float>("heatIn" + s_ext, func) : nullptr;
2257
2258 /* Fire. */
2259 mFlame = (fire) ? getPointer<float>("flame" + s_ext, func) : nullptr;
2260 mFuel = (fire) ? getPointer<float>("fuel" + s_ext, func) : nullptr;
2261 mReact = (fire) ? getPointer<float>("react" + s_ext, func) : nullptr;
2262 mFuelIn = (fire) ? getPointer<float>("fuelIn" + s_ext, func) : nullptr;
2263 mReactIn = (fire) ? getPointer<float>("reactIn" + s_ext, func) : nullptr;
2264
2265 /* Colors. */
2266 mColorR = (colors) ? getPointer<float>("color_r" + s_ext, func) : nullptr;
2267 mColorG = (colors) ? getPointer<float>("color_g" + s_ext, func) : nullptr;
2268 mColorB = (colors) ? getPointer<float>("color_b" + s_ext, func) : nullptr;
2269 mColorRIn = (colors) ? getPointer<float>("color_r_in" + s_ext, func) : nullptr;
2270 mColorGIn = (colors) ? getPointer<float>("color_g_in" + s_ext, func) : nullptr;
2271 mColorBIn = (colors) ? getPointer<float>("color_b_in" + s_ext, func) : nullptr;
2272
2273 /* Noise. */
2274 mDensityHigh = (noise) ? getPointer<float>("density" + sn_ext, func) : nullptr;
2275 mTextureU = (noise) ? getPointer<float>("texture_u" + s_ext, func) : nullptr;
2276 mTextureV = (noise) ? getPointer<float>("texture_v" + s_ext, func) : nullptr;
2277 mTextureW = (noise) ? getPointer<float>("texture_w" + s_ext, func) : nullptr;
2278 mTextureU2 = (noise) ? getPointer<float>("texture_u2" + s_ext, func) : nullptr;
2279 mTextureV2 = (noise) ? getPointer<float>("texture_v2" + s_ext, func) : nullptr;
2280 mTextureW2 = (noise) ? getPointer<float>("texture_w2" + s_ext, func) : nullptr;
2281
2282 /* Fire with noise. */
2283 mFlameHigh = (noise && fire) ? getPointer<float>("flame" + sn_ext, func) : nullptr;
2284 mFuelHigh = (noise && fire) ? getPointer<float>("fuel" + sn_ext, func) : nullptr;
2285 mReactHigh = (noise && fire) ? getPointer<float>("react" + sn_ext, func) : nullptr;
2286
2287 /* Colors with noise. */
2288 mColorRHigh = (noise && colors) ? getPointer<float>("color_r" + sn_ext, func) : nullptr;
2289 mColorGHigh = (noise && colors) ? getPointer<float>("color_g" + sn_ext, func) : nullptr;
2290 mColorBHigh = (noise && colors) ? getPointer<float>("color_b" + sn_ext, func) : nullptr;
2291
2292 /* Liquid. */
2293 mPhi = (liquid) ? getPointer<float>("phi" + s_ext, func) : nullptr;
2294 mFlipParticleData = (liquid) ? getPointer<vector<pData>>("pp" + s_ext, func) : nullptr;
2295 mFlipParticleVelocity = (liquid) ? getPointer<vector<pVel>>("pVel" + pp_ext, func) : nullptr;
2296
2297 /* Mesh. */
2298 mMeshNodes = (mesh) ? getPointer<vector<Node>>("mesh" + sm_ext, funcNodes) : nullptr;
2299 mMeshTriangles = (mesh) ? getPointer<vector<Triangle>>("mesh" + sm_ext, funcTris) : nullptr;
2300
2301 /* Mesh velocities. */
2302 mMeshVelocities = (meshvel) ? getPointer<vector<pVel>>("mVel" + mesh_ext, func) : nullptr;
2303
2304 /* Secondary particles. */
2305 mParticleData = (parts) ? getPointer<vector<pData>>("ppSnd" + snd_ext, func) : nullptr;
2306 mParticleVelocity = (parts) ? getPointer<vector<pVel>>("pVelSnd" + pp_ext, func) : nullptr;
2307 mParticleLife = (parts) ? getPointer<vector<float>>("pLifeSnd" + pp_ext, func) : nullptr;
2308
2309 mFlipFromFile = false;
2310 mMeshFromFile = false;
2311 mParticlesFromFile = false;
2312 mSmokeFromFile = false;
2313 mNoiseFromFile = false;
2314}
2315
2317{
2318 string extension = FLUID_DOMAIN_EXTENSION_UNI;
2319 return BLI_exists(
2320 getFile(fmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_NAME_CONFIG, extension, framenr).c_str());
2321}
2322
2323bool MANTA::hasData(FluidModifierData *fmd, int framenr)
2324{
2325 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2326 bool exists = BLI_exists(
2327 getFile(fmd, FLUID_DOMAIN_DIR_DATA, FLUID_NAME_DATA, extension, framenr).c_str());
2328
2329 /* Check single file naming. */
2330 if (!exists) {
2331 string filename = (mUsingSmoke) ? FLUID_NAME_DENSITY : FLUID_NAME_PP;
2332 exists = BLI_exists(getFile(fmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str());
2333 }
2334 if (with_debug) {
2335 cout << "Fluid: Has Data: " << exists << endl;
2336 }
2337
2338 return exists;
2339}
2340
2341bool MANTA::hasNoise(FluidModifierData *fmd, int framenr)
2342{
2343 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2344 bool exists = BLI_exists(
2345 getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_NOISE, extension, framenr).c_str());
2346
2347 /* Check single file naming. */
2348 if (!exists) {
2349 extension = getCacheFileEnding(fmd->domain->cache_data_format);
2350 exists = BLI_exists(
2351 getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr)
2352 .c_str());
2353 }
2354 /* Check single file naming with deprecated extension. */
2355 if (!exists) {
2356 extension = getCacheFileEnding(fmd->domain->cache_noise_format);
2357 exists = BLI_exists(
2358 getFile(fmd, FLUID_DOMAIN_DIR_NOISE, FLUID_NAME_DENSITY_NOISE, extension, framenr)
2359 .c_str());
2360 }
2361 if (with_debug) {
2362 cout << "Fluid: Has Noise: " << exists << endl;
2363 }
2364
2365 return exists;
2366}
2367
2368bool MANTA::hasMesh(FluidModifierData *fmd, int framenr)
2369{
2370 string extension = getCacheFileEnding(fmd->domain->cache_mesh_format);
2371 bool exists = BLI_exists(
2372 getFile(fmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_MESH, extension, framenr).c_str());
2373
2374 /* Check old file naming. */
2375 if (!exists) {
2376 exists = BLI_exists(
2377 getFile(fmd, FLUID_DOMAIN_DIR_MESH, FLUID_NAME_LMESH, extension, framenr).c_str());
2378 }
2379 if (with_debug) {
2380 cout << "Fluid: Has Mesh: " << exists << endl;
2381 }
2382
2383 return exists;
2384}
2385
2387{
2388 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2389 bool exists = BLI_exists(
2390 getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PARTICLES, extension, framenr).c_str());
2391
2392 /* Check single file naming. */
2393 if (!exists) {
2394 extension = getCacheFileEnding(fmd->domain->cache_data_format);
2395 exists = BLI_exists(
2396 getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr)
2397 .c_str());
2398 }
2399 /* Check single file naming with deprecated extension. */
2400 if (!exists) {
2402 exists = BLI_exists(
2403 getFile(fmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_NAME_PP_PARTICLES, extension, framenr)
2404 .c_str());
2405 }
2406 if (with_debug) {
2407 cout << "Fluid: Has Particles: " << exists << endl;
2408 }
2409
2410 return exists;
2411}
2412
2413bool MANTA::hasGuiding(FluidModifierData *fmd, int framenr, bool sourceDomain)
2414{
2415 string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE;
2416 string filename = (sourceDomain) ? FLUID_NAME_DATA : FLUID_NAME_GUIDING;
2417 string extension = getCacheFileEnding(fmd->domain->cache_data_format);
2418 bool exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str());
2419
2420 /* Check old file naming. */
2421 if (!exists) {
2422 filename = (sourceDomain) ? FLUID_NAME_VEL : FLUID_NAME_GUIDEVEL;
2423 exists = BLI_exists(getFile(fmd, subdirectory, filename, extension, framenr).c_str());
2424 }
2425
2426 if (with_debug) {
2427 cout << "Fluid: Has Guiding: " << exists << endl;
2428 }
2429
2430 return exists;
2431}
2432
2433string MANTA::getDirectory(FluidModifierData *fmd, string subdirectory)
2434{
2435 char directory[FILE_MAX];
2436 BLI_path_join(directory, sizeof(directory), fmd->domain->cache_directory, subdirectory.c_str());
2437 BLI_path_make_safe(directory);
2438 return directory;
2439}
2440
2441string MANTA::getFile(
2442 FluidModifierData *fmd, string subdirectory, string fname, string extension, int framenr)
2443{
2444 char targetFile[FILE_MAX];
2445 string path = getDirectory(fmd, subdirectory);
2446 string filename = fname + "_####" + extension;
2447 BLI_path_join(targetFile, sizeof(targetFile), path.c_str(), filename.c_str());
2448 BLI_path_frame(targetFile, sizeof(targetFile), framenr, 0);
2449 return targetFile;
2450}
#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:373
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
Definition fileops_c.cc:391
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
@ 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_FUEL_NOISE
#define FLUID_NAME_COLORG_NOISE
#define FLUID_NAME_COLORB_NOISE
#define FLUID_NAME_FLAGS_MESH
#define FLUID_NAME_NOISE
@ FLUID_DOMAIN_TYPE_GAS
@ FLUID_DOMAIN_TYPE_LIQUID
#define FLUID_DOMAIN_DIR_DATA
@ FLUID_DOMAIN_FILE_BIN_OBJECT
@ FLUID_DOMAIN_FILE_RAW
@ FLUID_DOMAIN_FILE_OBJECT
@ FLUID_DOMAIN_FILE_UNI
@ FLUID_DOMAIN_FILE_OPENVDB
#define FLUID_NAME_PHIPARTS_MESH
#define FLUID_NAME_DATA
#define FLUID_DOMAIN_DIR_PARTICLES
#define FLUID_NAME_PP
#define FLUID_NAME_TMPFLAGS
#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
#define FLUID_NAME_GUIDEVEL_Z
#define FLUID_NAME_PVEL_PARTICLES
#define FLUID_NAME_LMESH
@ FLUID_DOMAIN_PARTICLE_SPRAY
@ FLUID_DOMAIN_PARTICLE_FOAM
@ FLUID_DOMAIN_PARTICLE_TRACER
@ FLUID_DOMAIN_PARTICLE_BUBBLE
#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
#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
@ 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_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
@ VDB_COMPRESSION_NONE
@ VDB_COMPRESSION_ZIP
@ VDB_COMPRESSION_BLOSC
#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
#define FLUID_NAME_GUIDING
#define FLUID_NAME_DENSITY
@ VDB_PRECISION_MINI_FLOAT
@ VDB_PRECISION_FULL_FLOAT
@ VDB_PRECISION_HALF_FLOAT
#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
@ FLUID_DOMAIN_MESH_IMPROVED
@ FLUID_DOMAIN_BORDER_BOTTOM
@ FLUID_DOMAIN_BORDER_LEFT
@ FLUID_DOMAIN_BORDER_RIGHT
@ FLUID_DOMAIN_BORDER_FRONT
@ FLUID_DOMAIN_BORDER_TOP
@ FLUID_DOMAIN_BORDER_BACK
#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
#define FLUID_NAME_PHIOUT_NOISE
#define FLUID_NAME_VELOCITY_NOISE
#define FLUID_NAME_TEXTURE_W
#define FLUID_NAME_PP_MESH
#define FLUID_DOMAIN_DIR_NOISE
#define FLUID_NAME_OBVEL_Z
#define FLUID_NAME_PHIPARTS
#define FLUID_NAME_NUMGUIDES
#define FLUID_NAME_OBVEL
#define FLUID_NAME_HEATIN
#define FLUID_NAME_UV1
@ FLUID_DOMAIN_METHOD_APIC
#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
#define FLUID_NAME_ENERGY
#define FLUID_NAME_VELOCITYX
#define FLUID_NAME_DENSITYIN
#define FLUID_NAME_NORMAL_PARTICLES
@ SNDPARTICLE_BOUNDARY_DELETE
@ SNDPARTICLE_BOUNDARY_PUSHOUT
#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:108
#define pow
#define in
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)
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)