Read Smoke Data

I’m starting to create an script that reads and meshes smoke simulation data by dual contouring (avoids special cases, so it’s easier for me to program). Seeing as smoke data is non-binary (often used as an excuse to say that it cannot be meshed at all), I’ve opted to use a threshold design. Pretty much, if the density at a given point is greater than the threshold, it’s part of the mesh. If not, it’s empty.

How do I get the voxel data from a domain object?
Also, ideally, how can I get a list of all smoke domains?

I plan to turn the interface into something similar to that of CubeSurfer in the future, so any info regarding the process behind that is also welcome…

This is how it’s done in the LuxCoreRender Blender addon:

    # Search smoke domain target for smoke modifiers    
    smoke_domain_mod = utils.find_smoke_domain_modifier(smoke_obj)

    if smoke_domain_mod is None:
        msg = 'Object "%s" is not a smoke domain' %
        raise Exception(msg)

    settings = smoke_domain_mod.domain_settings

    if channel == "density":
        grid = settings.density_grid
    elif channel == "fire":
        grid = settings.flame_grid
    elif channel == "heat":
        grid = settings.heat_grid
    # ToDo: implement velocity grid export
    # velocity grid has 3 times more values => probably vector field
    #elif channel == "velocity":
    #    grid = settings.velocity_grid
        raise NotImplementedError("Unknown channel type " + channel)

    # Prevent a crash
    if len(grid) == 0:
        msg = 'Object "%s": No smoke data (simulate some frames first)' %
        raise Exception(msg)

    channeldata = list(grid)
    big_res = list(settings.domain_resolution)

    if settings.use_high_resolution:
        for i in range(3):
            big_res[i] *= settings.amplify + 1

Maybe it helps. I only wrote small parts of this code, so I’m not exactly sure what e.g. the “big_res” stuff does.
I think the “channeldata” variable contains the grid array in the end.

Thank you SO MUCH for finding this code!
When looking at the amplify function in the API, it seems like the big_res array enables (and apparently generates) support for the Smoke High Resolution upsampling / noise algorithm.
Generating it on the fly like this could be helpful in the viewport, and it’s what lets you choose whether or not to show smoke high resolution in the viewport.