Begin working on an mdl import/export plugin for blender.

This is only preliminary at this stage:
  o No export yet.
  o Only the first frame is converte4d.
  o Skins are not yet converted
This commit is contained in:
Bill Currie 2011-09-14 19:33:51 +09:00
parent 5029fde3e1
commit 9d025e0058
3 changed files with 273 additions and 0 deletions

1
.gitignore vendored
View file

@ -6,6 +6,7 @@
*.a
*.o
*~
__pycache__/
autom4te.cache/
.deps/
.libs/

94
tools/qfmdl/__init__.py Normal file
View file

@ -0,0 +1,94 @@
# vim:ts=4:et
# ##### 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 #####
# copied from io_scene_obj
# <pep8 compliant>
bl_info = {
"name": "Quake MDL format",
"author": "Bill Currie",
"blender": (2, 5, 7),
"api": 35622,
"location": "File > Import-Export",
"description": "Import-Export Quake MDL (version 6) files. (.mdl)",
"warning": "not even alpha",
"wiki_url": "",
"tracker_url": "",
# "support": 'OFFICIAL',
"category": "Import-Export"}
# To support reload properly, try to access a package var, if it's there,
# reload everything
if "bpy" in locals():
import imp
if "import_mdl" in locals():
imp.reload(import_mdl)
#if "export_mdl" in locals():
# imp.reload(export_mdl)
import bpy
from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty
from bpy_extras.io_utils import ExportHelper, ImportHelper, path_reference_mode, axis_conversion
class ImportMDL6(bpy.types.Operator, ImportHelper):
'''Load a Quake MDL (v6) File'''
bl_idname = "import_mesh.quake_mdl_v6"
bl_label = "Import MDL"
def execute(self, context):
from . import import_mdl
keywords = self.as_keywords ()
return import_mdl.import_mdl(self, context, **keywords)
class ExportMDL6(bpy.types.Operator, ExportHelper):
'''Save a Quake MDL (v6) File'''
bl_idname = "export_mesh.quake_mdl_v6"
bl_label = 'Export MDL'
def execute(self, context):
return export_mdl.export_mdl(self, context, **keywords)
def menu_func_import(self, context):
self.layout.operator(ImportMDL6.bl_idname, text="Quake MDL (.mdl)")
def menu_func_export(self, context):
self.layout.operator(ExportMDL6.bl_idname, text="Quake MDL (.mdl)")
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_import.append(menu_func_import)
bpy.types.INFO_MT_file_export.append(menu_func_export)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_import.remove(menu_func_import)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
if __name__ == "__main__":
register()

178
tools/qfmdl/import_mdl.py Normal file
View file

@ -0,0 +1,178 @@
# vim:ts=4:et
# ##### 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>
from struct import unpack
from pprint import pprint
import bpy
from bpy_extras.object_utils import object_data_add
from mathutils import Vector,Matrix
class MDL:
pass
class stvert:
pass
class tri:
pass
class frame:
pass
class vert:
pass
def load_mdl(filepath):
data = open(filepath, "rb").read()
m = unpack("<4s i 3f 3f f 3f i i i i i i i i f", data[:84])
data = data[84:]
mdl = MDL()
mdl.ident = m[0]
mdl.version = m[1]
mdl.scale = Vector(m[2:5])
mdl.scale_origin = Vector(m[5:8])
mdl.boundingradius = m[8]
mdl.eyeposition = Vector(m[9:12])
mdl.numskins = m[12]
mdl.skinwidth = m[13]
mdl.skinheight = m[14]
mdl.numverts = m[15]
mdl.numtris = m[16]
mdl.numframes = m[17]
mdl.synctype = m[18]
mdl.flags = m[19]
mdl.size = m[20]
# read in the skin data
size = mdl.skinwidth * mdl.skinheight
mdl.skins = []
for i in range(mdl.numskins):
skintype = unpack ("<i", data[:4])[0]
data = data[4:]
if skintype == 0:
# single skin
mdl.skins.append((0, data[:size]))
data = data[size:]
else:
# skin group
n = unpack ("<i", data[:4])[0]
data = data[4:]
k = (n, unpack("<" + repr(n) + "f", data[:n * 4]), [])
data = data[n * 4:]
for j in range(n):
k[2].append(data[:size])
data = data[size:]
mdl.skins.append(k)
#read in the st verts (uv map)
mdl.stverts = []
for i in range(mdl.numverts):
st = stvert ()
st.onseam, st.s, st.t = unpack ("<i i i", data[:12])
data = data[12:]
mdl.stverts.append(st)
#read in the tris
mdl.tris = []
for i in range(mdl.numtris):
t = unpack("<i 3i", data[:16])
data = data[16:]
mdl.tris.append(tri())
mdl.tris[-1].facesfront = t[0]
mdl.tris[-1].verts = t[1:]
#read in the frames
mdl.frames = []
for i in range(mdl.numframes):
f = frame()
f.type = unpack("<i", data[:4])[0]
data = data[4:]
if f.type == 0:
x = unpack("<3B B 3B B 16s", data[:24])
data = data[24:]
f.mins = x[0:3]
f.maxs = x[4:7]
name = x[8]
if b"\0" in name:
name = name[:name.index(b"\0")]
f.name = name
f.verts = []
for j in range(mdl.numverts):
x = unpack("<3B B", data[:4])
data = data[4:]
v = vert()
v.r = x[:3]
v.ni = x[3]
f.verts.append(v)
else:
g = f
x = unpack("<i 3B B 3B B", data[:12])
data = data[12:]
g.numframes = n = x[0]
g.mins = x[1:4]
g.maxs = x[5:8]
g.times = unpack("<" + repr(n) + "f", data[:n * 4])
data = data[n * 4:]
g.frames = []
for k in range(g.numframes):
f = frame()
x = unpack("<3B B 3B B 16s", data[:24])
data = data[24:]
f.mins = x[0:3]
f.maxs = x[4:7]
f.name = x[8]
f.verts = []
for j in range(mdl.numverts):
x = unpack("<3B B", data[:4])
data = data[4:]
v = vert()
v.r = x[:3]
v.ni = x[3]
f.verts.append(v)
g.frames.append(f)
f = g
mdl.frames.append(f)
return mdl
def make_mesh(mdl, framenum, subframenum=0):
frame = mdl.frames[framenum]
if frame.type:
frame = frame.frames[subframenum]
verts = []
faces = []
s = mdl.scale
o = mdl.scale_origin
m = Matrix(((s.x, 0, 0, 0),
( 0,s.y, 0, 0),
( 0, 0,s.z, 0),
(o.x,o.y,o.z, 1)))
for v in frame.verts:
verts.append(Vector(v.r) * m)
for t in mdl.tris:
faces.append (t.verts)
return verts, faces
def import_mdl(operator, context, filepath):
mdl = load_mdl(filepath)
verts, faces = make_mesh (mdl, 0)
name = filepath.split('/')[-1]
name = name.split('.')[0]
bpy.context.user_preferences.edit.use_global_undo = False
mesh = bpy.data.meshes.new(name)
mesh.from_pydata(verts, [], faces)
mesh.update()
object_data_add(context, mesh, operator=None)
bpy.context.user_preferences.edit.use_global_undo = True
return 'FINISHED'