MAXScripting FumeFX


MAXScript is a powerful 3ds Max language that allows users to customize their interface, automate tasks, or increase functionality. FumeFX`s open architecture facilitates the use of this tool, which means you can tailor FumeFX to meet your own needs. Refer to the 3ds Max Reference Guide for general information on how to use this tool.




Here is a list of global variables exposed to MXS.


ffxSilent - No Message box will show up (like Stop/Continue).



Adding/Removing objects

Here is a list of all functions exposed by FumeFX Geometry Source.



Returns the number of objects.


<node>GetObject <integer>index

Returns object.

index - its range goes from 0 to NumObjects()-1


<boolean>AddObject <node>node

It will add an object to the list. No duplicates or unsupported objects will be added.


<boolean>RemoveObjectByNode <node>node

Removes object based on the node.


<boolean>RemoveObjectByIndex <integer>index

Removed object based on the object`s index.



Saving and Loading Presets

Here is a list of all functions exposed by FumeFX.


SavePresets <filename>presetFile

This saves all current FumeFX settings to a preset file "presetFile.fxp" in default preset folder. The output returns false on error.
If user provides a full path to the preset file (like c:\\mypresets\\explosion.fxp) then the preset file will be saved to the specified folder.


LoadPresets <filename>presetFile <rollout_names_array>rollouts

Use this to load all or some of the controls from the preset file "presetFile.fxp". The output returns false upon error.

If user provides a full path to the preset file (like c:\\mypresets\\explosion.fxp) then the preset file will be loaded from the specified folder.


The Rollouts parameter is an array with some of the following values:


all: load all rollouts


grid: load all rollouts from Grid Tab


sim: load all rollouts from Simulation Tab


render: load all rollouts from Render Tab


illum: load all rollouts from Illumination Tab


grid_dim: load Grid Tab / General Parameters Rollout


grid_play: load Grid Tab / Playback Rollout


grid_rec: load Grid Tab / Recording Parameters Rollout


sim_main: load Simulation Tab / Simulation Rollout


sim_smoke: load Simulation Tab / Smoke Rollout


sim_fuel: load Simulation Tab / Fuel Rollout


sim_temp: load Simulation Tab / Temperature Rollout


sim_fm: load Simulation Tab / Fluid Mapping Rollout


render_main: load Rendering Tab / Rendering Parameters


shader: load Rendering Tab / Shader Rollout




-- have FumeFX01 save its settings to file mypreset.fxp in default presets folder

$FumeFX01.SavePresets "mypreset1"


-- have selected FumeFX object load Render Tab > Render parameters rollup and Simulation Tab > Fuel rollup from file mypreset1.fxd.

$.LoadPresets "mypreset1" #("render_main", "sim_fuel")


-- have FumeFX01 load all rollouts in Grid Tab from file mypreset.fxd.

$FumeFX01.LoadPresets "mypreset" "grid"



Adding/Removing objects, lights, sources


Returns number of sources.


<node>GetSource <integer>index

Returns source.

index - its range goes from 0 to NumSources()-1

<boolean> AddSource <node>source

Use this to attach FumeFX Sources to FumeFX. It is equivalent to picking a Source object in the Objects panel of the Floater Window.


<boolean> RemoveSource <node>source

Use this to remove Force FumeFX Sources from FumeFX. It is equivalent to removing a Source object in the Objects panel of the Floater Window.


<boolean> AddForce <node>force

Use this to attach Force objects like Wind to FumeFX. It is equivalent to picking a Force object in Objects panel of the Floater Window.


<boolean> RemoveForce <node> force

Use this to remove Force objects like Wind from FumeFX. It is equivalent to removing a Force object in Objects panel of the Floater Window.


<integer> NumObjects()

Returns a number of objects that are currently picked.


<maxObject>GetObject <integer>index

Returns object based on index (zero based index).


<boolean>AddLight <node>node
Adds a light


<boolean>RemoveLight <node>node

Removes light


<integer> NumEffectors()

Returns a number of Effectors that are currently picked.


<maxObject>GetEffector <integer>index

Returns Effector based on index (zero based index).


<integer> NumSpaceWarps()

Returns a number of objects that are currently picked.


<maxObject>GetSpaceWarp <integer>index

Returns SpaceWarp based on index (zero based index).



