diff options
author | Campbell Barton <ideasman42@gmail.com> | 2007-01-28 15:33:04 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2007-01-28 15:33:04 +0300 |
commit | 5943ad8f6572824c83dcd2d13302788b0d200d0a (patch) | |
tree | 054ccd6e628da191186aec27be3078aeb5ca6334 /release/scripts | |
parent | c7718d2bcd644286c7f9ceed0a60118a9cd81589 (diff) |
update to the md2 importer.
* moved from NMesh to Mesh
* made newstyle classes (use less memory)
* optimized mesh creation
* Animation now imports and plays (Bugfix for 5834)
+ other small tweaks
Added mesh.key - was missing from docs
Diffstat (limited to 'release/scripts')
-rw-r--r-- | release/scripts/md2_import.py | 273 |
1 files changed, 150 insertions, 123 deletions
diff --git a/release/scripts/md2_import.py b/release/scripts/md2_import.py index 82b76d40c94..e39b2ca85ec 100644 --- a/release/scripts/md2_import.py +++ b/release/scripts/md2_import.py @@ -8,7 +8,7 @@ Tooltip: 'Import from Quake file format (.md2).' """ __author__ = 'Bob Holcomb' -__version__ = '0.15' +__version__ = '0.16' __url__ = ["Bob's site, http://bane.servebeer.com", "Support forum, http://scourage.servebeer.com/phpbb/", "blender", "elysiun"] __email__ = ["Bob Holcomb, bob_holcomb:hotmail*com", "scripts"] @@ -16,7 +16,7 @@ __bpydoc__ = """\ This script imports a Quake 2 file (MD2), textures, and animations into blender for editing. Loader is based on MD2 loader from www.gametutorials.com-Thanks DigiBen! and the md3 blender loader by PhaethonH <phaethon@linux.ucla.edu><br> - Additional help from: Shadwolf, Skandal, Rojo, Cambo<br> + Additional help from: Shadwolf, Skandal, Rojo and Campbell Barton<br> Thanks Guys! """ @@ -43,18 +43,15 @@ and animations into blender for editing. Loader is based on MD2 loader from www import Blender -from Blender import NMesh, Object, sys +from Blender import Mesh, Object, sys from Blender.BGL import * from Blender.Draw import * from Blender.Window import * -from Blender.Image import * - -import struct, string +from Blender.Mathutils import Vector +import struct from types import * - - ###################################################### # Main Body ###################################################### @@ -80,10 +77,8 @@ MD2_MAX_FRAMESIZE=(MD2_MAX_VERTICES * 4 + 128) ###################################################### # MD2 data structures ###################################################### -class md2_alias_triangle: - vertices=[] - lightnormalindex=0 - +class md2_alias_triangle(object): + __slots__ = 'vertices', 'lightnormalindex' binary_format="<3BB" #little-endian (<), 3 Unsigned char def __init__(self): @@ -107,12 +102,12 @@ class md2_alias_triangle: print "lightnormalindex: ",self.lightnormalindex print "" -class md2_face: - vertex_index=[] - texture_index=[] - +class md2_face(object): + binary_format="<3h3h" #little-endian (<), 3 short, 3 short + __slots__ = 'vertex_index', 'texture_index' + def __init__(self): self.vertex_index = [ 0, 0, 0 ] self.texture_index = [ 0, 0, 0] @@ -138,12 +133,10 @@ class md2_face: print "texture index: ", self.texture_index[2] print "" -class md2_tex_coord: - u=0 - v=0 - +class md2_tex_coord(object): + __slots__ = 'u', 'v' binary_format="<2h" #little-endian (<), 2 unsigned short - + def __init__(self): self.u=0 self.v=0 @@ -162,9 +155,8 @@ class md2_tex_coord: print "" -class md2_skin: - name="" - +class md2_skin(object): + __slots__ = 'name' binary_format="<64s" #little-endian (<), char[64] def __init__(self): @@ -181,12 +173,8 @@ class md2_skin: print "skin name: ",self.name print "" -class md2_alias_frame: - scale=[] - translate=[] - name=[] - vertices=[] - +class md2_alias_frame(object): + __slots__ = 'scale', 'translate', 'name', 'vertices' binary_format="<3f3f16s" #little-endian (<), 3 float, 3 float char[16] #did not add the "3bb" to the end of the binary format #because the alias_vertices will be read in through @@ -222,7 +210,17 @@ class md2_alias_frame: print "name: ",self.name print "" -class md2_obj: +class md2_obj(object): + __slots__ =\ + 'tex_coords', 'faces', 'frames',\ + 'skins', 'ident', 'version',\ + 'skin_width', 'skin_height',\ + 'frame_size', 'num_skins', 'num_vertices',\ + 'num_tex_coords', 'num_faces', 'num_GL_commands',\ + 'num_frames', 'offset_skins', 'offset_tex_coords',\ + 'offset_faces', 'offset_frames', 'offset_GL_commands' + + ''' #Header Structure ident=0 #int 0 This is used to identify the file version=0 #int 1 The version number of the file (Must be 8) @@ -241,14 +239,10 @@ class md2_obj: offset_frames=0 #int 14 The offset in the file for the frames data offset_GL_commands=0#int 15 The offset in the file for the gl commands data offset_end=0 #int 16 The end of the file offset - + ''' binary_format="<17i" #little-endian (<), 17 integers (17i) #md2 data objects - tex_coords=[] - faces=[] - frames=[] - skins=[] def __init__ (self): self.tex_coords=[] @@ -356,133 +350,162 @@ class md2_obj: ###################################################### def load_textures(md2, texture_filename): #did the user specify a texture they wanted to use? - if (texture_filename!="texture"): + if texture_filename: if (Blender.sys.exists(texture_filename)): - mesh_image=Blender.Image.Load(texture_filename) - return mesh_image - else: - result=Blender.Draw.PupMenu("Cannot find texture: "+texture_filename+"-Continue?%t|OK") - if(result==1): - return -1 + try: return Blender.Image.Load(texture_filename) + except: return -1 # could not load? + #does the model have textures specified with it? if int(md2.num_skins) > 0: for i in xrange(0,md2.num_skins): #md2.skins[i].dump() if (Blender.sys.exists(md2.skins[i].name)): - mesh_image=Blender.Image.Load(md2.skins[i].name) - else: - result=Blender.Draw.PupMenu("Cannot find texture: "+md2.skins[i].name+"-Continue?%t|OK") - if(result==1): - return -1 - return mesh_image - else: - result=Blender.Draw.PupMenu("There will be no Texutre"+"-Continue?%t|OK") - if(result==1): - return -1 + try: return Blender.Image.Load(md2.skins[i].name) + except: return -1 -def animate_md2(md2, mesh_obj): +def animate_md2(md2, mesh): ######### Animate the verts through keyframe animation - mesh=mesh_obj.getData() + + # Fast access to the meshes vertex coords + verts = [v.co for v in mesh.verts] + scale = g_scale.val + for i in xrange(1, md2.num_frames): + frame = md2.frames[i] #update the vertices - for j in xrange(0,md2.num_vertices): - x=(md2.frames[i].scale[0]*md2.frames[i].vertices[j].vertices[0]+md2.frames[i].translate[0])*g_scale.val - y=(md2.frames[i].scale[1]*md2.frames[i].vertices[j].vertices[1]+md2.frames[i].translate[1])*g_scale.val - z=(md2.frames[i].scale[2]*md2.frames[i].vertices[j].vertices[2]+md2.frames[i].translate[2])*g_scale.val - + for j in xrange(md2.num_vertices): + x=(frame.scale[0] * frame.vertices[j].vertices[0] + frame.translate[0]) * scale + y=(frame.scale[1] * frame.vertices[j].vertices[1] + frame.translate[1]) * scale + z=(frame.scale[2] * frame.vertices[j].vertices[2] + frame.translate[2]) * scale + #put the vertex in the right spot - mesh.verts[j].co[0]=y - mesh.verts[j].co[1]=-x - mesh.verts[j].co[2]=z - - mesh.update() - NMesh.PutRaw(mesh, mesh_obj.name) - #absolute keys, need to figure out how to get them working around the 100 frame limitation + verts[j][:] = y,-x,z + mesh.insertKey(i,"absolute") + # mesh.insertKey(i) #not really necissary, but I like playing with the frame counter Blender.Set("curframe", i) + + + # Make the keys animate in the 3d view. + key = mesh.key + key.relative = False + + # Add an IPO to teh Key + ipo = Blender.Ipo.New('Key', 'md2') + key.ipo = ipo + # Add a curve to the IPO + curve = ipo.addCurve('Basis') + + # Add 2 points to cycle through the frames. + curve.append((1, 0)) + curve.append((md2.num_frames, (md2.num_frames-1)/10.0)) + curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR + -def load_md2 (md2_filename, texture_filename): +def load_md2(md2_filename, texture_filename): #read the file in file=open(md2_filename,"rb") + WaitCursor(1) + DrawProgressBar(0.0, 'Loading MD2') md2=md2_obj() md2.load(file) #md2.dump() file.close() ######### Creates a new mesh - mesh = NMesh.New() + mesh = Mesh.New() uv_coord=[] - uv_list=[] - + #uv_list=[] + verts_extend = [] #load the textures to use later #-1 if there is no texture to load mesh_image=load_textures(md2, texture_filename) + if mesh_image == -1 and texture_filename: + print 'MD2 Import, Warning, texture "%s" could not load' ######### Make the verts DrawProgressBar(0.25,"Loading Vertex Data") - for i in xrange(0,md2.num_vertices): + frame = md2.frames[0] + scale = g_scale.val + + def tmp_get_vertex(i): #use the first frame for the mesh vertices - x=(md2.frames[0].scale[0]*md2.frames[0].vertices[i].vertices[0]+md2.frames[0].translate[0])*g_scale.val - y=(md2.frames[0].scale[1]*md2.frames[0].vertices[i].vertices[1]+md2.frames[0].translate[1])*g_scale.val - z=(md2.frames[0].scale[2]*md2.frames[0].vertices[i].vertices[2]+md2.frames[0].translate[2])*g_scale.val - vertex=NMesh.Vert(y,-x,z) - mesh.verts.append(vertex) - + x=(frame.scale[0]*frame.vertices[i].vertices[0]+frame.translate[0])*scale + y=(frame.scale[1]*frame.vertices[i].vertices[1]+frame.translate[1])*scale + z=(frame.scale[2]*frame.vertices[i].vertices[2]+frame.translate[2])*scale + return y,-x,z + + mesh.verts.extend( [tmp_get_vertex(i) for i in xrange(0,md2.num_vertices)] ) + del tmp_get_vertex + ######## Make the UV list DrawProgressBar(0.50,"Loading UV Data") - mesh.hasFaceUV(1) #turn on face UV coordinates for this mesh - for i in xrange(0, md2.num_tex_coords): - u=(float(md2.tex_coords[i].u)/float(md2.skin_width)) - v=(float(md2.tex_coords[i].v)/float(md2.skin_height)) - #for some reason quake2 texture maps are upside down, flip that - uv_coord=(u,1-v) - uv_list.append(uv_coord) - + + w = float(md2.skin_width) + h = float(md2.skin_height) + #for some reason quake2 texture maps are upside down, flip that + uv_list = [Vector(co.u/w, 1-(co.v/h)) for co in md2.tex_coords] + del w, h + ######### Make the faces DrawProgressBar(0.75,"Loading Face Data") - for i in xrange(0,md2.num_faces): - face = NMesh.Face() - #draw the triangles in reverse order so they show up - face.v.append(mesh.verts[md2.faces[i].vertex_index[0]]) - face.v.append(mesh.verts[md2.faces[i].vertex_index[2]]) - face.v.append(mesh.verts[md2.faces[i].vertex_index[1]]) - #append the list of UV - #ditto in reverse order with the texture verts - face.uv.append(uv_list[md2.faces[i].texture_index[0]]) - face.uv.append(uv_list[md2.faces[i].texture_index[2]]) - face.uv.append(uv_list[md2.faces[i].texture_index[1]]) - - #set the texture that this face uses if it has one - if (mesh_image!=-1): - face.image=mesh_image + faces = [] + face_uvs = [] + for md2_face in md2.faces: + f = md2_face.vertex_index[0], md2_face.vertex_index[2], md2_face.vertex_index[1] + uv = uv_list[md2_face.texture_index[0]], uv_list[md2_face.texture_index[2]], uv_list[md2_face.texture_index[1]] - #add the face - mesh.faces.append(face) - - mesh_obj=NMesh.PutRaw(mesh) - animate_md2(md2, mesh_obj) - DrawProgressBar(0.999,"Loading Animation Data") + if f[2] == 0: + # EEKADOODLE :/ + f= f[1], f[2], f[0] + uv= uv[1], uv[2], uv[0] + + #ditto in reverse order with the texture verts + faces.append(f) + face_uvs.append(uv) + + + face_mapping = mesh.faces.extend(faces, indexList=True) + print len(faces) + print len(mesh.faces) + mesh.faceUV= True #turn on face UV coordinates for this mesh + mesh_faces = mesh.faces + for i, uv in enumerate(face_uvs): + if face_mapping[i] != None: + f = mesh_faces[face_mapping[i]] + f.uv = uv + if (mesh_image!=-1): + f.image=mesh_image + + scn= Blender.Scene.GetCurrent() + mesh_obj= scn.objects.new(mesh) + animate_md2(md2, mesh) + DrawProgressBar(0.98,"Loading Animation Data") #locate the Object containing the mesh at the cursor location cursor_pos=Blender.Window.GetCursorPos() mesh_obj.setLocation(float(cursor_pos[0]),float(cursor_pos[1]),float(cursor_pos[2])) - DrawProgressBar (1.0, "Finished") + DrawProgressBar (1.0, "") + WaitCursor(0) #*********************************************** # MAIN #*********************************************** # Import globals -g_md2_filename=Create("model") -g_texture_filename=Create("texture") +g_md2_filename=Create("*.md2") +#g_md2_filename=Create("/d/warvet/tris.md2") +g_texture_filename=Create('') +# g_texture_filename=Create("/d/warvet/warvet.jpg") -g_filename_search=Create("model") -g_texture_search=Create("texture") +g_filename_search=Create("*.md2") +g_texture_search=Create('') +# g_texture_search=Create("/d/warvet/warvet.jpg") #Globals g_scale=Create(1.0) @@ -523,23 +546,27 @@ def draw_gui(): Text("MD2 loader") ######### Parameters GUI Buttons + BeginAlign() g_md2_filename = String("MD2 file to load: ", EVENT_NOEVENT, 10, 55, 210, 18, - g_md2_filename.val, 255, "MD2 file to load") + g_md2_filename.val, 255, "MD2 file to load") ########## MD2 File Search Button - Button("Search",EVENT_CHOOSE_FILENAME,220,55,80,18) + Button("Browse",EVENT_CHOOSE_FILENAME,220,55,80,18) + EndAlign() + BeginAlign() g_texture_filename = String("Texture file to load: ", EVENT_NOEVENT, 10, 35, 210, 18, - g_texture_filename.val, 255, "Texture file to load-overrides MD2 file") + g_texture_filename.val, 255, "Texture file to load-overrides MD2 file") ########## Texture Search Button - Button("Search",EVENT_CHOOSE_TEXTURE,220,35,80,18) + Button("Browse",EVENT_CHOOSE_TEXTURE,220,35,80,18) + EndAlign() ########## Scale slider-default is 1/8 which is a good scale for md2->blender g_scale= Slider("Scale Factor: ", EVENT_NOEVENT, 10, 75, 210, 18, - 1.0, 0.001, 10.0, 1, "Scale factor for obj Model"); + 1.0, 0.001, 10.0, 1, "Scale factor for obj Model"); ######### Draw and Exit Buttons Button("Load",EVENT_LOAD_MD2 , 10, 10, 80, 18) - Button("Exit",EVENT_EXIT , 170, 10, 80, 18) + Button("Exit",EVENT_EXIT , 170, 10, 80, 18) def event(evt, val): if (evt == QKEY and not val): @@ -558,14 +585,14 @@ def bevent(evt): elif (evt==EVENT_CHOOSE_TEXTURE): FileSelector(texture_callback, "Texture Selection") elif (evt==EVENT_LOAD_MD2): - if (g_md2_filename.val == "model"): - Blender.Draw.Exit() + if not Blender.sys.exists(g_md2_filename.val): + PupMenu('Model file does not exist') return else: load_md2(g_md2_filename.val, g_texture_filename.val) - Blender.Redraw() + Blender.Redraw() Blender.Draw.Exit() return - -Register(draw_gui, event, bevent) +if __name__ == '__main__': + Register(draw_gui, event, bevent) |