From 9f87f03843e07c23b66a92c7b4e3644980225d60 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas94@gmx.net>
Date: Tue, 31 Jan 2023 19:45:16 +0100
Subject: [PATCH] Robustify root dir detection when running through Python
 bindings

---
 include/neural-graphics-primitives/testbed.h |  4 ++++
 scripts/run.py                               |  1 +
 src/nerf_loader.cu                           |  1 +
 src/python_api.cu                            |  4 ++++
 src/testbed.cu                               | 22 +++++++++++++-------
 src/testbed_nerf.cu                          |  5 +----
 6 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/include/neural-graphics-primitives/testbed.h b/include/neural-graphics-primitives/testbed.h
index 9459285..e88dd45 100644
--- a/include/neural-graphics-primitives/testbed.h
+++ b/include/neural-graphics-primitives/testbed.h
@@ -496,6 +496,8 @@ public:
 	void compute_and_save_marching_cubes_mesh(const char* filename, Eigen::Vector3i res3d = Eigen::Vector3i::Constant(128), BoundingBox aabb = {}, float thresh = 2.5f, bool unwrap_it = false);
 	Eigen::Vector3i compute_and_save_png_slices(const char* filename, int res, BoundingBox aabb = {}, float thresh = 2.5f, float density_range = 4.f, bool flip_y_and_z_axes = false);
 
+	fs::path root_dir();
+
 	////////////////////////////////////////////////////////////////
 	// marching cubes related state
 	struct MeshState {
@@ -935,6 +937,8 @@ public:
 		char video_path[MAX_PATH_LEN] = "video.mp4";
 	} m_imgui;
 
+	fs::path m_root_dir = "";
+
 	bool m_visualize_unit_cube = false;
 	bool m_edit_render_aabb = false;
 
diff --git a/scripts/run.py b/scripts/run.py
index d7b2054..fce5b2a 100644
--- a/scripts/run.py
+++ b/scripts/run.py
@@ -86,6 +86,7 @@ if __name__ == "__main__":
 		print("Warning: the '--mode' argument is no longer in use. It has no effect. The mode is automatically chosen based on the scene.")
 
 	testbed = ngp.Testbed()
+	testbed.root_dir = ROOT_DIR
 
 	for file in args.files:
 		scene_info = get_scene(file)
