8

I have about thousands of files I need to convert into from one format to another. Both formats are handled by existing add-ons..

I assume the script process would go something like this:

  • Select every source file in a directory and it's sub-directories
  • Store the path and filename of the source format.
  • Delete everything in scene and import the file
  • Export the file to the destination format with the same path and the same filename as the original file, with a different extension.
  • move on to the next item

The problem is that I have very little experience with Blender, and Python is not my area. The manual solution of importing and exporting works perfectly fine, as there is no need for anything to be modified.

ideasman42
  • 47,387
  • 10
  • 141
  • 223
Mats Bakken
  • 83
  • 1
  • 1
  • 4
  • what are using to import .meshdata ? – Chebhou Jul 25 '15 at 21:34
  • Was wondering if you could point me in the direction regarding batch exporting since you found good success in the endeavor. I am looking to importing a whole bunch of FBX file then save them individually into blender format. I have looked over the stuff posted here but did not really understand how it all fit together. Is there a add-on plugin that you wrote yourself or packages you could share so that I can edit them to the fix the files I needed to convert Thanks for your time. – hawkenfox Dec 26 '15 at 06:08
  • https://gist.github.com/HsiaTsing/31361ea018637aa1781c#file-ply2obj-py (This code uses the Blender Python API to batch convert 3D model file with ''ply'' format to ''obj'' format. It is only tested on Blender 2.64.) Also works on Blender 3.1.0. Easy to change I/O formates. – Martin Řezníček Dec 02 '22 at 21:48

2 Answers2

6

Set the path variable and change the import line to whatever importer you are using :

import bpy
import os

path = 'C:/path/to/files/'  # set this path

for root, dirs, files in os.walk(path):
    for f in files:
        if f.endswith('.meshdata') :
            mesh_file = os.path.join(path, f)
            obj_file = os.path.splitext(mesh_file)[0] + ".obj"

            bpy.ops.object.select_all(action='SELECT')
            bpy.ops.object.delete()

            bpy.ops.import_scene.obj(filepath=mesh_file) # change this line

            bpy.ops.object.select_all(action='SELECT')

            bpy.ops.export_scene.obj(filepath=obj_file)
ideasman42
  • 47,387
  • 10
  • 141
  • 223
Chebhou
  • 19,533
  • 51
  • 98
  • Although I have one issue. I can't seem to find the correct importer function. Here's the init.py: http://pastebin.com/G980EA2h

    and here's the meshdata_import.py: http://pastebin.com/bKkWiVMD

    Here's a meshdata file: http://dump.no/files/78e43d0cb895/MeshP_NAM_Bridge_01_part01_Mesh_lod0_data.meshdata

    the error occurs on this line: bpy.ops.object.mode_set(mode='OBJECT')

    With the error: RuntimeError: Operator bpy.ops.object.mode_set.poll() failed, context is incorrect.

    Disabling everything bellow the import line causes no errors, but also no imported files. Could you have a look?

    – Mats Bakken Jul 26 '15 at 14:31
  • Okay, it now successfully imports all the objects, but it's still getting the "RuntimeError: Operator bpy.ops.object.mode_set.poll() failed, context is incorrect" error. caused by "bpy.ops.object.mode_set(mode='OBJECT')" – Mats Bakken Jul 26 '15 at 15:08
  • @MatsBakken ( sorry I was away ) can you just comment this line and try again (it's not that crucial ) – Chebhou Jul 26 '15 at 15:41
  • Wow, I didn't actually think of that. It works now! Thank you! Although it only does the specified directory and not it's sub directories. I guess I should read up on python. – Mats Bakken Jul 26 '15 at 15:57
  • @Mats see if this helps – Chebhou Jul 26 '15 at 16:22
  • That looks exactly like the code I just wrote. Thank you for all your help! It's greatly appreciated! The script works perfectly now! – Mats Bakken Jul 26 '15 at 16:30
  • 1
    this works, but when you import a lot of meshes, blender will crash after a while because it runs out of memory. This mainly happens because textures, materials and the like are not dereferenced when you delete the object. To fix this issue I used the answer by Amir found here: https://blender.stackexchange.com/questions/48836/purge-unused-data-e-g-particle-system-or-groups-by-script Basically you need to call bpy.data.materials.remove(block), bpy.data.textures.remove(block) and so on, in every iteration of the for-loop

    EDIT: old thread, but answer is still valid. I'm on Blender 3.6.2

    – Dimitri Troncquo Oct 19 '23 at 06:42
3

This script is an example of how you can loop over all files and convert from one format to another.

This example converts all .obj files to .x3d, but changing the formats is trivial.

CONVERT_DIR = "/my/test/directory"

import os

def file_iter(path, ext):
    for dirpath, dirnames, filenames in os.walk(path):
        for filename in filenames:
            ext = os.path.splitext(filename)[1]
            if ext.lower().endswith(ext):
                yield os.path.join(dirpath, filename)

import bpy


def reset_blend():
    bpy.ops.wm.read_factory_settings(use_empty=True)

def convert_recursive(base_path):
    for filepath_src in file_iter(base_path, ".obj"):
        filepath_dst = os.path.splitext(filepath_src)[0] + ".x3d"

        print("Converting %r -> %r" % (filepath_src, filepath_dst))

        reset_blend()

        bpy.ops.import_scene.obj(filepath=filepath_src)
        bpy.ops.export_scene.x3d(filepath=filepath_dst)


if __name__ == "__main__":
    convert_recursive(CONVERT_DIR)
ideasman42
  • 47,387
  • 10
  • 141
  • 223
  • I'm getting this error when I use this script: TypeError: Converting py args to operator properties: : keyword "use_empty" unrecognized – Joel Harris Jul 30 '17 at 05:07