home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 4987 / xpr script.7z / io_import_xpr.py next >
Encoding:
Python Source  |  2012-01-15  |  9.9 KB  |  224 lines

  1. bl_info = {
  2.     "name": "XPR format",
  3.     "author": "Thomas Larsson",
  4.     "location": "File > Import > Import XPR (.xpr)",
  5.     "description": "xpr import.(vertex buffers)",
  6.     "category": "Import-Export"}
  7.  
  8. import bpy
  9. from bpy.props import *
  10. from bpy_extras.io_utils import ExportHelper, ImportHelper
  11. #----------------------------------------------------------
  12. import bpy, os
  13. import struct
  14. import chunk
  15.  
  16. def import_xpr(filepath):
  17.     name = os.path.basename(filepath)
  18.     realpath = os.path.realpath(os.path.expanduser(filepath))
  19.     file = open(realpath, 'rb')    # Universal read
  20.     print('Importing %s' % realpath)
  21.     
  22.     skBones = []
  23.     highBones = []
  24.   #try to open cat file
  25.     skeletonPath = os.path.dirname(filepath) + "\\\\skeletons\\" + name[0] + name[1] + name[2] + ".doau"
  26.     if os.path.lexists(skeletonPath):
  27.         print("skeleton found")
  28.         catpath = realpath.replace('.xpr','.cat')
  29.         if os.path.exists(catpath):
  30.             print("cat found")
  31.             with open(skeletonPath, 'rb') as f:
  32.                 temp_read = f.read()
  33.                 f.seek(0)
  34.                 for i in range(0, len(temp_read), 0x10):
  35.                     skBones.append(struct.unpack("<ffff", f.read(16)))
  36.             print("the skeleton has %d bones = {"% len(skBones))
  37.             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]))
  38.             print("}")
  39.             with open(catpath, 'rb') as f:
  40.                 temp = struct.unpack("<L", f.read(4))[0]
  41.                 if temp == 0x20:
  42.                     f.seek(28)#go to high poly
  43.                     temp_offset = struct.unpack("<L", f.read(4))[0]
  44.                     f.seek(temp_offset + 0x14)
  45.                     while True:
  46.                         highBones.append(struct.unpack("<BBB", f.read(3)))#B unsigned char
  47.                         if highBones[len(highBones) - 1][0] == 0:
  48.                             highBones.pop()
  49.                             break
  50.                     for i in range(len(highBones)): print("id_%d, bone_%x, OBJ_%d"% (highBones[i][0], highBones[i][1], highBones[i][2]))
  51.                     print("%d high bones"% len(highBones))
  52.  
  53.                     f.seek(16)#go to joints
  54.                     joints_offset = struct.unpack("<L", f.read(4))[0]
  55.                     f.seek(joints_offset)
  56.                     joints = []
  57.                     joint = struct.unpack("<L", f.read(4))[0]
  58.                     while joint != 0:
  59.                         joints.append(joint)
  60.                         joint = struct.unpack("<L", f.read(4))[0]
  61.                     for i in range(len(joints)):
  62.                         f.seek(joints[i] + joints_offset + 8)
  63.                         jointObj, jointBone = struct.unpack("<BB", f.read(2))
  64.                         highBones.append((3, jointBone, jointObj))
  65.                     print("joints %d"% len(joints))
  66.                 else:print("wrong cat header")
  67.         else:print("cat not found")
  68.     else:print("skeleton not found. skeleton folder should be in the same folder with xpr and cat : %s"%skeletonPath)
  69.  
  70.     #return
  71.  
  72.     bonesHierarchy = []
  73.     bonesHierarchy.append((2, -1))
  74.     bonesHierarchy.append((0,2))
  75.     bonesHierarchy.append((-1, -1)) #in a python list you can't store a list with size = 0, or size = 1 :((
  76.     bonesHierarchy.append((7,6,2))
  77.     bonesHierarchy.append((8,0,2))
  78.     bonesHierarchy.append((4,8,0,2))
  79.     bonesHierarchy.append((2, -1))
  80.     bonesHierarchy.append((6,2))
  81.     bonesHierarchy.append((0,2))
  82.     bonesHierarchy.append((0xd,0xc,2))
  83.     bonesHierarchy.append((0xe,0,2))
  84.     bonesHierarchy.append((0xa,0xe,0,2))
  85.     bonesHierarchy.append((2, -1))
  86.     bonesHierarchy.append((0xc,2))
  87.     bonesHierarchy.append((0,2))
  88.     
  89.     try:
  90.         dwXprMagic, dwXPRSize, dwHeaderSize, dwChunkID = struct.unpack("<4sLLL", file.read(16))
  91.     except:
  92.         print("Error parsing file header!")
  93.         file.close()
  94.         return
  95.         
  96.     # Handle XPR
  97.     if dwXprMagic == b'XPR0':#is "xpr"
  98.             if dwChunkID == 0x80000000:
  99.                 print("mdl ID")#is first chunk a mdl one
  100.                 dwMDLSize, dwMDLMagic, dwNumObj, dwNumTxt, dwUnk0, dwNumIVBuf = struct.unpack("<1L4sLLLL", file.read(24))
  101.                 if dwMDLMagic == b'MDL\0':#is magic "mdl"
  102.                     print("mdl magic. objects %d"% dwNumObj)
  103.                     objects = []
  104.                     for object in range(dwNumObj): objects.append(struct.unpack("<1L", file.read(4))[0])
  105.     # Handle OBJ
  106.                     for object in range(len(objects)):
  107.                         file.seek(objects[object])
  108.                         dwOBJMagic = struct.unpack("<4s", file.read(4))[0]
  109.                         if dwOBJMagic == b'OBJ\0': 
  110.                             #print("%x obj magic"% (objects[object]))
  111.                             verts = []
  112.                             faces = []
  113.                             indices = []
  114.                             normals = []
  115.                             diffuse = []
  116.                             uv = []
  117.                           #load first vertex buffer
  118.                             file.seek(28, 1)
  119.                             dwNumVertices, dwVBufOffset, dwNumIndices, dwIBufOffset = struct.unpack("<LLLL", file.read(16))
  120.                             buffer = 0
  121.                           #if first vertex buffer not found load the second one
  122.                             if dwNumVertices == 0:
  123.                                 dwNumVertices, dwVBufOffset, dwNumIndices, dwIBufOffset = struct.unpack("<LLLL", file.read(16))
  124.                                 buffer = 1
  125.                           #go to buffer offset and read the fvf
  126.                             file.seek(dwIBufOffset)
  127.                             for i in range(dwNumIndices): indices.append(struct.unpack("<1H", file.read(2))[0])#H - usigned short
  128.                             for i in range(dwNumIndices - 2): faces.append((indices[i], indices[i + 1], indices[i + 2]))
  129.                             file.seek(dwVBufOffset)
  130.                             scale = 3
  131.                             for v in range(dwNumVertices):
  132.                                 vx, vy, vz = struct.unpack("<fff", file.read(12))
  133.                                 #verts.append( (scale*vx, -scale*vz, scale*vy) )
  134.                                 verts.append( (vx, vy, vz) )
  135.                                 if buffer == 0:
  136.                                     normals.append(struct.unpack("<3f", file.read(12)))
  137.                                 else:
  138.                                     diffuse.append(struct.unpack("<f", file.read(4))[0])
  139.                                 uv.append(struct.unpack("<2f", file.read(8)))
  140.                           #create object from verts and faces
  141.                             name = "vtf%d"% (object + 100)
  142.                             me = bpy.data.meshes.new(name)
  143.                             me.from_pydata(verts, [], faces)
  144.                             me.update()
  145.                           #add new obj to scene
  146.                             scn = bpy.context.scene
  147.                             ob = bpy.data.objects.new(name, me)
  148.                             scn.objects.link(ob)
  149.                             scn.objects.active = ob
  150.                             
  151.                             isHBone = False
  152.                             #print("object %x"% object)
  153.                             for i in range(len(highBones)):
  154.                                 if object == highBones[i][2]:
  155.                                     bn = highBones[i][1]
  156.                                     if bn < len(bonesHierarchy):
  157.                                         isHBone = True
  158.                                         newx = skBones[bn][0]
  159.                                         newy = skBones[bn][1]
  160.                                         newz = skBones[bn][2]
  161.                                         print("=====%d"% len(bonesHierarchy[bn]))
  162.                                         for j in range(len(bonesHierarchy[bn])):
  163.                                             print("+ %x"% bonesHierarchy[bn][j])
  164.                                             if bonesHierarchy[bn][j] == -1:
  165.                                                 break
  166.                                             else:
  167.                                                 newx += skBones[bonesHierarchy[bn][j]][0]
  168.                                                 newy += skBones[bonesHierarchy[bn][j]][1]
  169.                                                 newz += skBones[bonesHierarchy[bn][j]][2]
  170.                                         ob.location = [newx, newy, newz]
  171.                                         break
  172.                             if isHBone == False: ob.location = [2,0,0]
  173.                             
  174.                             #go to edit mode and fix the mesh
  175.                             bpy.ops.object.mode_set(mode='EDIT')
  176.                             bpy.ops.mesh.select_all(action='SELECT')
  177.                             bpy.ops.mesh.normals_make_consistent(inside=False)
  178.                             bpy.ops.object.editmode_toggle()
  179.                             
  180.                     
  181.                 else:
  182.                     print("not mdl magic")
  183.             else: print("first chunk is not mdl chunk %x " % dwChunkID)
  184.     else:
  185.         print("No XPR0 found! %s" % dwXprMagic)
  186.         file.close()
  187.         return
  188.  
  189.     file.close()
  190.  
  191.     return
  192.  
  193. class IMPORT_OT_xpr(bpy.types.Operator, ImportHelper):
  194.     bl_idname= "import_scene.xpr"
  195.     bl_description = 'Import from XPR vBuffers (.xpr)'
  196.     bl_label = "Import XPR"
  197.     filename_ext = ".xpr"
  198.     filter_glob = StringProperty(default="*.xpr", options={'HIDDEN'})
  199.  
  200.     filepath= StringProperty(name="File Path", description="Filepath used for importing the XPR file", maxlen=1024, default="")
  201.  
  202.     def execute(self, context): 
  203.         import_xpr(self.properties.filepath)
  204.         return {'FINISHED'}
  205.  
  206.     def invoke(self, context, event):
  207.         context.window_manager.fileselect_add(self)
  208.         return {'RUNNING_MODAL'}
  209.         
  210.  
  211. def menu_func(self, context):
  212.     self.layout.operator(IMPORT_OT_xpr.bl_idname, text="XPR vBuffers (.xpr)")
  213.  
  214. def register():
  215.     bpy.utils.register_module(__name__)
  216.     bpy.types.INFO_MT_file_import.append(menu_func)
  217.  
  218. def unregister():
  219.     bpy.utils.unregister_module(__name__)
  220.     bpy.types.INFO_MT_file_import.remove(menu_func)
  221.  
  222. if __name__ == "__main__":
  223.     register()
  224.