From 14a1ab26980f53cffa21b5d0cc7c64dc428bab45 Mon Sep 17 00:00:00 2001 From: Andrea Paris Date: Mon, 19 Jan 2026 08:57:32 +0100 Subject: [PATCH 1/2] Fix USD volume range and skip NanoVDB grids with no active voxels --- tsd/src/tsd/io/importers/import_NVDB.cpp | 28 ++++++++++++++++++++++++ tsd/src/tsd/io/importers/import_USD.cpp | 6 +++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tsd/src/tsd/io/importers/import_NVDB.cpp b/tsd/src/tsd/io/importers/import_NVDB.cpp index 53e7433da..897502317 100644 --- a/tsd/src/tsd/io/importers/import_NVDB.cpp +++ b/tsd/src/tsd/io/importers/import_NVDB.cpp @@ -30,6 +30,34 @@ SpatialFieldRef import_NVDB(Scene &scene, const char *filepath) try { auto grid = nanovdb::io::readGrid(filepath); auto metadata = grid.gridMetaData(); + + bool hasActiveVoxels = false; + switch (metadata->gridType()) { + case nanovdb::GridType::Fp4: + hasActiveVoxels = grid.grid()->activeVoxelCount() > 0; + break; + case nanovdb::GridType::Fp8: + hasActiveVoxels = grid.grid()->activeVoxelCount() > 0; + break; + case nanovdb::GridType::Fp16: + hasActiveVoxels = grid.grid()->activeVoxelCount() > 0; + break; + case nanovdb::GridType::FpN: + hasActiveVoxels = grid.grid()->activeVoxelCount() > 0; + break; + case nanovdb::GridType::Float: + hasActiveVoxels = grid.grid()->activeVoxelCount() > 0; + break; + default: + break; + } + + if (!hasActiveVoxels) { + logStatus("[import_NVDB] no active voxels, skipping '%s'", filepath); + scene.removeObject(field.data()); + return {}; + } + if (!metadata->hasMinMax()) { switch (metadata->gridType()) { case nanovdb::GridType::Fp4: { diff --git a/tsd/src/tsd/io/importers/import_USD.cpp b/tsd/src/tsd/io/importers/import_USD.cpp index e30ce42f9..2f1b26208 100644 --- a/tsd/src/tsd/io/importers/import_USD.cpp +++ b/tsd/src/tsd/io/importers/import_USD.cpp @@ -910,7 +910,8 @@ static void import_usd_volume(Scene &scene, VolumeTransferFunction tf = get_volume_transfer_function(prim); ArrayRef colorArray; - math::float2 valueRange; + // Default to the field's value range to avoid undefined ranges. + math::float2 valueRange = field->computeValueRange(); // Create a volume node and assign the field, color map, and value range auto [inst, volume] = scene.insertNewChildObjectNode( @@ -922,7 +923,8 @@ static void import_usd_volume(Scene &scene, // Use transfer function from USD material colorArray = scene.createArray(ANARI_FLOAT32_VEC4, tf.colors.size()); colorArray->setData(tf.colors.data(), tf.colors.size()); - valueRange = tf.domain; + if (tf.domain.x < tf.domain.y) + valueRange = tf.domain; // Create opacity control points from USD transfer function std::vector opacityControlPoints; From de6d0e7c83e66e99179e6f3aa65d7c1adaeac4f4 Mon Sep 17 00:00:00 2001 From: Andrea Paris Date: Fri, 6 Feb 2026 09:14:25 +0100 Subject: [PATCH 2/2] Added environment variable to decide on invalid nvdbs --- tsd/CMakeLists.txt | 2 ++ tsd/src/tsd/io/CMakeLists.txt | 6 ++++++ tsd/src/tsd/io/importers/import_NVDB.cpp | 11 +++++++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tsd/CMakeLists.txt b/tsd/CMakeLists.txt index baba550af..85e2ab75e 100644 --- a/tsd/CMakeLists.txt +++ b/tsd/CMakeLists.txt @@ -59,6 +59,8 @@ option(TSD_USE_TORCH "Use PyTorch for importing neural geometries" OFF) option(TSD_USE_VTK "Use VTK for importing VTK file formats" OFF) option(TSD_USE_SILO "Use Silo for importing Silo file formats" OFF) option(TSD_USE_MPI "Enable MPI support" OFF) +option(TSD_NANOVDB_SKIP_INVALID_VOLUMES + "Skip NanoVDB volumes with zero active voxels" OFF) if (APPLE) set(TSD_USE_CUDA OFF) diff --git a/tsd/src/tsd/io/CMakeLists.txt b/tsd/src/tsd/io/CMakeLists.txt index bc49ad184..4d4bc7cc5 100644 --- a/tsd/src/tsd/io/CMakeLists.txt +++ b/tsd/src/tsd/io/CMakeLists.txt @@ -141,3 +141,9 @@ if (TSD_USE_SILO) else() project_compile_definitions(PRIVATE -DTSD_USE_SILO=0) endif() + +if (TSD_NANOVDB_SKIP_INVALID_VOLUMES) + project_compile_definitions(PRIVATE -DTSD_NANOVDB_SKIP_INVALID_VOLUMES=1) +else() + project_compile_definitions(PRIVATE -DTSD_NANOVDB_SKIP_INVALID_VOLUMES=0) +endif() diff --git a/tsd/src/tsd/io/importers/import_NVDB.cpp b/tsd/src/tsd/io/importers/import_NVDB.cpp index 897502317..1e30c26c3 100644 --- a/tsd/src/tsd/io/importers/import_NVDB.cpp +++ b/tsd/src/tsd/io/importers/import_NVDB.cpp @@ -23,7 +23,6 @@ SpatialFieldRef import_NVDB(Scene &scene, const char *filepath) std::string file = fileOf(filepath); if (file.empty()) return {}; - auto field = scene.createObject(tokens::spatial_field::nanovdb); field->setName(file.c_str()); @@ -53,9 +52,13 @@ SpatialFieldRef import_NVDB(Scene &scene, const char *filepath) } if (!hasActiveVoxels) { - logStatus("[import_NVDB] no active voxels, skipping '%s'", filepath); - scene.removeObject(field.data()); - return {}; + logWarning("[import_NVDB] no active voxels in '%s'", filepath); + if (TSD_NANOVDB_SKIP_INVALID_VOLUMES) { + logStatus( + "[import_NVDB] skipping due to TSD_NANOVDB_SKIP_INVALID_VOLUMES"); + scene.removeObject(field.data()); + return {}; + } } if (!metadata->hasMinMax()) {