5
$\begingroup$

I have around 10,000 wavefront (obj) files with a volume.

I would like to load a predefined scene with a camera position, light, etc. Then load an obj file, render a snapshot from that camera (no animation), save that as a png file and then pass to the next one and repeat the operation.

I know bash and python, but I am not sure how to do this "load & render" from the command line or using python.

Cheers.

$\endgroup$
4
  • $\begingroup$ How do you know which files to import? Do you have the filenames of the OBJ files in a file somewhere? Or are they all in the same directory? $\endgroup$
    – dr. Sybren
    Jun 7, 2017 at 9:19
  • $\begingroup$ File, directory, etc... That is not really important. I can either do: for fileName in $dir/*.obj ; do BLA ; done or while read line ; do BLA ; done < list_of_names.txt $\endgroup$
    – Phai
    Jun 7, 2017 at 13:10
  • $\begingroup$ One tactic that might be useful is to load all the objects into a .blend file, but only make each object renderable for a single frame. That way when you render the 10000 frames of animation, each frame will have a different object in it. This might have scaling problems, so you might end up doing 10 .blend files with 1000 frames each, or 100 .blend files with 100 frames each. $\endgroup$
    – Mutant Bob
    Jun 7, 2017 at 14:36
  • $\begingroup$ Not feasible. Objects are complex (More than 40 MB each), so memory requirements for that would be crazy. $\endgroup$
    – Phai
    Jun 7, 2017 at 15:18

1 Answer 1

4
$\begingroup$

This script will take all OBJ files in a certain directory, and one by one load them, render them, and remove them from the scene again. This way you can render 10000 OBJ files without having to load them all into memory at the same time. The OBJ files do not need to be named in any special way (except ending in .obj).

import bpy
import pathlib

# Adjust this for where you have the OBJ files.
obj_root = pathlib.Path('c:/temp/obj')

# Before we start, make sure nothing is selected. The importer will select
# imported objects, which allows us to delete them after rendering.
bpy.ops.object.select_all(action='DESELECT')
render = bpy.context.scene.render

for obj_fname in obj_root.glob('*.obj'):
    bpy.ops.import_scene.obj(filepath=str(obj_fname))

    render.filepath = '//obj-%s' % obj_fname.stem
    bpy.ops.render.render(write_still=True)

    # Remember which meshes were just imported
    meshes_to_remove = []
    for ob in bpy.context.selected_objects:
        meshes_to_remove.append(ob.data)

    bpy.ops.object.delete()

    # Remove the meshes from memory too
    for mesh in meshes_to_remove:
        bpy.data.meshes.remove(mesh)

The rendered image files will have the OBJ filename in their name, so if you have cube.obj, the output file will be obj-cube.jpg (assuming you're rendering to JPEG files).

The camera and lighting is use as-is in the scene, so you can set it up beforehand and render everything with the same settings.

NOTE: since this is a synchronous script, Blender's UI will block while it's running. You may want to start Blender from a terminal (or choose Window > Toggle System Console on Windows) before you start it, to keep an eye on its progress.

$\endgroup$
1
  • 1
    $\begingroup$ A small suggestion: That's a lot of render time and one might find that the script needs to be restarted because of crashes. If you set render.filepath before attempting to import the next obj file you can follow that with something like if render.filepath.exists(): continue before that call and the script will skip every file that already has a render output $\endgroup$ Oct 22, 2021 at 20:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .