22
$\begingroup$

Is it possible to batch import Wavefront .obj to blender? I'm working on 2.69. If I select multiple .obj files, only one gets imported. Also if I hit A on file selection window to select all files (.obj and .mtl) I get an error, nothing gets imported. I have to import several hundreds of .obj into the blender file, is this possible?

$\endgroup$
19
$\begingroup$

Unfortunately, this is not possible by default with Blender 2.5x+ it seems. In 2.49, you could hold Shift then press the Import Obj button and it would prompt you to select a directory with the sequence.

In 2.69, you can do the same with a script — it could be converted into a more usable utility but it works.

import os
import bpy

# put the location to the folder where the objs are located here in this fashion
# this line will only work on windows ie C:\objects
path_to_obj_dir = os.path.join('C:\\', 'objects')

# get list of all files in directory
file_list = sorted(os.listdir(path_to_obj_dir))

# get a list of files ending in 'obj'
obj_list = [item for item in file_list if item.endswith('.obj')]

# loop through the strings in obj_list and add the files to the scene
for item in obj_list:
    path_to_file = os.path.join(path_to_obj_dir, item)
    bpy.ops.import_scene.obj(filepath = path_to_file)

For unix machines the direct path should look like:

# location of obj folder
path_to_obj_dir = '/home/user/Desktop/objects/'
$\endgroup$
  • 1
    $\begingroup$ To use the script, simply paste it into Blender's text editor, edit the path on the 5th line and press Alt + P or Run. $\endgroup$ – iKlsR Nov 23 '13 at 16:09
  • $\begingroup$ Thank you so much, works like a charm, but I had to do some research and trial error with my very poor knowledge of python. I had to change the extension to OBJ because by using print(obj_list) I noticed that it wasn't seeing the objs that had an uppercase extension, checked it with print(file_list) and then changed to OBJ and it worked! $\endgroup$ – finsopraiets Nov 24 '13 at 19:22
  • $\begingroup$ @akzash rejected your suggested edit re removing objects from windwos path. Your error would be in that you don't have an objects folder in c drive. $\endgroup$ – batFINGER Dec 14 '17 at 12:22
  • $\begingroup$ @iKlsR I am importing many .obj files sequentially. Very quickly, import time increases significantly to the point that it takes minutes for each object to get imported. Could you please take a look at my question here and see if you can offer a solution? Appreciate it. $\endgroup$ – Amir Mar 4 '18 at 20:38
17
$\begingroup$

The following Add-on allows to import multiple Wavefront OBJ files at once.

By using the file browser the import process is platform independent. It doesn't matter if you are on a linux, mac or windows machine, because blender handles the file paths internally. In addition, all known standard options like Forward Axis, Up Axis or Clamp Size are available:

enter image description here Click to enlarge

enter image description here

io_import_multiple_objs.py

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>

bl_info = {
    "name": "Import multiple OBJ files",
    "author": "poor",
    "version": (0, 1, 0),
    "blender": (2, 65, 0),
    "location": "File > Import-Export",
    "description": "Import multiple OBJ files, UV's, materials",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "Import-Export"}


import bpy
import os

from bpy_extras.io_utils import ImportHelper

from bpy.props import (BoolProperty,
                       FloatProperty,
                       StringProperty,
                       EnumProperty,
                       CollectionProperty
                       )