Shader Access


Returns current shader.


<boolean>SetShaderByName <string>name

Sets current shader based on name.


<boolean>SetShaderByIndex <integer>index

Sets current shader based on index (zero based).



Simulation Control


This command will cancel the simulation



This command will stop the simulation. This means it will finish the current frame and save stop/continue data according to the preferences settings.


<void>RunSimulation <integer>simMode

This does exactly the same as hitting the start button on the FumeFX Floater. Simulation will run from StartFrame to EndFrame.

simMode - 0 - Default Simulation

1 - Simulation from Initial State

2 - Wavelet Simulation

3 - Retimer


<void>ContinueSimulation <integer>simMode

This does exactly the same as hitting the continue button on the FumeFX Floater

simMode - 0 - Default Simulation

1 - Default Simulation

2 - Wavelet Simulation


<boolean>SetInitialStateFile <filename>filename

Use this command to set Initial State file to be used with Initial State Simulation Mode.



Returns Initial State file name.


SaveOutput <filename>outputFile

This saves a .fxd type output file; note, you must enter the full file name. Output returns false on error.


SaveSim <filename>presetFile

This saves a .fdc type simulation file; note, you must enter full file name. Output returns false on error.


<boolean>LoadSim <filename>filename

This will load a .fdc file into the FumeFX.


<filename>GetPath <string>type

This returns the current base output file name without the frame number suffix.

cacheType -default - path for Deault Sim. caches

wavelet- path for Wavelet Sim. caches

retimer - path for Retimer caches

illummap - path for Illumination Map

preview - path for preview animation clip

presets - path for presets

defaultpreset - path for the default preset file (Preferences)

scrsim - FumeFX MXS file


<boolean>SetPath <filename>path <name array>params

params -match- if grid is of different proportions, FumeFX will be matched to it.

default - path for Deault Sim. caches

wavelet- path for Wavelet Sim. caches

retimer - path for Retimer caches

illummap - path for Illumination Map

preview- path for preview animation clip

defaultpreset - path for the default preset file (Preferences)

