quake 3 model conv | | | Search

This Python script uses the Blender API to import 3D models from various formats (e.g.,.map,.bsp,.obj) and export them as MD3 files, with the option to scale the model down by 50% and export it with a "-half" suffix. The script performs these tasks using the Blender API's import and export operators, with some error handling for specific exceptions.

Run example

npm run import -- "convert a model using python and blender"

convert a model using python and blender


import bpy
# from import_bsp import MD3
import sys
from pathlib import Path

# bpy.context.window.cursor_warp(10, 10)
# current_file_name = bpy.path.basename(file_path)
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete()
# bpy.ops.render.view_show('INVOKE_DEFAULT')

# usage: 

print(f'Starting {sys.argv[4]}...')

extname = '.map'
if ".map" in sys.argv[4]:
  bpy.ops.import_scene.id_map(filepath=sys.argv[4])
elif ".bsp" in sys.argv[4]:
  extname = '.bsp'
  bpy.ops.import_scene.id3_bsp(
    filepath=sys.argv[4], 
    preset="BRUSHES", 
    vert_map_packing="Keep"
    )
elif ".obj" in sys.argv[4]:
  extname = '.obj'
  bpy.ops.wm.obj_import("filepath=sys.argv[4")


bpy.context.view_layer.update()

# https://github.com/SomaZ/Blender_BSP_Importer/blob/main/import_bsp/UI.py#L362
# bpy.ops.export_scene.id3_md3(
#     filepath = file,
#     preset = "MATERIALS",
#     only_selected = True,
#     limits = "LEGACY",
#     start_frame = 0,
#     end_frame = 0,
#     individual = False # use model space coordinates instead of world space
#     )

try:
  bpy.ops.export_scene.id3_md3(
    filepath = sys.argv[4].replace(extname, '.md3'),
    preset = "MATERIALS",
    only_selected = False,
    limits = "STUPID",
    start_frame = 0,
    end_frame = 0,
    individual = False # use model space coordinates instead of world space
  )
except RuntimeError as err:
  if not "Model exceeds MD3 bounds" in str(err):
    raise RuntimeError
except Exception as err:
  if not "BSP format not supported" in str(err):
    raise err

for ob in bpy.data.objects:
   ob.scale = (0.5,0.5,0.5)
   bpy.ops.object.transform_apply(scale=True)

bpy.context.view_layer.update()

try:
  bpy.ops.export_scene.id3_md3(
    filepath = sys.argv[4].replace(extname, '-half.md3'),
    preset = "MATERIALS",
    only_selected = False,
    limits = "STUPID",
    start_frame = 0,
    end_frame = 0,
    individual = False # use model space coordinates instead of world space
  )
except RuntimeError as err:
  if not "Model exceeds MD3 bounds" in str(err):
    raise err
except Exception as err:
  if not "BSP format not supported" in str(err):
    raise err

for ob in bpy.data.objects:
   ob.scale = (0.25,0.25,0.25)
   bpy.ops.object.transform_apply(scale=True)

bpy.context.view_layer.update()

# MD3.ExportMD3(
#   sys.argv[4].replace(extname, '-quarter.md3'),
#   bpy.data.objects,
#   range(0, 1),
#   False,
#   True,
#   100000,
#   1024)

try:
  bpy.ops.export_scene.id3_md3(
    filepath = sys.argv[4].replace(extname, '-quarter.md3'),
    preset = "MATERIALS",
    only_selected = False,
    limits = "STUPID",
    start_frame = 0,
    end_frame = 0,
    individual = False # use model space coordinates instead of world space
  )
except RuntimeError as err:
  if not "Model exceeds MD3 bounds" in str(err):
    raise err
except Exception as err:
  if not "BSP format not supported" in str(err):
    raise err


for ob in bpy.data.objects:
   ob.scale = (0.125,0.125,0.125)
   bpy.ops.object.transform_apply(scale=True)

bpy.context.view_layer.update()

try:
  bpy.ops.export_scene.id3_md3(
    filepath = sys.argv[4].replace(extname, '-eigth.md3'),
    preset = "MATERIALS",
    only_selected = False,
    limits = "STUPID",
    start_frame = 0,
    end_frame = 0,
    individual = False # use model space coordinates instead of world space
  )
except RuntimeError as err:
  if not "Model exceeds MD3 bounds" in str(err):
    raise err
except Exception as err:
  if not "BSP format not supported" in str(err):
    raise err


# bpy.ops.wm.revert_mainfile()

print(f'Done {sys.argv[4]}...')
# bpy.ops.wm.call_menu(name="FILE_quit")
# bpy.ops.file.reset_recent()
bpy.ops.wm.window_close()
bpy.ops.wm.quit_blender()
sys.exit()

What the code could have been:

import bpy
import sys
from pathlib import Path

def scale_model(scale_factor):
    for ob in bpy.data.objects:
        ob.scale = (scale_factor, scale_factor, scale_factor)
        bpy.ops.object.transform_apply(scale=True)
    bpy.context.view_layer.update()

def export_md3(filepath, scale_factor):
    try:
        bpy.ops.export_scene.id3_md3(
            filepath=filepath,
            preset="MATERIALS",
            only_selected=False,
            limits="STUPID",
            start_frame=0,
            end_frame=0,
            individual=False
        )
    except RuntimeError as err:
        if "Model exceeds MD3 bounds" not in str(err):
            raise err
    except Exception as err:
        if "BSP format not supported" not in str(err):
            raise err

def main():
    print(f'Starting {sys.argv[4]}...')

    file_path = sys.argv[4]
    extname = file_path.split('.')[-1]

    if extname in ["map", "bsp", "obj"]:
        if extname == "map":
            bpy.ops.import_scene.id_map(filepath=file_path)
        elif extname == "bsp":
            bpy.ops.import_scene.id3_bsp(filepath=file_path, preset="BRUSHES", vert_map_packing="Keep")
        else:
            bpy.ops.wm.obj_import(filepath=file_path)

        bpy.context.view_layer.update()

        export_md3(file_path.replace(extname, '.md3'), 1.0)

        scale_factors = [0.5, 0.25, 0.125, 0.0625]
        for scale_factor in scale_factors:
            scale_model(scale_factor)
            export_md3(file_path.replace(extname, f'-{scale_factor}.md3'), scale_factor)

        # TODO: Revert main file to restore original state
        # bpy.ops.wm.revert_mainfile()

        print(f'Done {sys.argv[4]}...')

        bpy.ops.wm.window_close()
        bpy.ops.wm.quit_blender()
        sys.exit()
    else:
        print(f"Unsupported file type: {extname}")

if __name__ == "__main__":
    main()

Overview

This is a Python script that utilizes the Blender API (bpy) to import 3D models in various formats and export them as MD3 files. The script takes a file path as an argument and performs the following tasks:

  1. Deletes all objects in the scene.
  2. Imports the model from the specified file path, depending on the file extension.
  3. Exports the model as an MD3 file at the original scale.
  4. Scales down the model by 50% and exports it as an MD3 file with a "-half" suffix.

Import Logic

The script checks the file extension of the input file and imports it accordingly:

Export Logic

The script exports the model as an MD3 file using the export_scene.id3_md3 operator. The export settings are:

Error Handling

The script catches RuntimeError exceptions and checks if the error message contains specific text. If not, it re-raises the exception. This is done to handle the "Model exceeds MD3 bounds" error and the "BSP format not supported" error.

Scaling and Export

The script scales down the model by 50% using the transform_apply operator and exports it as an MD3 file with a "-half" suffix.

Notes