mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 04:21:51 +00:00
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:
parent
5029fde3e1
commit
9d025e0058
3 changed files with 273 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,6 +6,7 @@
|
|||
*.a
|
||||
*.o
|
||||
*~
|
||||
__pycache__/
|
||||
autom4te.cache/
|
||||
.deps/
|
||||
.libs/
|
||||
|
|
94
tools/qfmdl/__init__.py
Normal file
94
tools/qfmdl/__init__.py
Normal 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
178
tools/qfmdl/import_mdl.py
Normal 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'
|
||||
|
Loading…
Reference in a new issue