mitsuba-blender
mitsuba-blender copied to clipboard
Export from command line
Hi,
it would be really nice to be able to do exports directly from the command line. Like that, the add-on will become more versatile and can even be executed without a GUI (when using blender -b
, see here)). That is especially helpful for GUI-less Blender operation, e.g., when working on a specific machine via SSH.
Personally, I would say that a Python script, which handles this and possibly allows options via a CLI, would be the easiest and best option. (I.e., usage would somehow look like this: blender somescene.blend -b --python new_exporter_script.py
and could be wrapped further with a shell script.)
Thank you!
Hi,
This is already supported, as all blender operators are registered in the Blender Python API. In general, you can find the API handle of each operator/parameter in the Blender UI by enabling "Python tooltips" in the Blender preferences (Interface > Display). Hovering over any operator/parameter will then show you the associated handle in the API.
In the case of this addon, the operator to call to export from the blender API should be bpy.ops.export_scene.mitsuba2
The full signature is as follows:
bpy.ops.export_scene.mitsuba2(filepath="", check_existing=True, filter_glob="*.xml", use_selection=False, split_files=False, export_ids=False, ignore_background=True, axis_forward='-Z', axis_up='Y')
You can get those signatures in the Python interactive console inside of blender, by just entering the name of the operator.
Please let me know if this doesn't work for you.
Thanks for the quick reply!
I already tried a little bit to go in that direction, but then ran into issues (I think I got the filepath argument wrong)...
With your suggested signature, I was able to export scenes. But, on Windows, is very crucial to state your path with double backslashes (bpy.ops.export_scene.mitsuba2(filepath="D:\\myfolder\\mysubfolder\\myfile.xml", check_existing=True, [...])
) instead of a single forward slash ("D:/myfolder/mysubfolder/myfile.xml"
). If you work with single forward slashes, the first few parts of the XML (i.e., the Defaults
, Camera and Rendering Parameters
, Materials
, and Emitters
sections) are created successfully, the it fails in the creation of the Shapes
-block. It took me quite a while to figure out that the double backslashes fix this, because the error is so strange. I know why I usually use the pathlib
module on Windows 😄
In case anyone runs into a similar problem, here is my traceback:
PS C:\> blender "D:/scenes/myscene/myscene.blend" -b --python-console
Blender 2.82 (sub 7) (hash 375c7dc4caf4 built 2020-03-12 15:41:08)
Read prefs: C:\Users\myuser\AppData\Roaming\Blender Foundation\Blender\2.82\config\userpref.blend
found bundled python: C:\Program Files\Blender Foundation\Blender 2.82\2.82\python
Read blend: D:/scenes/myscene/myscene.blend
Python 3.7.4 (default, Nov 1 2019, 13:23:36) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
>>> import bpy
>>> bpy.ops.export_scene.mitsuba2(filepath="D:/temp/from_commandline/myscene.xml", check_existing=True, use_selection=False, split_files=False, export_ids=False, ignore_background=True, axis_forward='-Z', axis_up='Y')
2022-05-02 11:05:00 INFO main [file_api.py:127] log(): Ignoring Blender's default background...
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\blender.dll" ..
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\diffuse.dll" ..
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\uniform.dll" ..
2022-05-02 11:05:00 WARN main [BlenderMesh] Mesh Plane-Matte has no texture coordinates!
2022-05-02 11:05:00 INFO main [BlenderMesh] Plane-Matte: Removed 2 duplicates
2022-05-02 11:05:00 INFO main [Mesh] Writing mesh to "D:/temp/from_commandline\meshes\Plane-Matte.ply" ..
2022-05-02 11:05:00 INFO main [Mesh] "D:/temp/from_commandline\meshes\Plane-Matte.ply": wrote 2 faces, 4 vertices (120 B in 0ms)
2022-05-02 11:05:00 WARN main [file_api.py:127] log(): Light 'Point' has a non-zero soft shadow radius. It will be ignored.
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\path.dll" ..
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\ply.dll" ..
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\perspective.dll" ..
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\point.dll" ..
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\independent.dll" ..
2022-05-02 11:05:00 INFO main [PluginManager] Loading plugin "plugins\hdrfilm.dll" ..
Error: Traceback (most recent call last):
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\export.py", line 154, in execute
self.export_ctx.write()
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\file_api.py", line 104, in write
self.xml_writer.process(self.scene_data)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 637, in process
self.write_dict(self.scene_data[Files.MAIN])
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 574, in write_dict
self.write_dict(value)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 588, in write_dict
value = self.format_path(value, self.current_tag())
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 525, in format_path
copy2(filepath, target_path)
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\shutil.py", line 266, in copy2
copyfile(src, dst, follow_symlinks=follow_symlinks)
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\shutil.py", line 104, in copyfile
raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
shutil.SameFileError: 'D:\\temp\\from_commandline\\meshes\\Plane.ply' and 'D:/temp/from_commandline\\meshes\\Plane.ply' are the same file
location: C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\modules\bpy\ops.py:201
Traceback (most recent call last):
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\export.py", line 154, in execute
self.export_ctx.write()
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\file_api.py", line 104, in write
self.xml_writer.process(self.scene_data)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 637, in process
self.write_dict(self.scene_data[Files.MAIN])
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 574, in write_dict
self.write_dict(value)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 588, in write_dict
value = self.format_path(value, self.current_tag())
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 525, in format_path
copy2(filepath, target_path)
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\shutil.py", line 266, in copy2
copyfile(src, dst, follow_symlinks=follow_symlinks)
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\shutil.py", line 104, in copyfile
raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
shutil.SameFileError: 'D:\\temp\\from_commandline\\meshes\\Plane.ply' and 'D:/temp/from_commandline\\meshes\\Plane.ply' are the same file
location: C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\modules\bpy\ops.py:201
location: C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\modules\bpy\ops.py:201
Error: Traceback (most recent call last):
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\export.py", line 154, in execute
self.export_ctx.write()
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\file_api.py", line 104, in write
self.xml_writer.process(self.scene_data)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 637, in process
self.write_dict(self.scene_data[Files.MAIN])
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 574, in write_dict
self.write_dict(value)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 588, in write_dict
value = self.format_path(value, self.current_tag())
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 525, in format_path
copy2(filepath, target_path)
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\shutil.py", line 266, in copy2
copyfile(src, dst, follow_symlinks=folloTraceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\modules\bpy\ops.py", line 201, in __call__
ret = op_call(self.idname_py(), None, kw)
RuntimeError: Error: Traceback (most recent call last):
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\export.py", line 154, in execute
self.export_ctx.write()
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\addons\mitsuba2-blender\file_api.py", line 104, in write
self.xml_writer.process(self.scene_data)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 637, in process
self.write_dict(self.scene_data[Files.MAIN])
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 574, in write_dict
self.write_dict(value)
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 588, in write_dict
value = self.format_path(value, self.current_tag())
File "D:\mitsuba2\dist\python\mitsuba\python\xml.py", line 525, in format_path
copy2(filepath, target_path)
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\shutil.py", line 266, in copy2
copyfile(src, dst, follow_symlinks=follow_symlinks)
File "C:\Program Files\Blender Foundation\Blender 2.82\2.82\python\lib\shutil.py", line 104, in copyfile
raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
shutil.SameFileError: 'D:\\temp\\from_commandline\\meshes\\Plane.ply' and 'D:/temp/from_commandline\\meshes\\Plane.ply' are the same file
location: C:\Program Files\Blender Foundation\Blender 2.82\2.82\scripts\modules\bpy\ops.py:201
... truncated>>>
That brings me to two smaller issues:
- The path needs to be set without the GUI. In the readme, it tells that
Point Path to Mitsuba 2's build directory. If the environment variable MITSUBA_DIR was set (cf. Mitsuba 2 install instructions), this field will automatically be filled with the path it contains.
I wasn't able to find the certain section. Just creating a new environment variable didn't seem to solve this.
- Maybe, there should be a small section in the readme on how the add-on can be executed from the command line. If you don't want to dig into this right now, I could also write a few sentences about this and create a PR for the updated readme.
Update to point 1:
I dug into it and found the problem. The created environment variable (just named mitsuba_dir
with mitsuba's build path) is read by the export.py
-script. However, there are two processing issues under Windows:
- The first issue is caused by this line:
for token in tokens.split(':'):
(see here) On Linux, where different entries of an environment variable are separated by colons (:
), everything works fine. But on Windows, environment variables are separated by semicolons (;
). So a pathD:\mitsuba
is splitted into the two partsD:
and\mitsuba
. Here needs to be distinguished between systems to get the correct seperator. - The second issue is caused by the default way of installation of Mitsuba2 on Windows, where the build directory and the mitsuba2 root directory are the same (caused by
cmake -G "Visual Studio 16 2019" -A x64
, see here). Therefore, the linepath = os.path.join(token, 'build')
(see here) is unnecessary.path
should just betoken
.
Edit / Update:
I tested it on Linux, there it's working. My test-export script looks like this:
import bpy
bpy.ops.preferences.addon_enable(module="mitsuba2-blender") # enable the add-on
# bpy.ops.wm.open_mainfile(filepath="/home/scenes/myscene/myscene.blend") # read a scene if no scene has been specified when starting calling "blender -b --python myscript.py"
bpy.ops.export_scene.mitsuba2(filepath="/home/scenes/myscene/myscene.xml", check_existing=True, use_selection=False, split_files=False, export_ids=False, ignore_background=True, axis_forward='-Z', axis_up='Y')
The filter_glob
keyword has to be left out in order for this to work.
Therefore, two issues remain in this ticket:
- The exporting does not work from the command line on Windows (see above). I don't really understand why it's working when operating from the GUI... I was only testing on Windows, I have no need to operate from command line on Windows personally.
- A short section in the readme on command-line operation would be helpful.
Thanks for looking into this.
The code to use the environment variable ion Windows seems broken indeed, and support for it will likely be dropped in the next release. I recommend you instead set the path manually in your script by accessing directly the preferences of the addon:
C.preferences.addons['mitsuba2-blender'].preferences.mitsuba_path