#------------------------------------------------------------------------------ # convert_to_vdb.py - Create OpenVDB (.vdb) volume data file from # image data in argument JSON file. JSON file is generated using # "VTK To OpenVDB Exporter" node in BVTKNodes (Blender add-on). # # Run example: python3 convert_to_vdb.py volume_00001.json # # Requirement: pyopenvdb module must be available to Python # # If you get error like: # "libjemalloc.so.2: cannot allocate memory in static TLS block" # then prepend command with LD_PRELOAD: # LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 python3 convert_to_vdb.py volume_00001.json #------------------------------------------------------------------------------ import sys import json try: import pyopenvdb vdb = pyopenvdb except ImportError: print("ERROR: Python can't import pyopenvdb. Please see " + "VTK To OpenVDB Exporter node documentation for more information.") raise def create_grid(background_value, dims, array, grid_name, atype): """ Return an OpenVDB grid with dimensions dims containing data from array. """ if array == None: return None if atype == 'scalar': grid = vdb.FloatGrid(background_value) elif atype == 'vector': grid = vdb.Vec3SGrid() else: raise TypeError("Unknown type %s" % str(atype)) grid.gridClass = vdb.GridClass.FOG_VOLUME grid.name = grid_name # Create grid by looping over points with accessor acc = grid.getAccessor() for i in range(dims[0]): for j in range(dims[1]): for k in range(dims[2]): idx = i + j*dims[0] + k*dims[0]*dims[1] value = array[idx] if atype == 'scalar': if value == None: continue if value > background_value: acc.setValueOn((i, j, k), value) elif atype == 'vector': if value[0] == None: continue acc.setValueOn((i, j, k), value) return grid def count_active_voxels(grids): """ Counts the number of active voxels in list of OpenVDB grids """ n = 0 for grid in grids: n += grid.activeVoxelCount() return n def create_vdb(vdb_filename, background_value, dims, density_data, color_data, flame_data, temperature_data): """ Create vdb file from argument data. """ density_grid = create_grid(background_value, dims, density_data, 'density', 'scalar') color_grid = create_grid(background_value, dims, color_data, 'color', 'vector') flame_grid = create_grid(background_value, dims, flame_data, 'flame', 'scalar') temperature_grid = create_grid(background_value, dims, temperature_data, 'temperature', 'scalar') grids = [density_grid, color_grid, flame_grid, temperature_grid] grids = [g for g in grids if g is not None] nvoxels = count_active_voxels(grids) vdb.write(vdb_filename, grids=grids) print("%s: %d grids, %d active voxels exported." % (vdb_filename, len(grids), nvoxels)) # Main program: Process all arguments for filename in sys.argv[1:]: with open(filename, "r") as read_file: background_value, dims, density_data, color_data, flame_data, \ temperature_data = json.load(read_file) vdb_filename = filename.replace('.json', '.vdb') create_vdb(vdb_filename, background_value, dims, density_data, color_data, flame_data, temperature_data)