nocheck - path validity won`t be checked.

scrsim - FumeFX MXS file



This sets output file name. You must enter the path and base file name; the extension is not necessary.


$FumeFX01.SetPath "F:\\temp\\FumeFX\\aa"

$FumeFX01.SetPath "F:\\temp\\FumeFX\\aa.fxd"
$FumeFX01.SetPath "F:\\temp\\FumeFX\\aa.fxd" #("default", "nocheck")

$FumeFX01.SetPath "F:\\temp\\FumeFX\\aa_0000.fxd" #("default","match")
For #match, if you omit _0000 (or any existing frame number), FumeFX and cache won`t be checked for grid dimensions and won`t be matched if grid and cache have different sizes.


<void>DeleteCaches <string>name

This command will delete all the cache files

Name -default- path for Default Sim. caches

wavelet- path for Wavelet Sim. caches

retimer- path for Retimer Sim. caches

illummap - path for Illumination Map. caches


<boolean>ExportRenderingParams <string>name

This will save current frame rendering params to the file.



Misc. Functions

<int>GetBBox <point3>&dim0 <point3>&dim1

This command will return the cache number that is currently loaded and FumeFX bounding box in local coordinates. The return number of -99999 could indicate that there was no cache loaded in memory at the time this function was called.
Returned values in dim0 and dim1 are corners of the bounding box.



$.GetBBox &min &max


<int>GetFireInfo<float>&min <float>&max <float>&avg

<int>GetSmokeInfo<float>&min <float>&max <float>&avg
<int>GetTempInfo<float>&min <float>&max <float>&avg
<int>GetVelInfo<float>&min <float>&max <float>&avg

This command will return the cache number that is currently loaded. The return number of

-99999 could indicate that there was no cache loaded in memory at the time this function was called or that channel was not present inside the cache.

min - returns the minimum channel value inside the grid

min - returns the maximum channel value inside the grid

avg - returns the average channel value inside the grid (empty voxels are excluded).
After the simulation is finished FumeFX will load channels depending on the viewport or requirements. To force channel to be loaded you should enable its display inside the viewport.



FumeFX MAXScript Functions for Accessing the Simulation

By learning to use FumeFX functions created for MAXScript, you can do almost anything that you want with FumeFX - including things not provided for in the default user interface. It is possible for you to plug in script between all significant phases of the simulation or even disable some simulation steps altogether.


In this version of FumeFX, MAXScript cannot be called from the Listener, Macro Scripts, or in any other way except from within FumeFX while the simulation is running or the output is being loaded. Preparation of the scripts takes place in the General panel of the Floater Window. You can access this by clicking the Edit Script button in the MAXScript rollout.


If you create a script that will modify all of the voxels in a simulation (which could be tens of millions), it will execute at reasonable speeds, measured in seconds.


To get the feel of it, here is an example script:

fn PostObjects = (

for i in 0 to (nx - 1) do

for j in 0 to (ny - 1) do

for k in 0 to (nz - 1) do(

val=k/(nz as float)

      SetSmoke i j k val




PostObjects is a "callback" function that FumeFX will call in every frame of the simulation after it has applied all sources and objects. It will go through all voxels in the adaptive grid (nx, ny and nz are global variables provided by FumeFX) and initialize the Smoke channel with a vertical gradient going from 0 to 1 over the local Z-axis. Channel is set using voxel coordinates.



MAXScript in FumeFX Simulation

How it works:

When you click Edit Script in the Simulation group, you will see a template in which to write your scripts. In it there are certain MAXScript functions that FumeFX will call during simulation. All of them are called once for each step of the simulation, unless otherwise noted.


Callback Functions

Note: Currently, the PostAdvection and PostPressure functions are for experimental use only, but are provided for those who are familiar with their use.


PreSim: Called once - at the beginning of simulation, before the first step has started, but after possible snapshot or stop/continue data has been loaded.


PostSim: Called once - after the last step of the simulation has ended and while the simulation results are still in memory.


PostObjects: Think of this as a scripted Source. It is called after the Adaptive grid has adjusted and FumeFX Sources, objects, and forces have all been applied. Here, you can additionally initialize the grid any way you like.


Vorticity: This is the only place where Vorticity can be customized. The AddVort function allows every voxel can have its own Vorticity strength. Be aware that the stability of simulation can become unreliable when using values greater than 1.


PostForces: Buoyancy, Gravity, Vorticity, Motion Drag have been applied. Here you can apply custom forces such as: radial gravity, motion drag dependent on object distance, etc???


PostAdvection: This is called after Velocities have moved through one step. If you have disabled FumeFX`s Advection phase, you could theoretically write your own version in this function.


PostDiffuse: This is called after movement of Smoke and Fuel and their diffusion and dissipation. This is the proper time to set Fuel and Temperature values to control fires.


PostStep: This is called following a whole simulation step, after the Fuel has been burned and diffusion and dissipation applied. You can set any kind of influence between channels here. If you have disabled FumeFX`s Burn phase, you could use this to burn Fuel your way.



Skipping FumeFX Simulation Phases

If you want to skip certain FumeFX simulation phases completely, uncomment in the template, or write the following statements on the global level of the script:

skipForces = true

skipAdvectFields = true

skipAdvectVels = true

skipPressure = true

skipBurn = true


This is not recommended unless you have experience.


A few examples of when you can skip certain phases are:


You can skip Pressure and Advection phase if you simulate only the effects of diffusion.


You can skip the Burn phase if you want to burn Fuel some other way.


You can skip Forces if you want to apply buoyancy, gravity or motion drag in some specific way, such as depending on position or distance from objects.


So, what can you do within these functions? Basically, you can get and set values for the main channels: Smoke, Fuel, Temperature and Velocity. You can also stop or cancel simulation and write messages to the FumeFX status window.



Simulation Control Functions

ffxPrintToStatus <string>message

This prints message to FumeFX status window during simulation.



This is equivalent to pressing the Stop button in the status window.



This is equivalent to pressing the Cancel button in the status window.



If this function is called during simulation, then after the simulation has stopped or cancelled, the simulation window will stay open, regardless of Hold Window checkbox selection.



Get Channel Functions

Smoke is used in this example; however, all other channels are analogous. The ways to get Smoke values are:


GetSmoke <integer>i <integer>j <integer>k

In this function, i, j, and k respectively represent the X, Y, and Z-axis coordinates in an adaptive grid. Voxel coordinates can range from 0 to nx-1 for i, 0 to ny-1 for j, and 0 to nz-1 for k. So, to get the smoke value in first voxel you would write

GetSmoke 0 0 0


Or, to get it from the top center voxel you would write:

GetSmoke (nx/2) (ny/2) (nz)


GetSmokeByIndex <integer>index

This is slightly faster than the form GetSmoke i j k. It uses only one parameter, voxel index, which is computed (i*ny + j)*nz + k.

To get the average value of smoke

average = 0.0

for ind in 0 to (voxels-1) do (average += GetSmokeByIndex ind)

average /= voxels


GetSmokeLocal <point3>lpt

Here lpt is a point in a FumeFX object or local space. Unless the pivot is moved, the center of that coordinate system is the bottom center point of the FumeFX object. FumeFX dimensions are exposed through FumeFX nodes: Width, Length, and Height.

GetSmokeLocal [10.0, 10.0, $FumeFX01.Heigth/2]


GetSmokeWorld <point3>wpt <matrix3>FumeFXt

Here wpt is a position in world coordinates. You must also provide a FumeFX transformation matrix.


To get Smoke density at some object`s position

