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
: MATERIALS
only_selected
: False
limits
: STUPID
start_frame
and end_frame
: 0
individual
: 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.