home *** CD-ROM | disk | FTP | other *** search
- bl_info = {
- "name": "XPR format",
- "author": "Thomas Larsson",
- "location": "File > Import > Import XPR (.xpr)",
- "description": "xpr import.(vertex buffers)",
- "category": "Import-Export"}
-
- import bpy
- from bpy.props import *
- from bpy_extras.io_utils import ExportHelper, ImportHelper
- #----------------------------------------------------------
- import bpy, os
- import struct
- import chunk
-
- def import_xpr(filepath):
- name = os.path.basename(filepath)
- realpath = os.path.realpath(os.path.expanduser(filepath))
- file = open(realpath, 'rb') # Universal read
- print('Importing %s' % realpath)
-
- skBones = []
- highBones = []
- #try to open cat file
- skeletonPath = os.path.dirname(filepath) + "\\\\skeletons\\" + name[0] + name[1] + name[2] + ".doau"
- if os.path.lexists(skeletonPath):
- print("skeleton found")
- catpath = realpath.replace('.xpr','.cat')
- if os.path.exists(catpath):
- print("cat found")
- with open(skeletonPath, 'rb') as f:
- temp_read = f.read()
- f.seek(0)
- for i in range(0, len(temp_read), 0x10):
- skBones.append(struct.unpack("<ffff", f.read(16)))
- print("the skeleton has %d bones = {"% len(skBones))
- for i in range(len(skBones)): print("bone_%d = \t%f, \t%f, \t%f, \t%f"% (i, skBones[i][0], skBones[i][1], skBones[i][2], skBones[i][3]))
- print("}")
- with open(catpath, 'rb') as f:
- temp = struct.unpack("<L", f.read(4))[0]
- if temp == 0x20:
- f.seek(28)#go to high poly
- temp_offset = struct.unpack("<L", f.read(4))[0]
- f.seek(temp_offset + 0x14)
- while True:
- highBones.append(struct.unpack("<BBB", f.read(3)))#B unsigned char
- if highBones[len(highBones) - 1][0] == 0:
- highBones.pop()
- break
- for i in range(len(highBones)): print("id_%d, bone_%x, OBJ_%d"% (highBones[i][0], highBones[i][1], highBones[i][2]))
- print("%d high bones"% len(highBones))
-
- f.seek(16)#go to joints
- joints_offset = struct.unpack("<L", f.read(4))[0]
- f.seek(joints_offset)
- joints = []
- joint = struct.unpack("<L", f.read(4))[0]
- while joint != 0:
- joints.append(joint)
- joint = struct.unpack("<L", f.read(4))[0]
- for i in range(len(joints)):
- f.seek(joints[i] + joints_offset + 8)
- jointObj, jointBone = struct.unpack("<BB", f.read(2))
- highBones.append((3, jointBone, jointObj))
- print("joints %d"% len(joints))
- else:print("wrong cat header")
- else:print("cat not found")
- else:print("skeleton not found. skeleton folder should be in the same folder with xpr and cat : %s"%skeletonPath)
-
- #return
-
- bonesHierarchy = []
- bonesHierarchy.append((2, -1))
- bonesHierarchy.append((0,2))
- bonesHierarchy.append((-1, -1)) #in a python list you can't store a list with size = 0, or size = 1 :((
- bonesHierarchy.append((7,6,2))
- bonesHierarchy.append((8,0,2))
- bonesHierarchy.append((4,8,0,2))
- bonesHierarchy.append((2, -1))
- bonesHierarchy.append((6,2))
- bonesHierarchy.append((0,2))
- bonesHierarchy.append((0xd,0xc,2))
- bonesHierarchy.append((0xe,0,2))
- bonesHierarchy.append((0xa,0xe,0,2))
- bonesHierarchy.append((2, -1))
- bonesHierarchy.append((0xc,2))
- bonesHierarchy.append((0,2))
-
- try:
- dwXprMagic, dwXPRSize, dwHeaderSize, dwChunkID = struct.unpack("<4sLLL", file.read(16))
- except:
- print("Error parsing file header!")
- file.close()
- return
-
- # Handle XPR
- if dwXprMagic == b'XPR0':#is "xpr"
- if dwChunkID == 0x80000000:
- print("mdl ID")#is first chunk a mdl one
- dwMDLSize, dwMDLMagic, dwNumObj, dwNumTxt, dwUnk0, dwNumIVBuf = struct.unpack("<1L4sLLLL", file.read(24))
- if dwMDLMagic == b'MDL\0':#is magic "mdl"
- print("mdl magic. objects %d"% dwNumObj)
- objects = []
- for object in range(dwNumObj): objects.append(struct.unpack("<1L", file.read(4))[0])
- # Handle OBJ
- for object in range(len(objects)):
- file.seek(objects[object])
- dwOBJMagic = struct.unpack("<4s", file.read(4))[0]
- if dwOBJMagic == b'OBJ\0':
- #print("%x obj magic"% (objects[object]))
- verts = []
- faces = []
- indices = []
- normals = []
- diffuse = []
- uv = []
- #load first vertex buffer
- file.seek(28, 1)
- dwNumVertices, dwVBufOffset, dwNumIndices, dwIBufOffset = struct.unpack("<LLLL", file.read(16))
- buffer = 0
- #if first vertex buffer not found load the second one
- if dwNumVertices == 0:
- dwNumVertices, dwVBufOffset, dwNumIndices, dwIBufOffset = struct.unpack("<LLLL", file.read(16))
- buffer = 1
- #go to buffer offset and read the fvf
- file.seek(dwIBufOffset)
- for i in range(dwNumIndices): indices.append(struct.unpack("<1H", file.read(2))[0])#H - usigned short
- for i in range(dwNumIndices - 2): faces.append((indices[i], indices[i + 1], indices[i + 2]))
- file.seek(dwVBufOffset)
- scale = 3
- for v in range(dwNumVertices):
- vx, vy, vz = struct.unpack("<fff", file.read(12))
- #verts.append( (scale*vx, -scale*vz, scale*vy) )
- verts.append( (vx, vy, vz) )
- if buffer == 0:
- normals.append(struct.unpack("<3f", file.read(12)))
- else:
- diffuse.append(struct.unpack("<f", file.read(4))[0])
- uv.append(struct.unpack("<2f", file.read(8)))
- #create object from verts and faces
- name = "vtf%d"% (object + 100)
- me = bpy.data.meshes.new(name)
- me.from_pydata(verts, [], faces)
- me.update()
- #add new obj to scene
- scn = bpy.context.scene
- ob = bpy.data.objects.new(name, me)
- scn.objects.link(ob)
- scn.objects.active = ob
-
- isHBone = False
- #print("object %x"% object)
- for i in range(len(highBones)):
- if object == highBones[i][2]:
- bn = highBones[i][1]
- if bn < len(bonesHierarchy):
- isHBone = True
- newx = skBones[bn][0]
- newy = skBones[bn][1]
- newz = skBones[bn][2]
- print("=====%d"% len(bonesHierarchy[bn]))
- for j in range(len(bonesHierarchy[bn])):
- print("+ %x"% bonesHierarchy[bn][j])
- if bonesHierarchy[bn][j] == -1:
- break
- else:
- newx += skBones[bonesHierarchy[bn][j]][0]
- newy += skBones[bonesHierarchy[bn][j]][1]
- newz += skBones[bonesHierarchy[bn][j]][2]
- ob.location = [newx, newy, newz]
- break
- if isHBone == False: ob.location = [2,0,0]
-
- #go to edit mode and fix the mesh
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.normals_make_consistent(inside=False)
- bpy.ops.object.editmode_toggle()
-
-
- else:
- print("not mdl magic")
- else: print("first chunk is not mdl chunk %x " % dwChunkID)
- else:
- print("No XPR0 found! %s" % dwXprMagic)
- file.close()
- return
-
- file.close()
-
- return
-
- class IMPORT_OT_xpr(bpy.types.Operator, ImportHelper):
- bl_idname= "import_scene.xpr"
- bl_description = 'Import from XPR vBuffers (.xpr)'
- bl_label = "Import XPR"
- filename_ext = ".xpr"
- filter_glob = StringProperty(default="*.xpr", options={'HIDDEN'})
-
- filepath= StringProperty(name="File Path", description="Filepath used for importing the XPR file", maxlen=1024, default="")
-
- def execute(self, context):
- import_xpr(self.properties.filepath)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- context.window_manager.fileselect_add(self)
- return {'RUNNING_MODAL'}
-
-
- def menu_func(self, context):
- self.layout.operator(IMPORT_OT_xpr.bl_idname, text="XPR vBuffers (.xpr)")
-
- def register():
- bpy.utils.register_module(__name__)
- bpy.types.INFO_MT_file_import.append(menu_func)
-
- def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
- if __name__ == "__main__":
- register()
-