Blender V5.0
smoke_script.h
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 <string>
10
12// VARIABLES
14
15const std::string smoke_variables =
16 "\n\
17mantaMsg('Smoke variables low')\n\
18preconditioner_s$ID$ = PcMGStatic\n\
19using_colors_s$ID$ = $USING_COLORS$\n\
20using_heat_s$ID$ = $USING_HEAT$\n\
21using_fire_s$ID$ = $USING_FIRE$\n\
22using_noise_s$ID$ = $USING_NOISE$\n\
23vorticity_s$ID$ = $VORTICITY$\n\
24buoyancy_dens_s$ID$ = float($BUOYANCY_ALPHA$) / float($FLUID_DOMAIN_SIZE$)\n\
25buoyancy_heat_s$ID$ = float($BUOYANCY_BETA$) / float($FLUID_DOMAIN_SIZE$)\n\
26dissolveSpeed_s$ID$ = $DISSOLVE_SPEED$\n\
27using_logdissolve_s$ID$ = $USING_LOG_DISSOLVE$\n\
28using_dissolve_s$ID$ = $USING_DISSOLVE$\n\
29flameVorticity_s$ID$ = $FLAME_VORTICITY$\n\
30burningRate_s$ID$ = $BURNING_RATE$\n\
31flameSmoke_s$ID$ = $FLAME_SMOKE$\n\
32ignitionTemp_s$ID$ = $IGNITION_TEMP$\n\
33maxTemp_s$ID$ = $MAX_TEMP$\n\
34flameSmokeColor_s$ID$ = vec3($FLAME_SMOKE_COLOR_X$,$FLAME_SMOKE_COLOR_Y$,$FLAME_SMOKE_COLOR_Z$)\n";
35
36const std::string smoke_variables_noise =
37 "\n\
38mantaMsg('Smoke variables noise')\n\
39wltStrength_s$ID$ = $WLT_STR$\n\
40uvs_s$ID$ = 2\n\
41uvs_offset_s$ID$ = vec3($MIN_RESX$, $MIN_RESY$, $MIN_RESZ$)\n\
42octaves_s$ID$ = int(math.log(upres_sn$ID$) / math.log(2.0) + 0.5) if (upres_sn$ID$ > 1) else 1\n";
43
44const std::string smoke_wavelet_noise =
45 "\n\
46# wavelet noise params\n\
47wltnoise_sn$ID$.posScale = vec3(int($BASE_RESX$), int($BASE_RESY$), int($BASE_RESZ$)) * (1. / $NOISE_POSSCALE$)\n\
48wltnoise_sn$ID$.timeAnim = $NOISE_TIMEANIM$\n";
49
50const std::string smoke_with_heat =
51 "\n\
52using_heat_s$ID$ = True\n";
53
54const std::string smoke_with_colors =
55 "\n\
56using_colors_s$ID$ = True\n";
57
58const std::string smoke_with_fire =
59 "\n\
60using_fire_s$ID$ = True\n";
61
63// GRIDS
65
66const std::string smoke_alloc =
67 "\n\
68mantaMsg('Smoke alloc')\n\
69shadow_s$ID$ = s$ID$.create(RealGrid, name='$NAME_SHADOW$', sparse=False)\n\
70emission_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSION$', sparse=True)\n\
71emissionIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_EMISSIONIN$')\n\
72density_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITY$', sparse=True)\n\
73densityIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITYIN$', sparse=True)\n\
74heat_s$ID$ = None # allocated dynamically\n\
75heatIn_s$ID$ = None\n\
76flame_s$ID$ = None\n\
77fuel_s$ID$ = None\n\
78react_s$ID$ = None\n\
79fuelIn_s$ID$ = None\n\
80reactIn_s$ID$ = None\n\
81color_r_s$ID$ = None\n\
82color_g_s$ID$ = None\n\
83color_b_s$ID$ = None\n\
84color_r_in_s$ID$ = None\n\
85color_g_in_s$ID$ = None\n\
86color_b_in_s$ID$ = None\n\
87\n\
88# Set some initial values\n\
89shadow_s$ID$.setConst(-1)\n\
90\n\
91# Keep track of important objects in dict to load them later on\n\
92smoke_data_dict_final_s$ID$ = { 'density' : density_s$ID$, 'shadow' : shadow_s$ID$ }\n\
93smoke_data_dict_resume_s$ID$ = { 'densityIn' : densityIn_s$ID$, 'emission' : emission_s$ID$ }\n";
94
95const std::string smoke_alloc_noise =
96 "\n\
97mantaMsg('Smoke alloc noise')\n\
98vel_sn$ID$ = sn$ID$.create(MACGrid, name='$NAME_VELOCITY_NOISE$')\n\
99density_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_DENSITY_NOISE$', sparse=True)\n\
100phiIn_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIIN_NOISE$')\n\
101phiOut_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOUT_NOISE$')\n\
102phiObs_sn$ID$ = sn$ID$.create(LevelsetGrid, name='$NAME_PHIOBS_NOISE$')\n\
103flags_sn$ID$ = sn$ID$.create(FlagGrid, name='$NAME_FLAGS_NOISE$')\n\
104tmpIn_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_TMPIN_NOISE$')\n\
105emissionIn_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_EMISSIONIN_NOISE$')\n\
106energy_s$ID$ = s$ID$.create(RealGrid, name='$NAME_ENERGY$')\n\
107tmpFlags_s$ID$ = s$ID$.create(FlagGrid, name='$NAME_TMPFLAGS$')\n\
108texture_u_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_U$')\n\
109texture_v_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_V$')\n\
110texture_w_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_W$')\n\
111texture_u2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_U2$')\n\
112texture_v2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_V2$')\n\
113texture_w2_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEXTURE_W2$')\n\
114flame_sn$ID$ = None\n\
115fuel_sn$ID$ = None\n\
116react_sn$ID$ = None\n\
117color_r_sn$ID$ = None\n\
118color_g_sn$ID$ = None\n\
119color_b_sn$ID$ = None\n\
120wltnoise_sn$ID$ = sn$ID$.create(NoiseField, fixedSeed=265, loadFromFile=True)\n\
121\n\
122mantaMsg('Initializing UV Grids')\n\
123uvGrid0_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV0$', sparse=False)\n\
124uvGrid1_s$ID$ = s$ID$.create(VecGrid, name='$NAME_UV1$', sparse=False)\n\
125resetUvGrid(target=uvGrid0_s$ID$, offset=uvs_offset_s$ID$)\n\
126resetUvGrid(target=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
127\n\
128# Sync UV and texture grids\n\
129copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
130copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n\
131\n\
132# Keep track of important objects in dict to load them later on\n\
133smoke_noise_dict_final_s$ID$ = { 'density_noise' : density_sn$ID$ }\n\
134smoke_noise_dict_resume_s$ID$ = { 'uv0_noise' : uvGrid0_s$ID$, 'uv1_noise' : uvGrid1_s$ID$ }\n";
135
137// ADDITIONAL GRIDS
139
140const std::string smoke_alloc_colors =
141 "\n\
142# Sanity check, clear grids first\n\
143if 'color_r_s$ID$' in globals(): del color_r_s$ID$\n\
144if 'color_g_s$ID$' in globals(): del color_g_s$ID$\n\
145if 'color_b_s$ID$' in globals(): del color_b_s$ID$\n\
146\n\
147mantaMsg('Allocating colors')\n\
148color_r_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORR$', sparse=True)\n\
149color_g_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORG$', sparse=True)\n\
150color_b_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORB$', sparse=True)\n\
151color_r_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORRIN$', sparse=True)\n\
152color_g_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORGIN$', sparse=True)\n\
153color_b_in_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORBIN$', sparse=True)\n\
154\n\
155# Add objects to dict to load them later on\n\
156if 'smoke_data_dict_final_s$ID$' in globals():\n\
157 smoke_data_dict_final_s$ID$.update(color_r=color_r_s$ID$, color_g=color_g_s$ID$, color_b=color_b_s$ID$)\n\
158if 'smoke_data_dict_resume_s$ID$' in globals():\n\
159 smoke_data_dict_resume_s$ID$.update(color_r_in=color_r_in_s$ID$, color_g_in=color_g_in_s$ID$, color_b_in=color_b_in_s$ID$)\n";
160
161const std::string smoke_alloc_colors_noise =
162 "\n\
163# Sanity check, clear grids first\n\
164if 'color_r_sn$ID$' in globals(): del color_r_sn$ID$\n\
165if 'color_g_sn$ID$' in globals(): del color_g_sn$ID$\n\
166if 'color_b_sn$ID$' in globals(): del color_b_sn$ID$\n\
167\n\
168mantaMsg('Allocating colors noise')\n\
169color_r_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORR_NOISE$', sparse=True)\n\
170color_g_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORG_NOISE$', sparse=True)\n\
171color_b_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORB_NOISE$', sparse=True)\n\
172\n\
173# Add objects to dict to load them later on\n\
174if 'smoke_noise_dict_final_s$ID$' in globals():\n\
175 smoke_noise_dict_final_s$ID$.update(color_r_noise=color_r_sn$ID$, color_g_noise=color_g_sn$ID$, color_b_noise=color_b_sn$ID$)\n";
176
177const std::string smoke_init_colors =
178 "\n\
179mantaMsg('Initializing colors')\n\
180color_r_s$ID$.copyFrom(density_s$ID$) \n\
181color_r_s$ID$.multConst($COLOR_R$) \n\
182color_g_s$ID$.copyFrom(density_s$ID$) \n\
183color_g_s$ID$.multConst($COLOR_G$) \n\
184color_b_s$ID$.copyFrom(density_s$ID$) \n\
185color_b_s$ID$.multConst($COLOR_B$)\n";
186
187const std::string smoke_init_colors_noise =
188 "\n\
189mantaMsg('Initializing colors noise')\n\
190color_r_sn$ID$.copyFrom(density_sn$ID$) \n\
191color_r_sn$ID$.multConst($COLOR_R$) \n\
192color_g_sn$ID$.copyFrom(density_sn$ID$) \n\
193color_g_sn$ID$.multConst($COLOR_G$) \n\
194color_b_sn$ID$.copyFrom(density_sn$ID$) \n\
195color_b_sn$ID$.multConst($COLOR_B$)\n";
196
197const std::string smoke_alloc_heat =
198 "\n\
199# Sanity check, clear grids first\n\
200if 'heat_s$ID$' in globals(): del heat_s$ID$\n\
201if 'heatIn_s$ID$' in globals(): del heatIn_s$ID$\n\
202\n\
203mantaMsg('Allocating heat')\n\
204heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATURE$', sparse=True)\n\
205heatIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_TEMPERATUREIN$', sparse=True)\n\
206\n\
207# Add objects to dict to load them later on\n\
208if 'smoke_data_dict_final_s$ID$' in globals():\n\
209 smoke_data_dict_final_s$ID$.update(heat=heat_s$ID$)\n\
210if 'smoke_data_dict_resume_s$ID$' in globals():\n\
211 smoke_data_dict_resume_s$ID$.update(heatIn=heatIn_s$ID$)\n";
212
213const std::string smoke_alloc_fire =
214 "\n\
215# Sanity check, clear grids first\n\
216if 'flame_s$ID$' in globals(): del flame_s$ID$\n\
217if 'fuel_s$ID$' in globals(): del fuel_s$ID$\n\
218if 'react_s$ID$' in globals(): del react_s$ID$\n\
219if 'fuelIn_s$ID$' in globals(): del fuelIn_s$ID$\n\
220if 'reactIn_s$ID$' in globals(): del reactIn_s$ID$\n\
221\n\
222mantaMsg('Allocating fire')\n\
223flame_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FLAME$', sparse=True)\n\
224fuel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUEL$', sparse=True)\n\
225react_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACT$', sparse=True)\n\
226fuelIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUELIN$', sparse=True)\n\
227reactIn_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACTIN$', sparse=True)\n\
228\n\
229# Add objects to dict to load them later on\n\
230if 'smoke_data_dict_final_s$ID$' in globals():\n\
231 smoke_data_dict_final_s$ID$.update(flame=flame_s$ID$)\n\
232if 'smoke_data_dict_resume_s$ID$' in globals():\n\
233 smoke_data_dict_resume_s$ID$.update(fuel=fuel_s$ID$, react=react_s$ID$, fuelIn=fuelIn_s$ID$, reactIn=reactIn_s$ID$)\n";
234
235const std::string smoke_alloc_fire_noise =
236 "\n\
237# Sanity check, clear grids first\n\
238if 'flame_sn$ID$' in globals(): del flame_sn$ID$\n\
239if 'fuel_sn$ID$' in globals(): del fuel_sn$ID$\n\
240if 'react_sn$ID$' in globals(): del react_sn$ID$\n\
241\n\
242mantaMsg('Allocating fire noise')\n\
243flame_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FLAME_NOISE$', sparse=True)\n\
244fuel_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FUEL_NOISE$', sparse=True)\n\
245react_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_REACT_NOISE$', sparse=True)\n\
246\n\
247# Add objects to dict to load them later on\n\
248if 'smoke_noise_dict_final_s$ID$' in globals():\n\
249 smoke_noise_dict_final_s$ID$.update(flame_noise=flame_sn$ID$)\n\
250if 'smoke_noise_dict_resume_s$ID$' in globals():\n\
251 smoke_noise_dict_resume_s$ID$.update(fuel_noise=fuel_sn$ID$, react_noise=react_sn$ID$)\n";
252
254// STEP FUNCTIONS
256
257const std::string smoke_adaptive_step =
258 "\n\
259def smoke_adaptive_step_$ID$(framenr):\n\
260 mantaMsg('Manta step, frame ' + str(framenr))\n\
261 s$ID$.frame = framenr\n\
262 \n\
263 fluid_pre_step_$ID$()\n\
264 \n\
265 flags_s$ID$.initDomain(boundaryWidth=0, phiWalls=phiObs_s$ID$, outflow=boundConditions_s$ID$)\n\
266 \n\
267 if using_obstacle_s$ID$:\n\
268 mantaMsg('Extrapolating object velocity')\n\
269 # ensure velocities inside of obs object, slightly add obvels outside of obs object\n\
270 # extrapolate with phiObsIn before joining (static) phiObsSIn grid to prevent flows into static obs\n\
271 extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
272 extrapolateVec3Simple(vel=obvelC_s$ID$, phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
273 resampleVec3ToMac(source=obvelC_s$ID$, target=obvel_s$ID$)\n\
274 \n\
275 mantaMsg('Initializing obstacle levelset')\n\
276 phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
277 phiObsIn_s$ID$.floodFill(boundaryWidth=1)\n\
278 extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
279 extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
280 phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
281 \n\
282 # Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
283 phiObs_s$ID$.floodFill(boundaryWidth=1)\n\
284 extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
285 extrapolateLsSimple(phi=phiObs_s$ID$, distance=3, inside=False)\n\
286 \n\
287 mantaMsg('Initializing fluid levelset')\n\
288 phiIn_s$ID$.join(phiSIn_s$ID$) # Join static flow map\n\
289 extrapolateLsSimple(phi=phiIn_s$ID$, distance=6, inside=True)\n\
290 extrapolateLsSimple(phi=phiIn_s$ID$, distance=3, inside=False)\n\
291 \n\
292 if using_outflow_s$ID$:\n\
293 phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
294 phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
295 \n\
296 setObstacleFlags(flags=flags_s$ID$, phiObs=phiObs_s$ID$, phiOut=phiOut_s$ID$, phiIn=phiIn_s$ID$, boundaryWidth=1)\n\
297 flags_s$ID$.fillGrid()\n\
298 \n\
299 # reset emission accumulation at the beginning of an adaptive frame\n\
300 if not s$ID$.timePerFrame:\n\
301 emission_s$ID$.setConst(0.)\n\
302 # accumulate emission value per adaptive step for later use in noise computation\n\
303 emission_s$ID$.join(emissionIn_s$ID$)\n\
304 \n\
305 applyEmission(flags=flags_s$ID$, target=density_s$ID$, source=densityIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
306 if using_heat_s$ID$:\n\
307 applyEmission(flags=flags_s$ID$, target=heat_s$ID$, source=heatIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
308 \n\
309 if using_colors_s$ID$:\n\
310 applyEmission(flags=flags_s$ID$, target=color_r_s$ID$, source=color_r_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
311 applyEmission(flags=flags_s$ID$, target=color_g_s$ID$, source=color_g_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
312 applyEmission(flags=flags_s$ID$, target=color_b_s$ID$, source=color_b_in_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
313 \n\
314 if using_fire_s$ID$:\n\
315 applyEmission(flags=flags_s$ID$, target=fuel_s$ID$, source=fuelIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
316 applyEmission(flags=flags_s$ID$, target=react_s$ID$, source=reactIn_s$ID$, emissionTexture=emissionIn_s$ID$, type=FlagInflow|FlagOutflow)\n\
317 \n\
318 mantaMsg('Smoke step / s$ID$.frame: ' + str(s$ID$.frame))\n\
319 if using_fire_s$ID$:\n\
320 process_burn_$ID$()\n\
321 smoke_step_$ID$()\n\
322 if using_fire_s$ID$:\n\
323 update_flame_$ID$()\n\
324 \n\
325 s$ID$.step()\n\
326 \n\
327 fluid_post_step_$ID$()\n";
328
329const std::string smoke_step =
330 "\n\
331def smoke_step_$ID$():\n\
332 mantaMsg('Smoke step low')\n\
333 \n\
334 # save original state for later (used during noise creation)\n\
335 velTmp_s$ID$.copyFrom(vel_s$ID$)\n\
336 \n\
337 if using_dissolve_s$ID$:\n\
338 mantaMsg('Dissolving smoke')\n\
339 dissolveSmoke(flags=flags_s$ID$, density=density_s$ID$, heat=heat_s$ID$, red=color_r_s$ID$, green=color_g_s$ID$, blue=color_b_s$ID$, \
340 speed=dissolveSpeed_s$ID$, logFalloff=using_logdissolve_s$ID$, dissolveScale=s$ID$.timestep / frameLengthUnscaled_s$ID$)\n\
341 \n\
342 mantaMsg('Advecting density')\n\
343 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=density_s$ID$, order=2)\n\
344 \n\
345 if using_heat_s$ID$:\n\
346 mantaMsg('Advecting heat')\n\
347 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=heat_s$ID$, order=2)\n\
348 \n\
349 if using_fire_s$ID$:\n\
350 mantaMsg('Advecting fire')\n\
351 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=fuel_s$ID$, order=2)\n\
352 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=react_s$ID$, order=2)\n\
353 \n\
354 if using_colors_s$ID$:\n\
355 mantaMsg('Advecting colors')\n\
356 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_r_s$ID$, order=2)\n\
357 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_g_s$ID$, order=2)\n\
358 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=color_b_s$ID$, order=2)\n\
359 \n\
360 mantaMsg('Advecting velocity')\n\
361 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=vel_s$ID$, order=2)\n\
362 \n\
363 if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
364 resetOutflow(flags=flags_s$ID$, real=density_s$ID$)\n\
365 \n\
366 mantaMsg('Vorticity')\n\
367 if using_fire_s$ID$:\n\
368 flame_s$ID$.copyFrom(fuel_s$ID$) # temporarily misuse flame grid as vorticity storage\n\
369 flame_s$ID$.multConst(flameVorticity_s$ID$ * s$ID$.timestep / frameLengthUnscaled_s$ID$)\n\
370 vorticityConfinement(vel=vel_s$ID$, flags=flags_s$ID$, strength=vorticity_s$ID$ * s$ID$.timestep / frameLengthUnscaled_s$ID$, strengthCell=flame_s$ID$ if using_fire_s$ID$ else None)\n\
371 \n\
372 if using_heat_s$ID$:\n\
373 mantaMsg('Adding heat buoyancy')\n\
374 addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$, scale=False)\n\
375 mantaMsg('Adding buoyancy')\n\
376 addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$, scale=False)\n\
377 \n\
378 mantaMsg('Adding forces')\n\
379 addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
380 \n\
381 # Cells inside obstacle should not contain any density, fire, etc.\n\
382 if deleteInObstacle_s$ID$:\n\
383 resetInObstacle(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, heat=heat_s$ID$, fuel=fuel_s$ID$, flame=flame_s$ID$, red=color_r_s$ID$, green=color_g_s$ID$, blue=color_b_s$ID$)\n\
384 \n\
385 # add initial velocity\n\
386 if using_invel_s$ID$:\n\
387 # Using cell centered invels, will be converted to MAC within the function\n\
388 setInitialVelocity(flags=flags_s$ID$, vel=vel_s$ID$, invel=invelC_s$ID$)\n\
389 \n\
390 mantaMsg('Walls')\n\
391 setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=obvel_s$ID$ if using_obstacle_s$ID$ else None)\n\
392 \n\
393 preconditioner_s$ID$ = PcMGDynamic if using_obstacle_s$ID$ and obvel_s$ID$.getMax() > 0 else PcMGStatic\n\
394 mantaMsg('Using preconditioner: ' + str(preconditioner_s$ID$))\n\
395 if using_guiding_s$ID$:\n\
396 mantaMsg('Guiding and pressure')\n\
397 PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=domainClosed_s$ID$)\n\
398 else:\n\
399 mantaMsg('Pressure')\n\
400 solvePressure(flags=flags_s$ID$, vel=vel_s$ID$, pressure=pressure_s$ID$, preconditioner=preconditioner_s$ID$, zeroPressureFixing=domainClosed_s$ID$) # closed domains require pressure fixing\n\
401\n\
402def process_burn_$ID$():\n\
403 mantaMsg('Process burn')\n\
404 processBurn(fuel=fuel_s$ID$, density=density_s$ID$, react=react_s$ID$, red=color_r_s$ID$, green=color_g_s$ID$, blue=color_b_s$ID$, heat=heat_s$ID$, burningRate=burningRate_s$ID$, flameSmoke=flameSmoke_s$ID$, ignitionTemp=ignitionTemp_s$ID$, maxTemp=maxTemp_s$ID$, flameSmokeColor=flameSmokeColor_s$ID$)\n\
405\n\
406def update_flame_$ID$():\n\
407 mantaMsg('Update flame')\n\
408 updateFlame(react=react_s$ID$, flame=flame_s$ID$)\n";
409
410const std::string smoke_step_noise =
411 "\n\
412def smoke_step_noise_$ID$(framenr):\n\
413 mantaMsg('Manta step noise, frame ' + str(framenr))\n\
414 sn$ID$.frame = framenr\n\
415 \n\
416 copyRealToVec3(sourceX=texture_u_s$ID$, sourceY=texture_v_s$ID$, sourceZ=texture_w_s$ID$, target=uvGrid0_s$ID$)\n\
417 copyRealToVec3(sourceX=texture_u2_s$ID$, sourceY=texture_v2_s$ID$, sourceZ=texture_w2_s$ID$, target=uvGrid1_s$ID$)\n\
418 \n\
419 flags_sn$ID$.initDomain(boundaryWidth=0, phiWalls=phiObs_sn$ID$, outflow=boundConditions_s$ID$)\n\
420 \n\
421 mantaMsg('Interpolating grids')\n\
422 # Join big obstacle levelset after initDomain() call as it overwrites everything in phiObs\n\
423 if using_obstacle_s$ID$:\n\
424 phiIn_sn$ID$.copyFrom(phiObsIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiIn_sn$ID$, source=phiObsIn_s$ID$) # mis-use phiIn_sn\n\
425 phiObs_sn$ID$.join(phiIn_sn$ID$)\n\
426 if using_outflow_s$ID$:\n\
427 phiOut_sn$ID$.copyFrom(phiOut_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiOut_sn$ID$, source=phiOut_s$ID$)\n\
428 phiIn_sn$ID$.copyFrom(phiIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(target=phiIn_sn$ID$, source=phiIn_s$ID$)\n\
429 vel_sn$ID$.copyFrom(velTmp_s$ID$) if upres_sn$ID$ <= 1 else interpolateMACGrid(target=vel_sn$ID$, source=velTmp_s$ID$)\n\
430 \n\
431 setObstacleFlags(flags=flags_sn$ID$, phiObs=phiObs_sn$ID$, phiOut=phiOut_sn$ID$, phiIn=phiIn_sn$ID$, boundaryWidth=1)\n\
432 flags_sn$ID$.fillGrid()\n\
433 \n\
434 # Interpolate emission grids and apply them to big noise grids\n\
435 tmpIn_sn$ID$.copyFrom(densityIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=densityIn_s$ID$, target=tmpIn_sn$ID$)\n\
436 emissionIn_sn$ID$.copyFrom(emission_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=emission_s$ID$, target=emissionIn_sn$ID$)\n\
437 \n\
438 # Higher-res noise grid needs scaled emission values\n\
439 tmpIn_sn$ID$.multConst(float(upres_sn$ID$))\n\
440 applyEmission(flags=flags_sn$ID$, target=density_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
441 \n\
442 if using_colors_s$ID$:\n\
443 tmpIn_sn$ID$.copyFrom(color_r_in_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=color_r_in_s$ID$, target=tmpIn_sn$ID$)\n\
444 applyEmission(flags=flags_sn$ID$, target=color_r_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
445 tmpIn_sn$ID$.copyFrom(color_g_in_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=color_g_in_s$ID$, target=tmpIn_sn$ID$)\n\
446 applyEmission(flags=flags_sn$ID$, target=color_g_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
447 tmpIn_sn$ID$.copyFrom(color_b_in_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=color_b_in_s$ID$, target=tmpIn_sn$ID$)\n\
448 applyEmission(flags=flags_sn$ID$, target=color_b_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
449 \n\
450 if using_fire_s$ID$:\n\
451 tmpIn_sn$ID$.copyFrom(fuelIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=fuelIn_s$ID$, target=tmpIn_sn$ID$)\n\
452 applyEmission(flags=flags_sn$ID$, target=fuel_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
453 tmpIn_sn$ID$.copyFrom(reactIn_s$ID$) if upres_sn$ID$ <= 1 else interpolateGrid(source=reactIn_s$ID$, target=tmpIn_sn$ID$)\n\
454 applyEmission(flags=flags_sn$ID$, target=react_sn$ID$, source=tmpIn_sn$ID$, emissionTexture=emissionIn_sn$ID$, type=FlagInflow|FlagOutflow)\n\
455 \n\
456 mantaMsg('Noise step / sn$ID$.frame: ' + str(sn$ID$.frame))\n\
457 if using_fire_s$ID$:\n\
458 process_burn_noise_$ID$()\n\
459 step_noise_$ID$()\n\
460 if using_fire_s$ID$:\n\
461 update_flame_noise_$ID$()\n\
462 \n\
463 sn$ID$.step()\n\
464 \n\
465 copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
466 copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n\
467\n\
468def step_noise_$ID$():\n\
469 mantaMsg('Smoke step noise')\n\
470 \n\
471 if using_dissolve_s$ID$:\n\
472 mantaMsg('Dissolving noise')\n\
473 dissolveSmoke(flags=flags_sn$ID$, density=density_sn$ID$, heat=None, red=color_r_sn$ID$, green=color_g_sn$ID$, blue=color_b_sn$ID$, \
474 speed=dissolveSpeed_s$ID$, logFalloff=using_logdissolve_s$ID$, dissolveScale=s$ID$.timestep / frameLengthUnscaled_s$ID$)\n\
475 \n\
476 mantaMsg('Advecting UVs and updating UV weight')\n\
477 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid0_s$ID$, order=2)\n\
478 updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=0, numUvs=uvs_s$ID$, uv=uvGrid0_s$ID$, offset=uvs_offset_s$ID$)\n\
479 advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid1_s$ID$, order=2)\n\
480 updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=1, numUvs=uvs_s$ID$, uv=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\
481 \n\
482 if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\
483 resetOutflow(flags=flags_sn$ID$, real=density_sn$ID$)\n\
484 \n\
485 mantaMsg('Energy')\n\
486 computeEnergy(flags=flags_s$ID$, vel=vel_s$ID$, energy=energy_s$ID$)\n\
487 \n\
488 tmpFlags_s$ID$.copyFrom(flags_s$ID$)\n\
489 extrapolateSimpleFlags(flags=flags_s$ID$, val=tmpFlags_s$ID$, distance=2, flagFrom=FlagObstacle, flagTo=FlagFluid)\n\
490 extrapolateSimpleFlags(flags=tmpFlags_s$ID$, val=energy_s$ID$, distance=6, flagFrom=FlagFluid, flagTo=FlagObstacle)\n\
491 computeWaveletCoeffs(energy_s$ID$)\n\
492 \n\
493 sStr_s$ID$ = 1.0 * wltStrength_s$ID$\n\
494 sPos_s$ID$ = 2.0\n\
495 \n\
496 mantaMsg('Applying noise vec')\n\
497 for o in range(octaves_s$ID$):\n\
498 uvWeight_s$ID$ = getUvWeight(uvGrid0_s$ID$)\n\
499 applyNoiseVec3(flags=flags_sn$ID$, target=vel_sn$ID$, noise=wltnoise_sn$ID$, scale=sStr_s$ID$ * uvWeight_s$ID$, scaleSpatial=sPos_s$ID$ , weight=energy_s$ID$, uv=uvGrid0_s$ID$)\n\
500 uvWeight_s$ID$ = getUvWeight(uvGrid1_s$ID$)\n\
501 applyNoiseVec3(flags=flags_sn$ID$, target=vel_sn$ID$, noise=wltnoise_sn$ID$, scale=sStr_s$ID$ * uvWeight_s$ID$, scaleSpatial=sPos_s$ID$ , weight=energy_s$ID$, uv=uvGrid1_s$ID$)\n\
502 \n\
503 sStr_s$ID$ *= 0.06 # magic kolmogorov factor \n\
504 sPos_s$ID$ *= 2.0 \n\
505 \n\
506 for substep in range(int(upres_sn$ID$)):\n\
507 if using_colors_s$ID$: \n\
508 mantaMsg('Advecting colors noise')\n\
509 advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_r_sn$ID$, order=2)\n\
510 advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_g_sn$ID$, order=2)\n\
511 advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=color_b_sn$ID$, order=2)\n\
512 \n\
513 if using_fire_s$ID$: \n\
514 mantaMsg('Advecting fire noise')\n\
515 advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=fuel_sn$ID$, order=2)\n\
516 advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=react_sn$ID$, order=2)\n\
517 \n\
518 mantaMsg('Advecting density noise')\n\
519 advectSemiLagrange(flags=flags_sn$ID$, vel=vel_sn$ID$, grid=density_sn$ID$, order=2)\n\
520\n\
521def process_burn_noise_$ID$():\n\
522 mantaMsg('Process burn noise')\n\
523 processBurn(fuel=fuel_sn$ID$, density=density_sn$ID$, react=react_sn$ID$, red=color_r_sn$ID$, green=color_g_sn$ID$, blue=color_b_sn$ID$, burningRate=burningRate_s$ID$, flameSmoke=flameSmoke_s$ID$, ignitionTemp=ignitionTemp_s$ID$, maxTemp=maxTemp_s$ID$, flameSmokeColor=flameSmokeColor_s$ID$)\n\
524\n\
525def update_flame_noise_$ID$():\n\
526 mantaMsg('Update flame noise')\n\
527 updateFlame(react=react_sn$ID$, flame=flame_sn$ID$)\n";
528
530// IMPORT
532
533const std::string smoke_load_data =
534 "\n\
535def smoke_load_data_$ID$(path, framenr, file_format, resumable):\n\
536 mantaMsg('Smoke load data')\n\
537 dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **smoke_data_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **smoke_data_dict_final_s$ID$ }\n\
538 fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$)\n\
539 \n\
540 copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n";
541
542const std::string smoke_load_noise =
543 "\n\
544def smoke_load_noise_$ID$(path, framenr, file_format, resumable):\n\
545 mantaMsg('Smoke load noise')\n\
546 dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
547 fluid_file_import_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_noise_s$ID$)\n\
548 \n\
549 if resumable:\n\
550 # Fill up xyz texture grids, important when resuming a bake\n\
551 copyVec3ToReal(source=uvGrid0_s$ID$, targetX=texture_u_s$ID$, targetY=texture_v_s$ID$, targetZ=texture_w_s$ID$)\n\
552 copyVec3ToReal(source=uvGrid1_s$ID$, targetX=texture_u2_s$ID$, targetY=texture_v2_s$ID$, targetZ=texture_w2_s$ID$)\n";
553
555// EXPORT
557
558const std::string smoke_save_data =
559 "\n\
560def smoke_save_data_$ID$(path, framenr, file_format, resumable):\n\
561 mantaMsg('Smoke save data')\n\
562 start_time = time.time()\n\
563 dict = { **fluid_data_dict_final_s$ID$, **fluid_data_dict_resume_s$ID$, **smoke_data_dict_final_s$ID$, **smoke_data_dict_resume_s$ID$ } if resumable else { **fluid_data_dict_final_s$ID$, **smoke_data_dict_final_s$ID$ } \n\
564 if not withMPSave or isWindows:\n\
565 fluid_file_export_s$ID$(dict=dict, path=path, framenr=framenr, file_format=file_format, file_name=file_data_s$ID$, clipGrid=density_s$ID$)\n\
566 else:\n\
567 fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_data_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n\
568 mantaMsg('--- Save: %s seconds ---' % (time.time() - start_time))\n";
569
570const std::string smoke_save_noise =
571 "\n\
572def smoke_save_noise_$ID$(path, framenr, file_format, resumable):\n\
573 mantaMsg('Smoke save noise')\n\
574 dict = { **smoke_noise_dict_final_s$ID$, **smoke_noise_dict_resume_s$ID$ } if resumable else { **smoke_noise_dict_final_s$ID$ } \n\
575 if not withMPSave or isWindows:\n\
576 fluid_file_export_s$ID$(dict=dict, framenr=framenr, file_format=file_format, path=path, file_name=file_noise_s$ID$, clipGrid=density_sn$ID$)\n\
577 else:\n\
578 fluid_cache_multiprocessing_start_$ID$(function=fluid_file_export_s$ID$, file_name=file_noise_s$ID$, framenr=framenr, format_data=file_format, path_data=path, dict=dict, do_join=False)\n";
579
581// STANDALONE MODE
583
584const std::string smoke_standalone =
585 "\n\
586# Helper function to call cache load functions\n\
587def load_data(frame, cache_resumable):\n\
588 smoke_load_data_$ID$(os.path.join(cache_dir, 'data'), frame, file_format_data, cache_resumable)\n\
589 if using_noise_s$ID$:\n\
590 smoke_load_noise_$ID$(os.path.join(cache_dir, 'noise'), frame, file_format_data, cache_resumable)\n\
591 if using_guiding_s$ID$:\n\
592 fluid_load_guiding_$ID$(os.path.join(cache_dir, 'guiding'), frame, file_format_data)\n\
593\n\
594# Helper function to call step functions\n\
595def step(frame):\n\
596 smoke_adaptive_step_$ID$(frame)\n\
597 if using_noise_s$ID$:\n\
598 smoke_step_noise_$ID$(frame)\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