wpt = $sensor01.position

tm = $FumeFX01.transform

if ((GetSmokeWorld wpt tm) > threshold) then myfunction()


These functions will return undefined if you ask for non-existing coordinates or coordinates outside of the grid. They will also return undefined if the channel has not been allocated - for example GetFuel() if Simulate Fire has been turned off in the Simulation tab.


A complete list of Get functions:


float GetSmoke


float GetSmokeByIndex


float GetSmokeLocal


float GetSmokeWorld


float GetTemp


float GetTempByIndex


float GetTempLocal


float GetTempWorld


float GetOxy


float GetOxyByIndex


float GetOxyLocal


float GetOxyWorld


float GetFuel


float GetFuelByIndex


float GetFuelLocal


float GetFuelWorld


point3 GetVel


point3 GetVelByIndex


point3 GetVelLocal


point3 GetVelWorld


Usage of functions:


GetChannel i j k


GetChannelByIndex index


GetChannelLocal lpt


GetChannelWorld wpt TM


Index and i,j,k coordinates must be passed as integers.



Set Channel Functions

To set channel values, functions are provided that are analogous to the Get functions. They only have one additional parameter - value to set. Input ranges are not checked - so accuracy is important. The output can return true or false even if the value was, for some reason, not set.

These functions set value at one voxel only - the voxel that the point belongs to.


SetSmoke <integer>i <integer>j <integer>k <float>value

This uses adaptive grid voxel coordinates.


SetSmokeByIndex <integer>index <float>value

This uses voxel index.


SetSmokeLocal <point3>lpt <float>value

This uses FumeFX local coordinates.


SetSmokeWorld <point3>wpt <matrix3>FumeFXtm <float>value

This uses world coordinates.


A complete list of Set functions:


float SetSmoke


float SetSmokeByIndex


float SetSmokeLocal


float SetSmokeWorld


float SetTemp


float SetTempByIndex


float SetTempLocal


float SetTempWorld


float SetOxy


float SetOxyByIndex


float SetOxyLocal


float SetOxyWorld


float SetFuel


float SetFuelByIndex


float SetFuelLocal


float SetFuelWorld


point3 SetVel


point3 SetVelByIndex


point3 SetVelLocal


point3 SetVelWorld


Usage of functions:


SetChannel i j k value


SetChannelByIndex index value


SetChannelLocal lpt value


SetChannelWorld wpt TM value


Smoke, Fuel and Temperature are float channels, and Velocity is a point3 channel. Remember to set the point3 channels with the point3 values, for example:


SetVelByIndex index [x,y,z]



More Channel Functions

There are also functions for Vorticity and Turbulence. Used in simulation, they are cumulative with UI defined global Vorticity and Turbulence. If you wish to use only the scripted values, you must set Vorticity and Turbulence strength in the UI to 0.


Note: Vorticity strengths above 1 may, in rare cases, make the simulation unstable.


To add Turbulence, you can use:


AddTurb <integer>i <integer>j <integer>k <float>value


AddTurbByIndex <integer>index <float>value


AddVort functions can only be used during Vorticity callback.


