Skip to content

Commit

Permalink
Add support of resources type in load_dict
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Speierer authored and njroussel committed Jul 6, 2023
1 parent da3b836 commit 66ea528
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 5 deletions.
18 changes: 18 additions & 0 deletions docs/src/key_topics/scene_format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -658,3 +658,21 @@ dictionary. For this purpose, you can specify a nested dictionary with
}
}
}
As in the XML scene description, it is possible to add a path to the list of
search paths. In the following example, the texture file can be found in the
``/home/username/data/textures/`` folder. Note that this added path can be
relative or absolute.

.. code-block:: python
{
"type": "scene",
'foo': { 'type': 'resources', 'path': '/home/username/data/textures'},
"bsdf": {
"type": "diffuse",
"reflectance": {
"type": "bitmap",
"filename": "my_texture.exr", # relative to the folder defined above
}
}
43 changes: 38 additions & 5 deletions src/core/python/xml_v.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <mitsuba/core/filesystem.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/xml.h>
#include <mitsuba/core/plugin.h>
#include <mitsuba/core/properties.h>
Expand Down Expand Up @@ -109,13 +110,25 @@ MI_PY_EXPORT(xml) {
m.def(
"load_dict",
[](const py::dict dict, bool parallel) {
// Make a backup copy of the FileResolver, which will be restored after parsing
ref<FileResolver> fs_backup = Thread::thread()->file_resolver();
Thread::thread()->set_file_resolver(new FileResolver(*fs_backup));

DictParseContext ctx;
ctx.parallel = parallel;
parse_dictionary<Float, Spectrum>(ctx, "__root__", dict);
std::unordered_map<std::string, Task*> task_map;
instantiate_node<Float, Spectrum>(ctx, "__root__", task_map);
auto objects = mitsuba::xml::detail::expand_node(ctx.instances["__root__"].object);
return single_object_or_list(objects);
ctx.env = ThreadEnvironment();

try {
parse_dictionary<Float, Spectrum>(ctx, "__root__", dict);
std::unordered_map<std::string, Task*> task_map;
instantiate_node<Float, Spectrum>(ctx, "__root__", task_map);
auto objects = mitsuba::xml::detail::expand_node(ctx.instances["__root__"].object);
Thread::thread()->set_file_resolver(fs_backup.get());
return single_object_or_list(objects);
} catch(...) {
Thread::thread()->set_file_resolver(fs_backup.get());
throw;
}
},
"dict"_a, "parallel"_a=true,
R"doc(Load a Mitsuba scene or object from an Python dictionary
Expand Down Expand Up @@ -293,6 +306,26 @@ void parse_dictionary(DictParseContext &ctx,
continue;
}

if (type2 == "resources") {
ref<FileResolver> fs = Thread::thread()->file_resolver();
std::string path = dict2["path"].template cast<std::string>();
fs::path resource_path(path);
if (!resource_path.is_absolute()) {
// First try to resolve it starting in the Python file directory
py::module_ inspect = py::module_::import("inspect");
py::object filename = inspect.attr("getfile")(inspect.attr("currentframe")());
fs::path current_file(filename.template cast<std::string>());
resource_path = current_file.parent_path() / resource_path;
// Otherwise try to resolve it with the FileResolver
if (!fs::exists(resource_path))
resource_path = fs->resolve(path);
}
if (!fs::exists(resource_path))
Throw("path: folder %s not found", resource_path);
fs->prepend(resource_path);
continue;
}

// Nested dict with type == "ref" specify a reference to another
// object previously instantiated
if (type2 == "ref") {
Expand Down

0 comments on commit 66ea528

Please sign in to comment.