#------------------------------------------------------------------------------
# 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)