diff --git a/include/neural-graphics-primitives/testbed.h b/include/neural-graphics-primitives/testbed.h
index 0edbf9fda724f797d78fe584374203bc841a16e1..4514162b062e06a4d568d2ef88b7ceafd3315226 100644
--- a/include/neural-graphics-primitives/testbed.h
+++ b/include/neural-graphics-primitives/testbed.h
@@ -70,6 +70,7 @@ public:
 
 	bool clear_tmp_dir();
 	void load_training_data(const std::string& data_path);
+	void reload_training_data();
 	void clear_training_data();
 
 	void set_mode(ETestbedMode mode);
diff --git a/src/testbed.cu b/src/testbed.cu
index 119b011f2f7691188b2f30f2d6eec883c9636d7e..ab674113ae56b85086f29c869376775e7bd493e6 100644
--- a/src/testbed.cu
+++ b/src/testbed.cu
@@ -99,6 +99,32 @@ json merge_parent_network_config(const json &child, const fs::path &child_filena
 	return parent;
 }
 
+std::string get_filename_in_data_path_with_suffix(fs::path data_path, fs::path network_config_path, const char* suffix) {
+	// use the network config name along with the data path to build a filename with the requested suffix & extension
+	std::string default_name = network_config_path.basename();
+	if (default_name == "") {
+		default_name = "base";
+	}
+
+	if (data_path.empty()) {
+		return default_name + std::string(suffix);
+	}
+
+	if (data_path.is_directory()) {
+		return (data_path / (default_name + std::string{suffix})).str();
+	}
+
+	return data_path.stem().str() + "_" + default_name + std::string(suffix);
+}
+
+void Testbed::update_imgui_paths() {
+	snprintf(m_imgui.cam_path_path, sizeof(m_imgui.cam_path_path), "%s", get_filename_in_data_path_with_suffix(m_data_path, m_network_config_path, "_cam.json").c_str());
+	snprintf(m_imgui.extrinsics_path, sizeof(m_imgui.extrinsics_path), "%s", get_filename_in_data_path_with_suffix(m_data_path, m_network_config_path, "_extrinsics.json").c_str());
+	snprintf(m_imgui.mesh_path, sizeof(m_imgui.mesh_path), "%s", get_filename_in_data_path_with_suffix(m_data_path, m_network_config_path, ".obj").c_str());
+	snprintf(m_imgui.snapshot_path, sizeof(m_imgui.snapshot_path), "%s", get_filename_in_data_path_with_suffix(m_data_path, m_network_config_path, ".msgpack").c_str());
+	snprintf(m_imgui.video_path, sizeof(m_imgui.video_path), "%s", get_filename_in_data_path_with_suffix(m_data_path, m_network_config_path, "_video.mp4").c_str());
+}
+
 void Testbed::load_training_data(const std::string& data_path_str) {
 	fs::path data_path = data_path_str;
 	if (!data_path.exists()) {
@@ -115,19 +141,23 @@ void Testbed::load_training_data(const std::string& data_path_str) {
 
 	m_data_path = data_path;
 
-	if (!m_data_path.exists()) {
-		throw std::runtime_error{fmt::format("Data path '{}' does not exist.", m_data_path.str())};
-	}
-
 	switch (m_testbed_mode) {
-		case ETestbedMode::Nerf:   load_nerf(); break;
-		case ETestbedMode::Sdf:    load_mesh(); break;
-		case ETestbedMode::Image:  load_image(); break;
-		case ETestbedMode::Volume: load_volume(); break;
+		case ETestbedMode::Nerf:   load_nerf(data_path); break;
+		case ETestbedMode::Sdf:    load_mesh(data_path); break;
+		case ETestbedMode::Image:  load_image(data_path); break;
+		case ETestbedMode::Volume: load_volume(data_path); break;
 		default: throw std::runtime_error{"Invalid testbed mode."};
 	}
 
 	m_training_data_available = true;
+
+	update_imgui_paths();
+}
+
+void Testbed::reload_training_data() {
+	if (m_data_path.exists()) {
+		load_training_data(m_data_path.str());
+	}
 }
 
 void Testbed::clear_training_data() {
@@ -1511,6 +1541,7 @@ bool Testbed::keyboard_event() {
 		}
 	}
 
+	bool ctrl = ImGui::GetIO().KeyMods & ImGuiKeyModFlags_Ctrl;
 	bool shift = ImGui::GetIO().KeyMods & ImGuiKeyModFlags_Shift;
 
 	if (ImGui::IsKeyPressed('Z')) {
@@ -1530,6 +1561,15 @@ bool Testbed::keyboard_event() {
 		if (shift) {
 			reset_camera();
 		} else {
+			if (ctrl) {
+				reload_training_data();
+				// After reloading the training data, also reset the NN.
+				// Presumably, there is no use case where the user would
+				// like to hot-reload the same training data set other than
+				// to slightly tweak its parameters. And to observe that
+				// effect meaningfully, the NN should be trained from scratch.
+			}
+
 			reload_network_from_file();
 		}
 	}
diff --git a/src/testbed_image.cu b/src/testbed_image.cu
index 742a3b1784c3d9c670b4d2cd43069dbcc96bb627..0b8313f72ec97f6fdfd41e272a5b1c0e9183be98 100644
--- a/src/testbed_image.cu
+++ b/src/testbed_image.cu
@@ -27,6 +27,7 @@
 
 using namespace Eigen;
 using namespace tcnn;
+namespace fs = filesystem;
 
 NGP_NAMESPACE_BEGIN
 
@@ -359,53 +360,44 @@ void Testbed::render_image(CudaRenderBuffer& render_buffer, cudaStream_t stream)
 	);
 }
 
-void Testbed::load_image() {
-	if (equals_case_insensitive(m_data_path.extension(), "exr")) {
-		load_exr_image();
-	} else if (equals_case_insensitive(m_data_path.extension(), "bin")) {
-		load_binary_image();
+void Testbed::load_image(const fs::path& data_path) {
+	if (equals_case_insensitive(data_path.extension(), "exr")) {
+		load_exr_image(data_path);
+	} else if (equals_case_insensitive(data_path.extension(), "bin")) {
+		load_binary_image(data_path);
 	} else {
-		load_stbi_image();
+		load_stbi_image(data_path);
 	}
 
-#ifdef COLOR_SPACE_CONVERT
-	const dim3 threads = { 32, 32, 1 };
-	const dim3 blocks = { div_round_up((uint32_t)m_image.resolution.x(), threads.x), div_round_up((uint32_t)m_image.resolution.x(), threads.y), 1 };
-	if (m_image.type == EDataType::Half)
-		colorspace_convert_image_half<<<blocks, threads, 0>>>(m_image.resolution, m_image.data.data());
-	else
-		colorspace_convert_image_float<<<blocks, threads, 0>>>(m_image.resolution, m_image.data.data());
-#endif
-
 	tlog::success()
 		<< "Loaded a " << (m_image.type == EDataType::Half ? "half" : "full") << "-precision image with "
 		<< m_image.resolution.x() << "x" << m_image.resolution.y() << " pixels.";
 }
 
-void Testbed::load_exr_image() {
-	if (!m_data_path.exists()) {
-		throw std::runtime_error{fmt::format("Image file '{}' does not exist.", m_data_path.str())};
+void Testbed::load_exr_image(const fs::path& data_path) {
+	if (!data_path.exists()) {
+		throw std::runtime_error{fmt::format("Image file '{}' does not exist.", data_path.str())};
 	}
 
-	tlog::info() << "Loading EXR image from " << m_data_path;
+	tlog::info() << "Loading EXR image from " << data_path;
 
 	// First step: load an image that we'd like to learn
-	GPUMemory<float> image = load_exr(m_data_path.str(), m_image.resolution.x(), m_image.resolution.y());
+	GPUMemory<float> image = load_exr(data_path.str(), m_image.resolution.x(), m_image.resolution.y());
 	m_image.data.resize(image.size() * sizeof(float));
 	CUDA_CHECK_THROW(cudaMemcpy(m_image.data.data(), image.data(), image.size() * sizeof(float), cudaMemcpyDeviceToDevice));
 
 	m_image.type = EDataType::Float;
 }
 
-void Testbed::load_stbi_image() {
-	if (!m_data_path.exists()) {
-		throw std::runtime_error{fmt::format("Image file '{}' does not exist.", m_data_path.str())};
+void Testbed::load_stbi_image(const fs::path& data_path) {
+	if (!data_path.exists()) {
+		throw std::runtime_error{fmt::format("Image file '{}' does not exist.", data_path.str())};
 	}
 
-	tlog::info() << "Loading STBI image from " << m_data_path;
+	tlog::info() << "Loading STBI image from " << data_path;
 
 	// First step: load an image that we'd like to learn
-	GPUMemory<float> image = load_stbi(m_data_path.str(), m_image.resolution.x(), m_image.resolution.y());
+	GPUMemory<float> image = load_stbi(data_path.str(), m_image.resolution.x(), m_image.resolution.y());
 	m_image.data.resize(image.size() * sizeof(float));
 	CUDA_CHECK_THROW(cudaMemcpy(m_image.data.data(), image.data(), image.size() * sizeof(float), cudaMemcpyDeviceToDevice));
 
@@ -413,14 +405,14 @@ void Testbed::load_stbi_image() {
 }
 
 
-void Testbed::load_binary_image() {
-	if (!m_data_path.exists()) {
-		throw std::runtime_error{fmt::format("Image file '{}' does not exist.", m_data_path.str())};
+void Testbed::load_binary_image(const fs::path& data_path) {
+	if (!data_path.exists()) {
+		throw std::runtime_error{fmt::format("Image file '{}' does not exist.", data_path.str())};
 	}
 
-	tlog::info() << "Loading binary image from " << m_data_path;
+	tlog::info() << "Loading binary image from " << data_path;
 
-	std::ifstream f(m_data_path.str(), std::ios::in | std::ios::binary);
+	std::ifstream f(data_path.str(), std::ios::in | std::ios::binary);
 	f.read(reinterpret_cast<char*>(&m_image.resolution.y()), sizeof(int));
 	f.read(reinterpret_cast<char*>(&m_image.resolution.x()), sizeof(int));
 
diff --git a/src/testbed_nerf.cu b/src/testbed_nerf.cu
index 1b4624dc42965797f41327e59aff923b35c20de1..cc054f828d981e1efae0f85f3ec1bc07bbe14f7f 100644
--- a/src/testbed_nerf.cu
+++ b/src/testbed_nerf.cu
@@ -2546,8 +2546,9 @@ void Testbed::Nerf::Training::update_transforms(int first, int last) {
 
 void Testbed::create_empty_nerf_dataset(size_t n_images, int aabb_scale, bool is_hdr) {
 	m_data_path = {};
+	set_mode(ETestbedMode::Nerf);
 	m_nerf.training.dataset = ngp::create_empty_nerf_dataset(n_images, aabb_scale, is_hdr);
-	load_nerf();
+	load_nerf(m_data_path);
 	m_nerf.training.n_images_for_training = 0;
 	m_training_data_available = true;
 }
@@ -2644,21 +2645,21 @@ void Testbed::load_nerf_post() { // moved the second half of load_nerf here
 	m_up_dir = m_nerf.training.dataset.up;
 }
 
-void Testbed::load_nerf() {
-	if (!m_data_path.empty()) {
+void Testbed::load_nerf(const fs::path& data_path) {
+	if (!data_path.empty()) {
 		std::vector<fs::path> json_paths;
-		if (m_data_path.is_directory()) {
-			for (const auto& path : fs::directory{m_data_path}) {
+		if (data_path.is_directory()) {
+			for (const auto& path : fs::directory{data_path}) {
 				if (path.is_file() && equals_case_insensitive(path.extension(), "json")) {
 					json_paths.emplace_back(path);
 				}
 			}
-		} else if (equals_case_insensitive(m_data_path.extension(), "msgpack")) {
-			load_snapshot(m_data_path.str());
+		} else if (equals_case_insensitive(data_path.extension(), "msgpack")) {
+			load_snapshot(data_path.str());
 			set_train(false);
 			return;
-		} else if (equals_case_insensitive(m_data_path.extension(), "json")) {
-			json_paths.emplace_back(m_data_path);
+		} else if (equals_case_insensitive(data_path.extension(), "json")) {
+			json_paths.emplace_back(data_path);
 		} else {
 			throw std::runtime_error{"NeRF data path must either be a json file or a directory containing json files."};
 		}
diff --git a/src/testbed_sdf.cu b/src/testbed_sdf.cu
index 5a0065e8874545fddc6783ff3b0aa6dc057182d8..df98fa5ba161839b5112c6d624ae1463324111ff 100644
--- a/src/testbed_sdf.cu
+++ b/src/testbed_sdf.cu
@@ -32,6 +32,7 @@
 
 using namespace Eigen;
 using namespace tcnn;
+namespace fs = filesystem;
 
 NGP_NAMESPACE_BEGIN
 
@@ -1012,42 +1013,59 @@ void Testbed::render_sdf(
 		for (uint32_t i = 0; i < n_hit; ++i) {
 			total_n_steps += payloads_final_cpu[i].n_steps;
 		}
+
 		tlog::info() << "Total steps per hit= " << total_n_steps << "/" << n_hit << " = " << ((float)total_n_steps/(float)n_hit);
 	}
 }
 
-void Testbed::load_mesh() {
+std::vector<Vector3f> load_stl(const std::string& filename) {
 	std::vector<Vector3f> vertices;
-	if (equals_case_insensitive(m_data_path.extension(), "obj")) {
-		vertices = load_obj(m_data_path.str());
-	} else if (equals_case_insensitive(m_data_path.extension(), "stl")) {
-		FILE* f = fopen(m_data_path.str().c_str(), "rb");
-		if (!f) {
-			throw std::runtime_error{"stl file not found"};
-		}
-		uint32_t buf[21]={};
-		if (fread(buf, 4, 21, f) != 4*21) {
-			throw std::runtime_error{"stl file too small for header"};
-		}
-		uint32_t nfaces = buf[20];
-		if (memcmp(buf,"solid",5)==0 || buf[20]==0) {
-			fclose(f);
-			throw std::runtime_error{"ascii stl files are not supported"};
-		}
-		vertices.reserve(nfaces * 3);
-		for (uint32_t i = 0; i < nfaces; ++i) {
-			if (fread(buf, 1, 50, f) < 50) {
-				nfaces = i;
-				break;
-			}
-			vertices.push_back(*(Vector3f*)(buf + 3));
-			vertices.push_back(*(Vector3f*)(buf + 6));
-			vertices.push_back(*(Vector3f*)(buf + 9));
+
+	std::ifstream f{filename, std::ios::in | std::ios::binary};
+	if (!f) {
+		throw std::runtime_error{fmt::format("Mesh file '{}' not found", filename)};
+	}
+
+	uint32_t buf[21] = {};
+	f.read((char*)buf, 4 * 21);
+	if (f.gcount() < 4 * 21) {
+		throw std::runtime_error{fmt::format("Mesh file '{}' too small for STL header", filename)};
+	}
+
+	uint32_t nfaces = buf[20];
+	if (memcmp(buf, "solid", 5) == 0 || buf[20] == 0) {
+		throw std::runtime_error{fmt::format("ASCII STL file '{}' not supported", filename)};
+	}
+
+	vertices.reserve(nfaces * 3);
+	for (uint32_t i = 0; i < nfaces; ++i) {
+		f.read((char*)buf, 50);
+		if (f.gcount() < 50) {
+			nfaces = i;
+			break;
 		}
-		fclose(f);
+
+		vertices.push_back(*(Vector3f*)(buf + 3));
+		vertices.push_back(*(Vector3f*)(buf + 6));
+		vertices.push_back(*(Vector3f*)(buf + 9));
+	}
+
+	return vertices;
+}
+
+void Testbed::load_mesh(const fs::path& data_path) {
+	tlog::info() << "Loading mesh from '" << data_path << "'";
+	auto start = std::chrono::steady_clock::now();
+
+	std::vector<Vector3f> vertices;
+	if (equals_case_insensitive(data_path.extension(), "obj")) {
+		vertices = load_obj(data_path.str());
+	} else if (equals_case_insensitive(data_path.extension(), "stl")) {
+		vertices = load_stl(data_path.str());
 	} else {
-		throw std::runtime_error{"Sdf data path must be a mesh in ascii .obj or binary .stl format."};
+		throw std::runtime_error{"SDF data path must be a mesh in ascii .obj or binary .stl format."};
 	}
+
 	// The expected format is
 	// [v1.x][v1.y][v1.z][v2.x]...
 	size_t n_vertices = vertices.size();
@@ -1076,6 +1094,7 @@ void Testbed::load_mesh() {
 	for (size_t i = 0; i < n_vertices; ++i) {
 		m_aabb.enlarge(vertices[i]);
 	}
+
 	m_aabb.inflate(m_aabb.diag().norm() * inflation);
 	m_aabb = m_aabb.intersection(BoundingBox{Vector3f::Zero(), Vector3f::Ones()});
 	m_render_aabb = m_aabb;
@@ -1087,8 +1106,10 @@ void Testbed::load_mesh() {
 		m_sdf.triangles_cpu[i/3] = {vertices[i+0], vertices[i+1], vertices[i+2]};
 	}
 
-	if (!m_sdf.triangle_bvh)
+	if (!m_sdf.triangle_bvh) {
 		m_sdf.triangle_bvh = TriangleBvh::make();
+	}
+
 	m_sdf.triangle_bvh->build(m_sdf.triangles_cpu, 8);
 	m_sdf.triangles_gpu.resize_and_copy_from_host(m_sdf.triangles_cpu);
 	m_sdf.triangle_bvh->build_optix(m_sdf.triangles_gpu, m_stream.get());
@@ -1116,7 +1137,8 @@ void Testbed::load_mesh() {
 	m_sdf.training.idx = 0;
 	m_sdf.training.size = 0;
 
-	tlog::success() << "Loaded mesh: triangles=" << n_triangles << " AABB=" << m_raw_aabb << " after scaling=" << m_aabb;
+	tlog::success() << "Loaded mesh after " << tlog::durationToString(std::chrono::steady_clock::now() - start);
+	tlog::info() << "  n_triangles=" << n_triangles << " aabb=" << m_raw_aabb;
 }
 
 void Testbed::generate_training_samples_sdf(Vector3f* positions, float* distances, uint32_t n_to_generate, cudaStream_t stream, bool uniform_only) {
diff --git a/src/testbed_volume.cu b/src/testbed_volume.cu
index 6559f08b0ac9b4a255f6b0f1d31f6f90b538160b..168b666fb6b063f26a81d7d9dc9a84d9515f7581 100644
--- a/src/testbed_volume.cu
+++ b/src/testbed_volume.cu
@@ -33,6 +33,7 @@
 
 using namespace Eigen;
 using namespace tcnn;
+namespace fs = filesystem;
 
 NGP_NAMESPACE_BEGIN
 
@@ -549,12 +550,12 @@ struct NanoVDBMetaData
 };
 static_assert(sizeof(NanoVDBMetaData) == 176, "nanovdb padding error");
 
-void Testbed::load_volume() {
-	if (!m_data_path.exists()) {
-		throw std::runtime_error{m_data_path.str() + " does not exist."};
+void Testbed::load_volume(const fs::path& data_path) {
+	if (!data_path.exists()) {
+		throw std::runtime_error{data_path.str() + " does not exist."};
 	}
-	tlog::info() << "Loading NanoVDB file from " << m_data_path;
-	std::ifstream f(m_data_path.str(), std::ios::in | std::ios::binary);
+	tlog::info() << "Loading NanoVDB file from " << data_path;
+	std::ifstream f(data_path.str(), std::ios::in | std::ios::binary);
 	NanoVDBFileHeader header;
 	NanoVDBMetaData metadata;
 	f.read(reinterpret_cast<char*>(&header), sizeof(header));
@@ -584,37 +585,41 @@ void Testbed::load_volume() {
 	m_volume.nanovdb_grid.copy_from_host(cpugrid);
 	const nanovdb::FloatGrid* grid = reinterpret_cast<const nanovdb::FloatGrid*>(cpugrid.data());
 
-	float mn=1e10f,mx=-1e10f;
+	float mn = 10000.0f, mx = -10000.0f;
 	bool hmm = grid->hasMinMax();
 	//grid->tree().extrema(mn,mx);
-	int  xsize = std::max(1,metadata.indexBBox[1][0]-metadata.indexBBox[0][0]);
-	int ysize = std::max(1,metadata.indexBBox[1][1]-metadata.indexBBox[0][1]);
-	int zsize = std::max(1,metadata.indexBBox[1][2]-metadata.indexBBox[0][2]);
-	float maxsize=std::max(std::max(xsize,ysize),zsize);
-	float scale = 1.f/maxsize;
+	int xsize = std::max(1, metadata.indexBBox[1][0] - metadata.indexBBox[0][0]);
+	int ysize = std::max(1, metadata.indexBBox[1][1] - metadata.indexBBox[0][1]);
+	int zsize = std::max(1, metadata.indexBBox[1][2] - metadata.indexBBox[0][2]);
+	float maxsize = std::max(std::max(xsize, ysize), zsize);
+	float scale = 1.0f / maxsize;
 	m_aabb = m_render_aabb = BoundingBox{
-		Vector3f{0.5f-xsize*scale*0.5f,0.5f-ysize*scale*0.5f,0.5f-zsize*scale*0.5f},
-		Vector3f{0.5f+xsize*scale*0.5f,0.5f+ysize*scale*0.5f,0.5f+zsize*scale*0.5f}
+		Vector3f{0.5f - xsize * scale * 0.5f, 0.5f - ysize * scale * 0.5f, 0.5f - zsize * scale * 0.5f},
+		Vector3f{0.5f + xsize * scale * 0.5f, 0.5f + ysize * scale * 0.5f, 0.5f + zsize * scale * 0.5f},
 	};
 	m_volume.world2index_scale = maxsize;
-	m_volume.world2index_offset= Vector3f{(metadata.indexBBox[0][0]+metadata.indexBBox[1][0])*0.5f-0.5f*maxsize,(metadata.indexBBox[0][1]+metadata.indexBBox[1][1])*0.5f-0.5f*maxsize,(metadata.indexBBox[0][2]+metadata.indexBBox[1][2])*0.5f-0.5f*maxsize};
+	m_volume.world2index_offset = Vector3f{
+		(metadata.indexBBox[0][0] + metadata.indexBBox[1][0]) * 0.5f - 0.5f * maxsize,
+		(metadata.indexBBox[0][1] + metadata.indexBBox[1][1]) * 0.5f - 0.5f * maxsize,
+		(metadata.indexBBox[0][2] + metadata.indexBBox[1][2]) * 0.5f - 0.5f * maxsize,
+	};
 
 	auto acc = grid->tree().getAccessor();
 	std::vector<uint8_t> bitgrid;
-	bitgrid.resize(128*128*128/8);
-	for (int i=metadata.indexBBox[0][0];i<metadata.indexBBox[1][0];++i)
-	for (int j=metadata.indexBBox[0][1];j<metadata.indexBBox[1][1];++j)
-	for (int k=metadata.indexBBox[0][2];k<metadata.indexBBox[1][2];++k) {
-		float d = acc.getValue({i,j,k});
-		if (d>mx) mx=d;
-		if (d<mn) mn=d;
-		if (d>0.001f) {
-			float fx=((i+0.5f)-m_volume.world2index_offset.x())/m_volume.world2index_scale;
-			float fy=((j+0.5f)-m_volume.world2index_offset.y())/m_volume.world2index_scale;
-			float fz=((k+0.5f)-m_volume.world2index_offset.z())/m_volume.world2index_scale;
-			uint32_t bitidx = tcnn::morton3D(int(fx*128.f+0.5f),int(fy*128.f+0.5f),int(fz*128.f+0.5f));
-			if (bitidx<128*128*128)
-				bitgrid[bitidx/8]|=1<<(bitidx&7);
+	bitgrid.resize(128 * 128 * 128 / 8);
+	for (int i = metadata.indexBBox[0][0]; i < metadata.indexBBox[1][0]; ++i)
+	for (int j = metadata.indexBBox[0][1]; j < metadata.indexBBox[1][1]; ++j)
+	for (int k = metadata.indexBBox[0][2]; k < metadata.indexBBox[1][2]; ++k) {
+		float d = acc.getValue({i, j, k});
+		if (d > mx) mx = d;
+		if (d < mn) mn = d;
+		if (d > 0.001f) {
+			float fx = ((i + 0.5f) - m_volume.world2index_offset.x()) / m_volume.world2index_scale;
+			float fy = ((j + 0.5f) - m_volume.world2index_offset.y()) / m_volume.world2index_scale;
+			float fz = ((k + 0.5f) - m_volume.world2index_offset.z()) / m_volume.world2index_scale;
+			uint32_t bitidx = tcnn::morton3D(int(fx * 128.0f + 0.5f), int(fy * 128.0f + 0.5f), int(fz * 128.0f + 0.5f));
+			if (bitidx < 128 * 128 * 128)
+				bitgrid[bitidx / 8] |= 1 << (bitidx & 7);
 		}
 	}
 	m_volume.bitgrid.enlarge(bitgrid.size());