diff --git a/src/nerf_loader.cu b/src/nerf_loader.cu
index 69af304..9b91a42 100644
--- a/src/nerf_loader.cu
+++ b/src/nerf_loader.cu
@@ -744,6 +744,7 @@ void NerfDataset::set_training_image(int frame_idx, const Eigen::Vector2i& image
 	if (frame_idx < 0 || frame_idx >= n_images) {
 		throw std::runtime_error{"NerfDataset::set_training_image: invalid frame index"};
 	}
+
 	size_t n_pixels = image_resolution.prod();
 	size_t img_size = n_pixels * 4; // 4 channels
 	size_t image_type_stride = image_type_size(image_type);
diff --git a/src/python_api.cu b/src/python_api.cu
index 8a8d436..fc95fe7 100644
--- a/src/python_api.cu
+++ b/src/python_api.cu
@@ -529,6 +529,10 @@ PYBIND11_MODULE(pyngp, m) {
 		.def("crop_box", &Testbed::crop_box, py::arg("nerf_space") = true)
 		.def("set_crop_box", &Testbed::set_crop_box, py::arg("matrix"), py::arg("nerf_space") = true)
 		.def("crop_box_corners", &Testbed::crop_box_corners, py::arg("nerf_space") = true)
+		.def_property("root_dir",
+			[](py::object& obj) { return obj.cast<Testbed&>().root_dir().str(); },
+			[](const py::object& obj, const std::string& value) { obj.cast<Testbed&>().m_root_dir = value; }
+		)
 		;
 
 	py::class_<Lens> lens(m, "Lens");
diff --git a/src/testbed.cu b/src/testbed.cu
index 6f088be..c212f96 100644
--- a/src/testbed.cu
+++ b/src/testbed.cu
@@ -223,7 +223,7 @@ fs::path Testbed::find_network_config(const fs::path& network_config_path) {
 		return network_config_path;
 	}
 
-	fs::path candidate = get_root_dir()/"configs"/to_string(m_testbed_mode)/network_config_path;
+	fs::path candidate = root_dir()/"configs"/to_string(m_testbed_mode)/network_config_path;
 	if (candidate.exists()) {
 		return candidate;
 	}
@@ -526,6 +526,14 @@ Eigen::Vector3i Testbed::compute_and_save_png_slices(const char* filename, int r
 	return res3d;
 }
 
+fs::path Testbed::root_dir() {
+	if (m_root_dir.empty()) {
+		m_root_dir = get_root_dir();
+	}
+
+	return m_root_dir;
+}
+
 inline float linear_to_db(float x) {
 	return -10.f*logf(x)/logf(10.f);
 }
@@ -2409,19 +2417,19 @@ void Testbed::prepare_next_camera_path_frame() {
 #ifdef _WIN32
 			// Under Windows, try automatically downloading FFmpeg binaries if they don't exist
 			if (system(fmt::format("where {} >nul 2>nul", ffmpeg.str()).c_str()) != 0) {
-				fs::path root_dir = get_root_dir();
-				if ((root_dir/"external"/"ffmpeg").exists()) {
-					for (const auto& path : fs::directory{root_dir/"external"/"ffmpeg"}) {
+				fs::path dir = root_dir();
+				if ((dir/"external"/"ffmpeg").exists()) {
+					for (const auto& path : fs::directory{dir/"external"/"ffmpeg"}) {
 						ffmpeg = path/"bin"/"ffmpeg.exe";
 					}
 				}
 
 				if (!ffmpeg.exists()) {
 					tlog::info() << "FFmpeg not found. Downloading FFmpeg...";
-					do_system((root_dir/"scripts"/"download_ffmpeg.bat").str());
+					do_system((dir/"scripts"/"download_ffmpeg.bat").str());
 				}
 
-				for (const auto& path : fs::directory{root_dir/"external"/"ffmpeg"}) {
+				for (const auto& path : fs::directory{dir/"external"/"ffmpeg"}) {
 					ffmpeg = path/"bin"/"ffmpeg.exe";
 				}
 
@@ -2994,7 +3002,7 @@ void Testbed::init_window(int resw, int resh, bool hidden, bool second_window) {
 	// Instead, we would like to place imgui.ini in the directory that instant-ngp project
 	// resides in.
 	static std::string ini_filename;
-	ini_filename = (get_root_dir()/"imgui.ini").str();
+	ini_filename = (root_dir()/"imgui.ini").str();
 	io.IniFilename = ini_filename.c_str();
 
 	// New ImGui event handling seems to make camera controls laggy if input trickling is true.
diff --git a/src/testbed_nerf.cu b/src/testbed_nerf.cu
index ba563a6..bdc35f1 100644
--- a/src/testbed_nerf.cu
+++ b/src/testbed_nerf.cu
@@ -2683,10 +2683,7 @@ void Testbed::load_nerf(const fs::path& data_path) {
 
 		// Check if the NeRF network has been previously configured.
 		// If it has not, don't reset it.
-		bool previously_configured = !m_network_config["rgb_network"].is_null()
-		                          && !m_network_config["dir_encoding"].is_null();
-
-		if (m_nerf.training.dataset.aabb_scale != prev_aabb_scale && previously_configured) {
+		if (m_nerf.training.dataset.aabb_scale != prev_aabb_scale && m_nerf_network) {
 			// The AABB scale affects network size indirectly. If it changed after loading,
 			// we need to reset the previously configured network to keep a consistent internal state.
 			reset_network();
-- 
GitLab