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.
npm run import -- "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()
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:
Import Logic
The script checks the file extension of the input file and imports it accordingly:
.map files are imported using the id_map operator..bsp files are imported using the id3_bsp operator with the BRUSHES preset and Keep vertex map packing..obj files are imported using the obj_import operator.Export Logic
The script exports the model as an MD3 file using the export_scene.id3_md3 operator. The export settings are:
preset: MATERIALSonly_selected: Falselimits: STUPIDstart_frame and end_frame: 0individual: False (uses model space coordinates instead of world space)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
sys.argv list to access the command-line arguments, specifically the file path.bpy module to interact with the Blender API.