class ImportMultipleObjs(bpy.types.Operator, ImportHelper):
    """This appears in the tooltip of the operator and in the generated docs"""
    bl_idname = "import_scene.multiple_objs"
    bl_label = "Import multiple OBJ's"
    bl_options = {'PRESET', 'UNDO'}

    # ImportHelper mixin class uses this
    filename_ext = ".obj"

    filter_glob = StringProperty(
            default="*.obj",
            options={'HIDDEN'},
            )

    # Selected files
    files = CollectionProperty(type=bpy.types.PropertyGroup)

    # List of operator properties, the attributes will be assigned
    # to the class instance from the operator settings before calling.
    ngons_setting = BoolProperty(
            name="NGons",
            description="Import faces with more than 4 verts as ngons",
            default=True,
            )
    edges_setting = BoolProperty(
            name="Lines",
            description="Import lines and faces with 2 verts as edge",
            default=True,
            )
    smooth_groups_setting = BoolProperty(
            name="Smooth Groups",
            description="Surround smooth groups by sharp edges",
            default=True,
            )

    split_objects_setting = BoolProperty(
            name="Object",
            description="Import OBJ Objects into Blender Objects",
            default=True,
            )
    split_groups_setting = BoolProperty(
            name="Group",
            description="Import OBJ Groups into Blender Objects",
            default=True,
            )

    groups_as_vgroups_setting = BoolProperty(
            name="Poly Groups",
            description="Import OBJ groups as vertex groups",
            default=False,
            )

    image_search_setting = BoolProperty(
            name="Image Search",
            description="Search subdirs for any associated images "
                        "(Warning, may be slow)",
            default=True,
            )

    split_mode_setting = EnumProperty(
            name="Split",
            items=(('ON', "Split", "Split geometry, omits unused verts"),
                   ('OFF', "Keep Vert Order", "Keep vertex order from file"),
                   ),
            )

    clamp_size_setting = FloatProperty(
            name="Clamp Size",
            description="Clamp bounds under this value (zero to disable)",
            min=0.0, max=1000.0,
            soft_min=0.0, soft_max=1000.0,
            default=0.0,
            )
    axis_forward_setting = EnumProperty(
            name="Forward",
            items=(('X', "X Forward", ""),
                   ('Y', "Y Forward", ""),
                   ('Z', "Z Forward", ""),
                   ('-X', "-X Forward", ""),
                   ('-Y', "-Y Forward", ""),
                   ('-Z', "-Z Forward", ""),
                   ),
            default='-Z',
            )

    axis_up_setting = EnumProperty(
            name="Up",
            items=(('X', "X Up", ""),
                   ('Y', "Y Up", ""),
                   ('Z', "Z Up", ""),
                   ('-X', "-X Up", ""),
                   ('-Y', "-Y Up", ""),
                   ('-Z', "-Z Up", ""),
                   ),
            default='Y',
            )

    def draw(self, context):
        layout = self.layout

        row = layout.row(align=True)
        row.prop(self, "ngons_setting")
        row.prop(self, "edges_setting")

        layout.prop(self, "smooth_groups_setting")

        box = layout.box()
        row = box.row()
        row.prop(self, "split_mode_setting", expand=True)

        row = box.row()
        if self.split_mode_setting == 'ON':
            row.label(text="Split by:")
            row.prop(self, "split_objects_setting")
            row.prop(self, "split_groups_setting")
        else:
            row.prop(self, "groups_as_vgroups_setting")

        row = layout.split(percentage=0.67)
        row.prop(self, "clamp_size_setting")
        layout.prop(self, "axis_forward_setting")
        layout.prop(self, "axis_up_setting")

        layout.prop(self, "image_search_setting")

    def execute(self, context):

        # get the folder
        folder = (os.path.dirname(self.filepath))

        # iterate through the selected files
        for i in self.files:

            # generate full path to file
            path_to_file = (os.path.join(folder, i.name))

            # call obj operator and assign ui values                  
            bpy.ops.import_scene.obj(filepath = path_to_file,
                                axis_forward = self.axis_forward_setting,
                                axis_up = self.axis_up_setting, 
                                use_edges = self.edges_setting,
                                use_smooth_groups = self.smooth_groups_setting, 
                                use_split_objects = self.split_objects_setting,
                                use_split_groups = self.split_groups_setting,
                                use_groups_as_vgroups = self.groups_as_vgroups_setting,
                                use_image_search = self.image_search_setting,
                                split_mode = self.split_mode_setting,
                                global_clamp_size = self.clamp_size_setting)

        return {'FINISHED'}


# Only needed if you want to add into a dynamic menu
def menu_func_import(self, context):
    self.layout.operator(ImportMultipleObjs.bl_idname, text="Wavefont Batch (.obj)")


def register():
    bpy.utils.register_class(ImportMultipleObjs)
    bpy.types.INFO_MT_file_import.append(menu_func_import)


def unregister():
    bpy.utils.unregister_class(ImportMultipleObjs)
    bpy.types.INFO_MT_file_import.remove(menu_func_import)


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.import_scene.multiple_objs('INVOKE_DEFAULT')

install

enter image description here Install and activate the Add-on via User Preferences (Import-Export Category)

Notes: It's simply a wrapper of bpy.ops.inport_scene.obj operator until exporting multiple files is supported officially. @JuhaW added a Scale setting to it, you can download the latest version here.


There is also an Add-on in order to export multiple obj files, see this answer: https://blender.stackexchange.com/a/31852/3710

$\endgroup$
  • 1
    $\begingroup$ Just wanted to add, THANKS. This helped my workflow immeasurably. I'm consolidating torus knots (KnotPlot) of MULTIPLE obj components and was looking for a way to streamline this import process. Your process (addon) reduced it to seconds. THANKS. $\endgroup$ – user16237 Aug 8 '15 at 7:27
  • $\begingroup$ Many thanks poor, works with Blender 2.76.11. $\endgroup$ – JuhaW Mar 2 '16 at 10:13
  • $\begingroup$ @JuhaW For collaborative work I thought it's a good idea to create a gist, instead of updating the answer continuously. I hope you like it. Thanks again. $\endgroup$ – p2or Mar 15 '16 at 11:05
  • $\begingroup$ How did you manage to offset the loaded OBJs? I can't see it in the example code. I could need it for importing an OBJ to a custom position and parent it. $\endgroup$ – Ray Koopa Jul 14 '16 at 18:09
  • $\begingroup$ @RayKoopa There is none, it's just an example for demo purposes. For parenting, read: blender.stackexchange.com/a/28762/3710 But why not simply asking a new question on this? $\endgroup$ – p2or Jul 14 '16 at 18:47

protected by iKlsR Mar 4 '18 at 22:28

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.