AddVort <integer>i <integer>j <integer>k <float>value


AddVortByIndex <integer>index <float>value


You can fill the entire channel with a given value using the following functions:


FillSmoke <float>value


FillFuel <float>value


FillTemp <float>value


FillVel <point3>value



MAXScript after Loading Output

It is possible to post-process FumeFX output files at the time of loading. Here, for example, you can change the displayed result or the result used by the particles without affecting the simulation. Appropriate callback is called PostLoad.


Example: To set smoke to any given minimum value throughout the entire grid, achieving a fog-like effect, enter the following script.


fn PostLoad = (

sm = 1.0 -- desired minimum smoke value

for i in 0 to (voxels-1) do


s = GetSmokeByIndex i

if (s < sm) then ( SetSmokeByIndex i sm )





Switching Between Coordinates

If you want to make modifications to FumeFX voxels, you will most often run loops in voxel space or index range. However, you may need to do some calculations in local or world space for some modifications. For this and similar cases, converter functions exist between various coordinate spaces that FumeFX uses.


List of functions:


<integer> ffxVoxelPtToIndex <point3>vpt


<point3> ffxVoxelPtToLocal <point3>vpt


<point3> ffxVoxelPtToWorld <point3>vpt



<point3> ffxIndexToVoxel <integer>ind


<point3> ffxIndexToLocal <integer>ind


<point3> ffxIndexToWorld <integer>ind



<integer> ffxLocalPtToIndex <point3>lpt


<point3> ffxLocalPtToVoxel <point3>lpt


<point3> ffxLocalPtToWorld <point3>lpt



<integer> ffxWorldPtToIndex <point3>wpt


<point3> ffxWorldPtToVoxel <point3>wpt


<point3> ffxWorldPtToLocal <point3>wpt



VoxelPtTo??? functions take point3 as argument, in adaptive grid coordinates, ranging [0.,0.,0.] - [nx, ny, nz].


IndexTo??? functions take integer as argument, ranging from 0 to (voxels-1).


LocalPtTo??? functions take point3 as argument, in FumeFX local coordinates, ranging from [-Width/2, -Length/2, 0.] - [Width/2, Length/2, Height] for values inside the FumeFX grid.


WorldPtTo??? functions take point3 as argument, in world coordinates.


IndexTo??? functions must get valid index or they return undefined, other functions will convert between spaces regardless of whether the point is within FumeFX grid or not.


???ToVoxel functions return point3 ranging from 0 to [0.,0.,0.] - [nx, ny, nz].


???ToIndex functions return integer ranging from 0 to (voxels-1).


???ToLocal functions return point3 ranging from 0 to [-Width/2, -Length/2, 0.] - [Width/2, Length/2, Height] for values inside FumeFX grid.


???ToWorld functions return point3 in world space.



Various Issues

FumeFX will execute MAXScript commands in a single thread, but the usual simulation phases still execute in multiple threads. So, if you do heavy scripting you can expect some slowdowns.


If you Get and Set just a few channel values at once, you will not have to be concerned with memory issues. However, should you want to keep a copy of a whole channel in memory as a MAXScript array, you will have to enlarge MAXScript`s heap size. To do this, go to Customize -> Preferences -> MaxScript tab -> Memory group -> Initial heap allocation. To copy a float channel with 1 million voxels to MAXScript`s array you will need 28MB of MAXScript Heap memory, and for a point3 channel you will need 36MB.


If you no longer need such a big array or if you want to overwrite it, do the following:


arrayname = #() -- make it an empty array


arrayname = undefined -- or undefine it completely


gc light:true -- wipe it from memory


The statement "gc" invokes the MAXScript garbage collector. Otherwise, if the array takes most of the MAXScript heap, just writing to the same array twice may take an incredibly long time. See the "Memory Allocation and Garbage Collection" and "Manual Garbage Collection" in the MAXScript User Reference for more detail.




You have to provide valid values to FumeFX when you set them.

For Fuel, ranges are -100 to 100. Set negative values to have fuel in non-burning state, or set positive values to have already burning fuel.


If you want to use the time slider`s global variable in FumeFX scripts, add one frame to it. FumeFX sets the time slider when it has finished calculating a frame. For example, when calculation of frame 5 is in progress, the slider time global variable will still be at frame 4.