Distribution of MDL materials in a self-contained file format for scenes

Hello!
I am working with an application that uses its own file format to represent a self-contained scene, including all assets and materials, and I am considering adding support for MDL.
However, as I am experimenting with the MDL SDK, it seems like it is very much oriented around standalone MDL/MDLE files accessed from the filesystem in user/system MDL folders. This does not really work well with my self-contained file format.
Is there any mechanism that would allow me to store/load MDL/MDLE files to memory, so that I can write it to/read it from my custom file format?

I can perhaps think of a work-around of exporting an MDLE to disk, then reading the exported file into memory, so that it can be written to my file format, and doing the reverse for importing. However, this seems less than ideal.

Best regards,
Limeth

Hi Limeth!

First some note about search paths:
With the MDL SDK, you can specify your own search paths (via mi::neuraylib::IMdl_configuration::add_mdl_path()).
The specification recommends to include the user/system MDL folders for interoperability with other applications supporting MDL (via mi::neuraylib::IMdl_configuration::add_mdl_system_paths() and mi::neuraylib::IMdl_configuration::add_mdl_user_paths()). Applications will usually add like one search path for application specific materials (like “the” invalid material, some default material and some helper materials to visualize normals or UV space) and one for the current scene.
Adding many search paths have their costs. And file paths may only resolve for one search path, shadowing depending on the order of search paths is not allowed. See MDL Spec Section 2.2 for details about how file path resolving works.

There are basically two ways of loading non-file based materials and resources:

  1. Loading resources from memory first into the database using mi::neuraylib::IMdl_impexp_api::create_reader() with functions like mi::neuraylib::IImage::reset_reader() and then using mi::neuraylib::IMdl_impexp_api::load_module_from_string() to first load imported modules (you need to keep track of in your own file-format…) and then the MDL module you want to load. See Loader_gltf::load() in mdl_examples\mdl_sdk\dxr\mdl_d3d12\gltf.cpp in the DXR example for one implementation.

  2. Or the more powerful way of using an mi::neuraylib::IMdl_entity_resolver set via mi::neuraylib::IMdl_configuration::set_entity_resolver(). With this, you get full control over how file paths are resolved and you can implement a virtual file system. There is currently no example available, but we could provide additional information, if you were intested in this solution.

Writing MDLE files is currently only supported on file level.
MDL modules can be exported in memory via mi::neuraylib::IMdl_impexp_api::export_module_to_string().

Best regards
Moritz

Hello Moritz,
I decided to try and go with the second approach. I thought I would create a new entity resolver that would wrap around the original entity resolver as a fallback, that way I could attempt to load resources from memory, and if no such resource is available in memory, load them from the disk.
However, it seems that calling IMdl_configuration::get_entity_resolver results in my program crashing with the following:

Exception thrown at 0x00007FFDEB0D4DCC (libmdl_sdk.dll) in main.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

Even though my intent was to access the original resolver, the issue occurs even if I invoke the method right after calling ::set_entity_resolver with an instance of my custom entity resolver.
I am using mdl-sdk-373000.3036.

I also have a question regarding the API of the IMdl_resolved_resource and IMdl_resolved_resource_element; it looks more involved to implement than IMdl_resolved_module. Specifically, it seems that I would be required to reimplement the parsing of UV-tileset and Texture sequence markers. In the interest of making this conformant to the spec, is there anything in the SDK that would help me with this?

Thank you,

Best,
Limeth

Hi Limeth,

yes, the fallback approach sounds reasonable.

Looks like the documentation is missing some important information here: You may only call mi::neuraylib::IMdl_configuration::get_entity_resolver() after mi::neuraylib::INeuray::start() has been called to initialize the SDK because it uses the MDL Core compiler.

Yes, implementing IMdl_resolved_resource* is involved. Sadly, we currently don’t provide any helper functions for that.
You can find some parts of the implementation at MDL-SDK/src/mdl/compiler/compilercore/compilercore_file_resolution.cpp at a71786e4df01915c142a83ef4a1e208d9d6029e7 · NVIDIA/MDL-SDK · GitHub and MDL-SDK/src/mdl/compiler/compilercore/compilercore_file_resolution.cpp at a71786e4df01915c142a83ef4a1e208d9d6029e7 · NVIDIA/MDL-SDK · GitHub

Best regards
Moritz

Thanks, I’ll try to apply this knowledge!