Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Phan <darkneter@gmail.com>2012-11-11 03:00:38 +0400
committerJohn Phan <darkneter@gmail.com>2012-11-11 03:00:38 +0400
commitad777e6b54106d891539eef23fd58fec64e0de77 (patch)
tree779c6dff72c8bc940e37397de127a6757117ba42
parent0b4e923d8baeb7a6bab326e3dfe8fcb7a45ae7b0 (diff)
changed file name and update credits as the bones are working a bit.
-rw-r--r--io_import_scene_unreal_psa_psk.py1089
-rw-r--r--io_import_scene_unreal_psk.py804
2 files changed, 1089 insertions, 804 deletions
diff --git a/io_import_scene_unreal_psa_psk.py b/io_import_scene_unreal_psa_psk.py
new file mode 100644
index 00000000..f7805768
--- /dev/null
+++ b/io_import_scene_unreal_psa_psk.py
@@ -0,0 +1,1089 @@
+# ##### 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 #####
+
+bl_info = {
+ "name": "Import Unreal Skeleton Mesh (.psk)/Animation Set (psa)",
+ "author": "Darknet, flufy3d, camg188",
+ "version": (2, 1),
+ "blender": (2, 6, 4),
+ "location": "File > Import > Skeleton Mesh (.psk)/Animation Set (psa)",
+ "description": "Import Skeleleton Mesh/Animation Data",
+ "warning": "",
+ "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
+ "Scripts/Import-Export/Unreal_psk_psa",
+ "tracker_url": "https://projects.blender.org/tracker/index.php?"\
+ "func=detail&aid=21366",
+ "category": "Import-Export"}
+
+"""
+Version': '2.0' ported by Darknet
+
+Unreal Tournament PSK file to Blender mesh converter V1.0
+Author: D.M. Sturgeon (camg188 at the elYsium forum), ported by Darknet
+Imports a *psk file to a new mesh
+
+-No UV Texutre
+-No Weight
+-No Armature Bones
+-No Material ID
+-Export Text Log From Current Location File (Bool )
+"""
+
+import bpy
+import mathutils
+import math
+from mathutils import *
+from math import *
+from bpy.props import *
+from string import *
+from struct import *
+from math import *
+from bpy.props import *
+
+bpy.types.Scene.unrealbonesize = FloatProperty(
+ name="Bone Length",
+ description="Bone Length from head to tail distance",
+ default=1,min=0.001,max=1000)
+
+#output log in to txt file
+DEBUGLOG = False
+
+scale = 1.0
+bonesize = 1.0
+from bpy_extras.io_utils import unpack_list, unpack_face_list
+
+class md5_bone:
+ bone_index=0
+ name=""
+ bindpos=[]
+ bindmat=[]
+ origmat=[]
+ head=[]
+ tail=[]
+ scale = []
+ parent=""
+ parent_index=0
+ blenderbone=None
+ roll=0
+
+ def __init__(self):
+ self.bone_index=0
+ self.name=""
+ self.bindpos=[0.0]*3
+ self.scale=[0.0]*3
+ self.head=[0.0]*3
+ self.tail=[0.0]*3
+ self.bindmat=[None]*3 #is this how you initilize a 2d-array
+ for i in range(3): self.bindmat[i] = [0.0]*3
+ self.origmat=[None]*3 #is this how you initilize a 2d-array
+ for i in range(3): self.origmat[i] = [0.0]*3
+ self.parent=""
+ self.parent_index=0
+ self.blenderbone=None
+
+ def dump(self):
+ print ("bone index: ", self.bone_index)
+ print ("name: ", self.name)
+ print ("bind position: ", self.bindpos)
+ print ("bind translation matrix: ", self.bindmat)
+ print ("parent: ", self.parent)
+ print ("parent index: ", self.parent_index)
+ print ("blenderbone: ", self.blenderbone)
+
+def getheadpos(pbone,bones):
+ pos_head = [0.0]*3
+
+ #pos = mathutils.Vector((x,y,z)) * pbone.origmat
+ pos = pbone.bindmat.to_translation()
+
+ """
+ tmp_bone = pbone
+ while tmp_bone.name != tmp_bone.parent.name:
+ pos = pos * tmp_bone.parent.bindmat
+ tmp_bone = tmp_bone.parent
+ """
+
+ pos_head[0] = pos.x
+ pos_head[1] = pos.y
+ pos_head[2] = pos.z
+
+ return pos_head
+def gettailpos(pbone,bones):
+ pos_tail = [0.0]*3
+ ischildfound = False
+ childbone = None
+ childbonelist = []
+ for bone in bones:
+ if bone.parent.name == pbone.name:
+ ischildfound = True
+ childbone = bone
+ childbonelist.append(bone)
+
+ if ischildfound:
+ tmp_head = [0.0]*3
+ for bone in childbonelist:
+ tmp_head[0] += bone.head[0]
+ tmp_head[1] += bone.head[1]
+ tmp_head[2] += bone.head[2]
+ tmp_head[0] /= len(childbonelist)
+ tmp_head[1] /= len(childbonelist)
+ tmp_head[2] /= len(childbonelist)
+ return tmp_head
+ else:
+ tmp_len = 0.0
+ tmp_len += (pbone.head[0] - pbone.parent.head[0])**2
+ tmp_len += (pbone.head[1] - pbone.parent.head[1])**2
+ tmp_len += (pbone.head[2] - pbone.parent.head[2])**2
+ tmp_len = tmp_len**0.5 * 0.5
+ pos_tail[0] = pbone.head[0] + tmp_len * pbone.bindmat[0][0]
+ pos_tail[1] = pbone.head[1] + tmp_len * pbone.bindmat[1][0]
+ pos_tail[2] = pbone.head[2] + tmp_len * pbone.bindmat[2][0]
+
+
+ return pos_tail
+
+
+
+def pskimport(infile,importmesh,importbone,bDebugLogPSK,importmultiuvtextures):
+ global DEBUGLOG
+ DEBUGLOG = bDebugLogPSK
+ print ("--------------------------------------------------")
+ print ("---------SCRIPT EXECUTING PYTHON IMPORTER---------")
+ print ("--------------------------------------------------")
+ print (" DEBUG Log:",bDebugLogPSK)
+ print ("Importing file: ", infile)
+
+ pskfile = open(infile,'rb')
+ if (DEBUGLOG):
+ logpath = infile.replace(".psk", ".txt")
+ print("logpath:",logpath)
+ logf = open(logpath,'w')
+
+ def printlog(strdata):
+ if (DEBUGLOG):
+ logf.write(strdata)
+
+ objName = infile.split('\\')[-1].split('.')[0]
+
+ me_ob = bpy.data.meshes.new(objName)
+ print("objName:",objName)
+ printlog(("New Mesh = " + me_ob.name + "\n"))
+ #read general header
+ indata = unpack('20s3i',pskfile.read(32))
+ #not using the general header at this time
+ #==================================================================================================
+ # vertex point
+ #==================================================================================================
+ #read the PNTS0000 header
+ indata = unpack('20s3i',pskfile.read(32))
+ recCount = indata[3]
+ printlog(( "Nbr of PNTS0000 records: " + str(recCount) + "\n"))
+ counter = 0
+ verts = []
+ verts2 = []
+ while counter < recCount:
+ counter = counter + 1
+ indata = unpack('3f',pskfile.read(12))
+ #print(indata[0],indata[1],indata[2])
+ verts.extend([(indata[0],indata[1],indata[2])])
+ verts2.extend([(indata[0],indata[1],indata[2])])
+ #print([(indata[0],indata[1],indata[2])])
+ printlog(str(indata[0]) + "|" +str(indata[1]) + "|" +str(indata[2]) + "\n")
+ #Tmsh.vertices.append(NMesh.Vert(indata[0],indata[1],indata[2]))
+
+ #==================================================================================================
+ # UV
+ #==================================================================================================
+ #read the VTXW0000 header
+ indata = unpack('20s3i',pskfile.read(32))
+ recCount = indata[3]
+ printlog( "Nbr of VTXW0000 records: " + str(recCount)+ "\n")
+ counter = 0
+ UVCoords = []
+ #UVCoords record format = [index to PNTS, U coord, v coord]
+ printlog("[index to PNTS, U coord, v coord]\n");
+ while counter < recCount:
+ counter = counter + 1
+ indata = unpack('hhffhh',pskfile.read(16))
+ UVCoords.append([indata[0],indata[2],indata[3]])
+ printlog(str(indata[0]) + "|" +str(indata[2]) + "|" +str(indata[3])+"\n")
+ #print('mat index %i',indata(4))
+ #print([indata[0],indata[2],indata[3]])
+ #print([indata[1],indata[2],indata[3]])
+
+ #==================================================================================================
+ # Face
+ #==================================================================================================
+ #read the FACE0000 header
+ indata = unpack('20s3i',pskfile.read(32))
+ recCount = indata[3]
+ printlog( "Nbr of FACE0000 records: "+ str(recCount) + "\n")
+ #PSK FACE0000 fields: WdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp
+ #associate MatIdx to an image, associate SmthGrp to a material
+ SGlist = []
+ counter = 0
+ faces = []
+ faceuv = []
+ facesmooth = []
+ #the psk values are: nWdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp
+ printlog("nWdgIdx1|WdgIdx2|WdgIdx3|MatIdx|AuxMatIdx|SmthGrp \n")
+ while counter < recCount:
+ counter = counter + 1
+ indata = unpack('hhhbbi',pskfile.read(12))
+ printlog(str(indata[0]) + "|" +str(indata[1]) + "|" +str(indata[2])+ "|" +str(indata[3])+ "|" +str(indata[4])+ "|" +str(indata[5]) + "\n")
+ #indata[0] = index of UVCoords
+ #UVCoords[indata[0]]=[index to PNTS, U coord, v coord]
+ #UVCoords[indata[0]][0] = index to PNTS
+ PNTSA = UVCoords[indata[2]][0]
+ PNTSB = UVCoords[indata[1]][0]
+ PNTSC = UVCoords[indata[0]][0]
+ #print(PNTSA,PNTSB,PNTSC) #face id vertex
+ #faces.extend([0,1,2,0])
+ faces.extend([(PNTSA,PNTSB,PNTSC,0)])
+ uv = []
+ u0 = UVCoords[indata[2]][1]
+ v0 = UVCoords[indata[2]][2]
+ uv.append([u0,1.0 - v0])
+ u1 = UVCoords[indata[1]][1]
+ v1 = UVCoords[indata[1]][2]
+ uv.append([u1,1.0 - v1])
+ u2 = UVCoords[indata[0]][1]
+ v2 = UVCoords[indata[0]][2]
+ uv.append([u2,1.0 - v2])
+ faceuv.append([uv,indata[3],indata[4],indata[5]])
+
+ #print("material:",indata[3])
+ #print("UV: ",u0,v0)
+ #update the uv var of the last item in the Tmsh.faces list
+ # which is the face just added above
+ ##Tmsh.faces[-1].uv = [(u0,v0),(u1,v1),(u2,v2)]
+ #print("smooth:",indata[5])
+ #collect a list of the smoothing groups
+ facesmooth.append(indata[5])
+ #print(indata[5])
+ if SGlist.count(indata[5]) == 0:
+ SGlist.append(indata[5])
+ print("smooth:",indata[5])
+ #assign a material index to the face
+ #Tmsh.faces[-1].materialIndex = SGlist.index(indata[5])
+ printlog( "Using Materials to represent PSK Smoothing Groups...\n")
+ #==========
+ # skip something...
+ #==========
+
+ #==================================================================================================
+ # Material
+ #==================================================================================================
+ ##
+ #read the MATT0000 header
+ indata = unpack('20s3i',pskfile.read(32))
+ recCount = indata[3]
+ printlog("Nbr of MATT0000 records: " + str(recCount) + "\n" )
+ printlog(" - Not importing any material data now. PSKs are texture wrapped! \n")
+ counter = 0
+ materialcount = 0
+ while counter < recCount:
+ counter = counter + 1
+ indata = unpack('64s6i',pskfile.read(88))
+ materialcount += 1
+ print("Material",counter)
+ print("Mat name %s",indata[0])
+
+ ##
+
+ #==================================================================================================
+ # Bones (Armature)
+ #==================================================================================================
+ #read the REFSKEL0 header
+ indata = unpack('20s3i',pskfile.read(32))
+ recCount = indata[3]
+ printlog( "Nbr of REFSKEL0 records: " + str(recCount) + "\n")
+ #REFSKEL0 fields - Name|Flgs|NumChld|PrntIdx|Qw|Qx|Qy|Qz|LocX|LocY|LocZ|Lngth|XSize|YSize|ZSize
+
+ Bns = []
+ bone = []
+
+ md5_bones = []
+ bni_dict = {}
+ #==================================================================================================
+ # Bone Data
+ #==================================================================================================
+ counter = 0
+ print ("---PRASE--BONES---")
+ printlog("Name|Flgs|NumChld|PrntIdx|Qx|Qy|Qz|Qw|LocX|LocY|LocZ|Lngth|XSize|YSize|ZSize\n")
+ while counter < recCount:
+ indata = unpack('64s3i11f',pskfile.read(120))
+ #print( "DATA",str(indata))
+
+ bone.append(indata)
+
+ createbone = md5_bone()
+ #temp_name = indata[0][:30]
+ temp_name = indata[0]
+ temp_name = bytes.decode(temp_name)
+ temp_name = temp_name.lstrip(" ")
+ temp_name = temp_name.rstrip(" ")
+ temp_name = temp_name.strip()
+ temp_name = temp_name.strip( bytes.decode(b'\x00'))
+ printlog(temp_name + "|" +str(indata[1]) + "|" +str(indata[2])+ "|" +str(indata[3])+ "|" +str(indata[4])+ "|" +str(indata[5]) + "|" +str(indata[6]) + "|" +str(indata[7]) + "|" +str(indata[8])+ "|" +str(indata[9])+ "|" +str(indata[10])+ "|" +str(indata[11]) + "|" +str(indata[12]) + "|" +str(indata[13]) + "|" +str(indata[14])+ "\n")
+ createbone.name = temp_name
+ createbone.bone_index = counter
+ createbone.parent_index = indata[3]
+ createbone.bindpos[0] = indata[8]
+ createbone.bindpos[1] = indata[9]
+ createbone.bindpos[2] = indata[10]
+ createbone.scale[0] = indata[12]
+ createbone.scale[1] = indata[13]
+ createbone.scale[2] = indata[14]
+
+ bni_dict[createbone.name] = createbone.bone_index
+
+ #w,x,y,z
+ if (counter == 0):#main parent
+ createbone.bindmat = mathutils.Quaternion((indata[7],-indata[4],-indata[5],-indata[6])).to_matrix()
+ createbone.origmat = mathutils.Quaternion((indata[7],-indata[4],-indata[5],-indata[6])).to_matrix()
+ else:
+ createbone.bindmat = mathutils.Quaternion((indata[7],-indata[4],-indata[5],-indata[6])).to_matrix()
+ createbone.origmat = mathutils.Quaternion((indata[7],-indata[4],-indata[5],-indata[6])).to_matrix()
+
+ createbone.bindmat = mathutils.Matrix.Translation(mathutils.Vector((indata[8],indata[9],indata[10]))) * createbone.bindmat.to_4x4()
+
+
+ md5_bones.append(createbone)
+ counter = counter + 1
+ bnstr = (str(indata[0]))
+ Bns.append(bnstr)
+
+ for pbone in md5_bones:
+ pbone.parent = md5_bones[pbone.parent_index]
+
+
+ for pbone in md5_bones:
+ if pbone.name != pbone.parent.name:
+ pbone.bindmat = pbone.parent.bindmat * pbone.bindmat
+ #print(pbone.name)
+ #print(pbone.bindmat)
+ #print("end")
+ else:
+ pbone.bindmat = pbone.bindmat
+
+ for pbone in md5_bones:
+ pbone.head = getheadpos(pbone,md5_bones)
+
+ for pbone in md5_bones:
+ pbone.tail = gettailpos(pbone,md5_bones)
+
+
+
+ for pbone in md5_bones:
+ pbone.parent = md5_bones[pbone.parent_index].name
+
+
+
+ bonecount = 0
+ for armbone in bone:
+ temp_name = armbone[0][:30]
+ #print ("BONE NAME: ",len(temp_name))
+ temp_name=str((temp_name))
+ #temp_name = temp_name[1]
+ #print ("BONE NAME: ",temp_name)
+ bonecount +=1
+ print ("-------------------------")
+ print ("----Creating--Armature---")
+ print ("-------------------------")
+
+ #================================================================================================
+ #Check armature if exist if so create or update or remove all and addnew bone
+ #================================================================================================
+ #bpy.ops.object.mode_set(mode='OBJECT')
+ meshname ="ArmObject"
+ objectname = "armaturedata"
+ # arm = None # UNUSED
+ if importbone:
+ obj = bpy.data.objects.get(meshname)
+ # arm = obj # UNUSED
+
+ if not obj:
+ armdata = bpy.data.armatures.new(objectname)
+ ob_new = bpy.data.objects.new(meshname, armdata)
+ #ob_new = bpy.data.objects.new(meshname, 'ARMATURE')
+ #ob_new.data = armdata
+ bpy.context.scene.objects.link(ob_new)
+ #bpy.ops.object.mode_set(mode='OBJECT')
+ for i in bpy.context.scene.objects: i.select = False #deselect all objects
+ ob_new.select = True
+ #set current armature to edit the bone
+ bpy.context.scene.objects.active = ob_new
+ #set mode to able to edit the bone
+ if bpy.ops.object.mode_set.poll():
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ #newbone = ob_new.data.edit_bones.new('test')
+ #newbone.tail.y = 1
+ print("creating bone(s)")
+ bpy.ops.object.mode_set(mode='OBJECT')
+ for bone in md5_bones:
+ #print(dir(bone))
+ bpy.ops.object.mode_set(mode='EDIT')#Go to edit mode for the bones
+ newbone = ob_new.data.edit_bones.new(bone.name)
+ #parent the bone
+ #print("DRI:",dir(newbone))
+ parentbone = None
+ #note bone location is set in the real space or global not local
+ bonesize = bpy.types.Scene.unrealbonesize
+ if bone.name != bone.parent:
+ pos_x = bone.bindpos[0]
+ pos_y = bone.bindpos[1]
+ pos_z = bone.bindpos[2]
+ #print( "LINKING:" , bone.parent ,"j")
+ parentbone = ob_new.data.edit_bones[bone.parent]
+ newbone.parent = parentbone
+ rotmatrix = bone.bindmat
+ newbone.head.x = bone.head[0]
+ newbone.head.y = bone.head[1]
+ newbone.head.z = bone.head[2]
+ newbone.tail.x = bone.tail[0]
+ newbone.tail.y = bone.tail[1]
+ newbone.tail.z = bone.tail[2]
+
+ vecp = parentbone.tail - parentbone.head
+ vecc = newbone.tail - newbone.head
+ vecc.normalize()
+ vecp.normalize()
+ if vecp.dot(vecc) > -0.8:
+ newbone.roll = parentbone.roll
+ else:
+ newbone.roll = - parentbone.roll
+ else:
+ rotmatrix = bone.bindmat
+ newbone.head.x = bone.head[0]
+ newbone.head.y = bone.head[1]
+ newbone.head.z = bone.head[2]
+ newbone.tail.x = bone.tail[0]
+ newbone.tail.y = bone.tail[1]
+ newbone.tail.z = bone.tail[2]
+ newbone.roll = math.radians(90.0)
+ """
+ vec = newbone.tail - newbone.head
+ if vec.z > 0.0:
+ newbone.roll = math.radians(90.0)
+ else:
+ newbone.roll = math.radians(-90.0)
+ """
+ bpy.context.scene.update()
+
+ #==================================================================================================
+ #END BONE DATA BUILD
+ #==================================================================================================
+ VtxCol = []
+ for x in range(len(Bns)):
+ #change the overall darkness of each material in a range between 0.1 and 0.9
+ tmpVal = ((float(x)+1.0)/(len(Bns))*0.7)+0.1
+ tmpVal = int(tmpVal * 256)
+ tmpCol = [tmpVal,tmpVal,tmpVal,0]
+ #Change the color of each material slightly
+ if x % 3 == 0:
+ if tmpCol[0] < 128: tmpCol[0] += 60
+ else: tmpCol[0] -= 60
+ if x % 3 == 1:
+ if tmpCol[1] < 128: tmpCol[1] += 60
+ else: tmpCol[1] -= 60
+ if x % 3 == 2:
+ if tmpCol[2] < 128: tmpCol[2] += 60
+ else: tmpCol[2] -= 60
+ #Add the material to the mesh
+ VtxCol.append(tmpCol)
+
+ #==================================================================================================
+ # Bone Weight
+ #==================================================================================================
+ #read the RAWW0000 header
+ indata = unpack('20s3i',pskfile.read(32))
+ recCount = indata[3]
+ printlog( "Nbr of RAWW0000 records: " + str(recCount) +"\n")
+ #RAWW0000 fields: Weight|PntIdx|BoneIdx
+ RWghts = []
+ counter = 0
+ while counter < recCount:
+ counter = counter + 1
+ indata = unpack('fii',pskfile.read(12))
+ RWghts.append([indata[1],indata[2],indata[0]])
+ #print("weight:",[indata[1],indata[2],indata[0]])
+ #RWghts fields = PntIdx|BoneIdx|Weight
+ RWghts.sort()
+ printlog( "Vertex point and groups count =" + str(len(RWghts)) + "\n")
+ printlog("PntIdx|BoneIdx|Weight")
+ for vg in RWghts:
+ printlog( str(vg[0]) + "|" + str(vg[1]) + "|" + str(vg[2]) + "\n")
+
+ #Tmsh.update_tag()
+
+ #set the Vertex Colors of the faces
+ #face.v[n] = RWghts[0]
+ #RWghts[1] = index of VtxCol
+ """
+ for x in range(len(Tmsh.faces)):
+ for y in range(len(Tmsh.faces[x].v)):
+ #find v in RWghts[n][0]
+ findVal = Tmsh.faces[x].v[y].index
+ n = 0
+ while findVal != RWghts[n][0]:
+ n = n + 1
+ TmpCol = VtxCol[RWghts[n][1]]
+ #check if a vertex has more than one influence
+ if n != len(RWghts)-1:
+ if RWghts[n][0] == RWghts[n+1][0]:
+ #if there is more than one influence, use the one with the greater influence
+ #for simplicity only 2 influences are checked, 2nd and 3rd influences are usually very small
+ if RWghts[n][2] < RWghts[n+1][2]:
+ TmpCol = VtxCol[RWghts[n+1][1]]
+ Tmsh.faces[x].col.append(NMesh.Col(TmpCol[0],TmpCol[1],TmpCol[2],0))
+ """
+ if (DEBUGLOG):
+ logf.close()
+ #==================================================================================================
+ #Building Mesh
+ #==================================================================================================
+ print("vertex:",len(verts),"faces:",len(faces))
+ print("vertex2:",len(verts2))
+ me_ob.vertices.add(len(verts2))
+ me_ob.tessfaces.add(len(faces))
+ me_ob.vertices.foreach_set("co", unpack_list(verts2))
+ me_ob.tessfaces.foreach_set("vertices_raw",unpack_list( faces))
+
+ for face in me_ob.tessfaces:
+ face.use_smooth = facesmooth[face.index]
+
+
+ """
+ Material setup coding.
+ First the mesh has to be create first to get the uv texture setup working.
+ -Create material(s) list in the psk pack data from the list.(to do list)
+ -Append the material to the from create the mesh object.
+ -Create Texture(s)
+ -fae loop for uv assign and assign material index
+
+ """
+ bpy.ops.object.mode_set(mode='OBJECT')
+ #===================================================================================================
+ #Material Setup
+ #===================================================================================================
+ print ("-------------------------")
+ print ("----Creating--Materials--")
+ print ("-------------------------")
+ materialname = "pskmat"
+ materials = []
+
+ for matcount in range(materialcount):
+ #if texturedata != None:
+ matdata = bpy.data.materials.new(materialname + str(matcount))
+ #mtex = matdata.texture_slots.new()
+ #mtex.texture = texture[matcount].data
+ #print(type(texture[matcount].data))
+ #print(dir(mtex))
+ #print(dir(matdata))
+ #for texno in range(len( bpy.data.textures)):
+ #print((bpy.data.textures[texno].name))
+ #print(dir(bpy.data.textures[texno]))
+ #matdata.active_texture = bpy.data.textures[matcount-1]
+ #matdata.texture_coords = 'UV'
+ #matdata.active_texture = texturedata
+ materials.append(matdata)
+
+ for material in materials:
+ #add material to the mesh list of materials
+ me_ob.materials.append(material)
+ #===================================================================================================
+ #UV Setup
+ #===================================================================================================
+ print ("-------------------------")
+ print ("-- Creating UV Texture --")
+ print ("-------------------------")
+ texture = []
+ # texturename = "text1" # UNUSED
+ countm = 0
+ for countm in range(materialcount):
+ psktexname="psk" + str(countm)
+ me_ob.uv_textures.new(name=psktexname)
+ countm += 1
+ print("INIT UV TEXTURE...")
+ _matcount = 0
+ #for mattexcount in materials:
+ #print("MATERAIL ID:",_matcount)
+ _textcount = 0
+ for uv in me_ob.tessface_uv_textures: # uv texture
+ print("UV TEXTURE ID:",_textcount)
+ print(dir(uv))
+ for face in me_ob.tessfaces:# face, uv
+ #print(dir(face))
+ if faceuv[face.index][1] == _textcount: #if face index and texture index matches assign it
+ mfaceuv = faceuv[face.index] #face index
+ _uv1 = mfaceuv[0][0] #(0,0)
+ uv.data[face.index].uv1 = mathutils.Vector((_uv1[0],_uv1[1])) #set them
+ _uv2 = mfaceuv[0][1] #(0,0)
+ uv.data[face.index].uv2 = mathutils.Vector((_uv2[0],_uv2[1])) #set them
+ _uv3 = mfaceuv[0][2] #(0,0)
+ uv.data[face.index].uv3 = mathutils.Vector((_uv3[0],_uv3[1])) #set them
+ else: #if not match zero them
+ uv.data[face.index].uv1 = mathutils.Vector((0,0)) #zero them
+ uv.data[face.index].uv2 = mathutils.Vector((0,0)) #zero them
+ uv.data[face.index].uv3 = mathutils.Vector((0,0)) #zero them
+ _textcount += 1
+ #_matcount += 1
+ #print(matcount)
+ print("END UV TEXTURE...")
+
+ print("UV TEXTURE LEN:",len(texture))
+ #for tex in me_ob.uv_textures:
+ #print("mesh tex:",dir(tex))
+ #print((tex.name))
+
+ #for face in me_ob.faces:
+ #print(dir(face))
+
+ #===================================================================================================
+ #
+ #===================================================================================================
+ obmesh = bpy.data.objects.new(objName,me_ob)
+ #===================================================================================================
+ #Mesh Vertex Group bone weight
+ #===================================================================================================
+ print("---- building bone weight mesh ----")
+ #print(dir(ob_new.data.bones))
+ #create bone vertex group #deal with bone id for index number
+ for bone in ob_new.data.bones:
+ #print("names:",bone.name,":",dir(bone))
+ #print("names:",bone.name)
+ group = obmesh.vertex_groups.new(bone.name)
+
+
+ for vgroup in obmesh.vertex_groups:
+ #print(vgroup.name,":",vgroup.index)
+ for vgp in RWghts:
+ #bone index
+
+ if vgp[1] == bni_dict[vgroup.name]:
+ #print(vgp)
+ #[vertex id],weight
+ vgroup.add([vgp[0]], vgp[2], 'ADD')
+
+
+ #check if there is a material to set to
+ if len(materials) > 0:
+ obmesh.active_material = materials[0] #material setup tmp
+ print("---- adding mesh to the scene ----")
+
+ bpy.ops.object.mode_set(mode='OBJECT')
+ #bpy.ops.object.select_pattern(extend=True, pattern=obmesh.name, case_sensitive=True)
+ #bpy.ops.object.select_pattern(extend=True, pattern=ob_new.name, case_sensitive=True)
+
+ #bpy.ops.object.select_name(name=str(obmesh.name))
+ #bpy.ops.object.select_name(name=str(ob_new.name))
+ #bpy.context.scene.objects.active = ob_new
+ me_ob.update()
+ bpy.context.scene.objects.link(obmesh)
+ bpy.context.scene.update()
+ obmesh.select = False
+ ob_new.select = False
+ obmesh.select = True
+ ob_new.select = True
+ bpy.ops.object.parent_set(type="ARMATURE")
+
+ print ("PSK2Blender completed")
+#End of def pskimport#########################
+
+def getInputFilenamepsk(self,filename,importmesh,importbone,bDebugLogPSK,importmultiuvtextures):
+ checktype = filename.split('\\')[-1].split('.')[1]
+ print ("------------",filename)
+ if checktype.lower() != 'psk':
+ print (" Selected file = ",filename)
+ raise (IOError, "The selected input file is not a *.psk file")
+ #self.report({'INFO'}, ("Selected file:"+ filename))
+ else:
+ pskimport(filename,importmesh,importbone,bDebugLogPSK,importmultiuvtextures)
+
+def getInputFilenamepsa(self,filename,context):
+ checktype = filename.split('\\')[-1].split('.')[1]
+ if checktype.lower() != 'psa':
+ print (" Selected file = ",filename)
+ raise (IOError, "The selected input file is not a *.psa file")
+ #self.report({'INFO'}, ("Selected file:"+ filename))
+ else:
+ psaimport(filename,context)
+
+class IMPORT_OT_psk(bpy.types.Operator):
+ '''Load a skeleton mesh psk File'''
+ bl_idname = "import_scene.psk"
+ bl_label = "Import PSK"
+ bl_space_type = "PROPERTIES"
+ bl_region_type = "WINDOW"
+ bl_options = {'UNDO'}
+
+ # List of operator properties, the attributes will be assigned
+ # to the class instance from the operator settings before calling.
+ filepath = StringProperty(
+ subtype='FILE_PATH',
+ )
+ filter_glob = StringProperty(
+ default="*.psk",
+ options={'HIDDEN'},
+ )
+ importmesh = BoolProperty(
+ name="Mesh",
+ description="Import mesh only. (not yet build.)",
+ default=True,
+ )
+ importbone = BoolProperty(
+ name="Bones",
+ description="Import bones only. Current not working yet",
+ default=True,
+ )
+ importmultiuvtextures = BoolProperty(
+ name="Single UV Texture(s)",
+ description="Single or Multi uv textures",
+ default=True,
+ )
+ bDebugLogPSK = BoolProperty(
+ name="Debug Log.txt",
+ description="Log the output of raw format. It will save in " \
+ "current file dir. Note this just for testing",
+ default=False,
+ )
+ unrealbonesize = FloatProperty(
+ name="Bone Length",
+ description="Bone Length from head to tail distance",
+ default=1,
+ min=0.001,
+ max=1000,
+ )
+
+ def execute(self, context):
+ bpy.types.Scene.unrealbonesize = self.unrealbonesize
+ getInputFilenamepsk(self,self.filepath,self.importmesh,self.importbone,self.bDebugLogPSK,self.importmultiuvtextures)
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ wm.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+
+class psa_bone:
+ name=""
+ Transform=None
+ parent=None
+ def __init__(self):
+ self.name=""
+ self.Transform=None
+ self.parent=None
+
+def psaimport(filename,context):
+ print ("--------------------------------------------------")
+ print ("---------SCRIPT EXECUTING PYTHON IMPORTER---------")
+ print ("--------------------------------------------------")
+ print ("Importing file: ", filename)
+ psafile = open(filename,'rb')
+ debug = True
+ if (debug):
+ logpath = filename.replace(".psa", ".txt")
+ print("logpath:",logpath)
+ logf = open(logpath,'w')
+ def printlog(strdata):
+ if (debug):
+ logf.write(strdata)
+ def printlogplus(name,data):
+ if (debug):
+ logf.write(str(name)+'\n')
+ if isinstance(data,bytes):
+ logf.write(str(bytes.decode(data).strip(bytes.decode(b'\x00'))))
+ else:
+ logf.write(str(data))
+ logf.write('\n')
+
+ printlog('-----------Log File------------\n')
+ #General Header
+ indata = unpack('20s3i',psafile.read(32))
+ printlogplus('ChunkID',indata[0])
+ printlogplus('TypeFlag',indata[1])
+ printlogplus('DataSize',indata[2])
+ printlogplus('DataCount',indata[3])
+ #Bones Header
+ indata = unpack('20s3i',psafile.read(32))
+ printlogplus('ChunkID',indata[0])
+ printlogplus('TypeFlag',indata[1])
+ printlogplus('DataSize',indata[2])
+ printlogplus('DataCount',indata[3])
+ #Bones Data
+ BoneIndex2NamePairMap = {}
+ BoneNotFoundList = []
+ printlog("Name|Flgs|NumChld|PrntIdx|Qx|Qy|Qz|Qw|LocX|LocY|LocZ|Length|XSize|YSize|ZSize\n")
+ recCount = indata[3]
+ counter = 0
+ nobonematch = True
+ while counter < recCount:
+ indata = unpack('64s3i11f',psafile.read(120))
+ #printlogplus('bone',indata[0])
+ bonename = str(bytes.decode(indata[0]).strip(bytes.decode(b'\x00')))
+ if bonename in bpy.data.armatures['armaturedata'].bones.keys():
+ BoneIndex2NamePairMap[counter] = bonename
+ print('find bone',bonename)
+ nobonematch = False
+ else:
+ print('can not find the bone:',bonename)
+ BoneNotFoundList.append(counter)
+ counter += 1
+
+ if nobonematch:
+ print('no bone was match so skip import!')
+ return
+
+ #Animations Header
+ indata = unpack('20s3i',psafile.read(32))
+ printlogplus('ChunkID',indata[0])
+ printlogplus('TypeFlag',indata[1])
+ printlogplus('DataSize',indata[2])
+ printlogplus('DataCount',indata[3])
+ #Animations Data
+ recCount = indata[3]
+ counter = 0
+ Raw_Key_Nums = 0
+ Action_List = []
+ while counter < recCount:
+ indata = unpack('64s64s4i3f3i',psafile.read(64+64+4*4+3*4+3*4))
+ printlogplus('Name',indata[0])
+ printlogplus('Group',indata[1])
+ printlogplus('totalbones',indata[2])
+ printlogplus('NumRawFrames',indata[-1])
+ Name = str(bytes.decode(indata[0]).strip(bytes.decode(b'\x00')))
+ Group = str(bytes.decode(indata[1]).strip(bytes.decode(b'\x00')))
+ totalbones = indata[2]
+ NumRawFrames = indata[-1]
+
+ Raw_Key_Nums += indata[2] * indata[-1]
+ Action_List.append((Name,Group,totalbones,NumRawFrames))
+
+ counter += 1
+
+ #Raw keys Header
+ Raw_Key_List = []
+ indata = unpack('20s3i',psafile.read(32))
+ printlogplus('ChunkID',indata[0])
+ printlogplus('TypeFlag',indata[1])
+ printlogplus('DataSize',indata[2])
+ printlogplus('DataCount',indata[3])
+ if(Raw_Key_Nums != indata[3]):
+ print('error! Raw_Key_Nums Inconsistent')
+ return
+ #Raw keys Data
+ recCount = Raw_Key_Nums
+ counter = 0
+ while counter < recCount:
+ indata = unpack('3f4f1f',psafile.read(3*4+4*4+4))
+ pos = mathutils.Vector((indata[0], indata[1], indata[2]))
+ quat = mathutils.Quaternion((indata[6], indata[3], indata[4], indata[5]))
+ time = indata[7]
+ Raw_Key_List.append((pos,quat,time))
+ counter += 1
+ #Scale keys Header,Scale keys Data,Curve keys Header,Curve keys Data
+ curFilePos = psafile.tell()
+ psafile.seek(0,2)
+ endFilePos = psafile.tell()
+ if curFilePos == endFilePos:
+ print('no Scale keys,Curve keys')
+
+ #build the animation line
+ if bpy.ops.object.mode_set.poll():
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+ NeededBoneMatrix = {}
+ for bone in bpy.data.armatures['armaturedata'].bones:
+ name = bone.name
+ ori_matrix = bone.matrix
+ matrix = bone.matrix_local.to_3x3()
+ bone_rest_matrix = Matrix(matrix)
+ #bone_rest_matrix = bone.matrix_local.to_3x3()
+ #bone_rest_matrix = bone.matrix_local.to_quaternion().conjugated().to_matrix()
+ bone_rest_matrix_inv = Matrix(bone_rest_matrix)
+ bone_rest_matrix_inv.invert()
+ bone_rest_matrix_inv.resize_4x4()
+ bone_rest_matrix.resize_4x4()
+ NeededBoneMatrix[name] = (bone_rest_matrix,bone_rest_matrix_inv,ori_matrix)
+
+ #build tmp pose bone tree
+ psa_bones = {}
+ for bone in bpy.data.objects['ArmObject'].pose.bones:
+ _psa_bone = psa_bone()
+ _psa_bone.name = bone.name
+ _psa_bone.Transform = bone.matrix
+ if bone.parent != None:
+ _psa_bone.parent = psa_bones[bone.parent.name]
+ else:
+ _psa_bone.parent = None
+ psa_bones[bone.name] = _psa_bone
+
+ raw_key_index = 0
+
+ for raw_action in Action_List:
+ Name = raw_action[0]
+ Group = raw_action[1]
+ Totalbones = raw_action[2]
+ NumRawFrames = raw_action[3]
+ context.scene.update()
+ object = bpy.data.objects['ArmObject']
+ object.animation_data_create()
+ action = bpy.data.actions.new(name=Name)
+ object.animation_data.action = action
+ for i in range(NumRawFrames):
+ context.scene.frame_set(i+1)
+ pose_bones = object.pose.bones
+ for j in range(Totalbones):
+ if j not in BoneNotFoundList:
+ bName = BoneIndex2NamePairMap[j]
+ pbone = psa_bones[bName]
+ pos = Raw_Key_List[raw_key_index][0]
+ quat = Raw_Key_List[raw_key_index][1]
+
+ mat = Matrix()
+ if pbone.parent != None:
+ quat = quat.conjugated()
+ mat = Matrix.Translation(pos) * quat.to_matrix().to_4x4()
+ mat = pose_bones[bName].parent.matrix * mat
+ #mat = pbone.parent.Transform * mat
+ else:
+ mat = pbone.Transform * Matrix.Translation(pos) * quat.to_matrix().to_4x4()
+
+ pose_bones[bName].matrix = mat
+ pbone.Transform = mat
+
+ raw_key_index += 1
+
+ #bpy.data.meshes[1]
+ for bone in pose_bones:
+ bone.matrix = psa_bones[bone.name].Transform
+ bone.keyframe_insert("rotation_quaternion")
+ bone.keyframe_insert("location")
+
+ def whirlSingleBone(pose_bone,quat):
+ bpy.context.scene.update()
+ #record child's matrix and origin rotate
+ hymat = Quaternion((0.707,-0.707,0,0)).inverted().to_matrix().to_4x4()
+ children_infos = {}
+ childrens = pose_bone.children
+ for child in childrens:
+ armmat = bpy.data.armatures['armaturedata'].bones[child.name].matrix.copy().to_4x4()
+ cmat = child.matrix.copy() * armmat.inverted() * hymat.inverted()
+ pos = cmat.to_translation()
+ rotmat = cmat.to_3x3()
+ children_infos[child] = (armmat,pos,rotmat)
+
+ #whirl this bone by quat
+ pose_bone.matrix *= quat.to_matrix().to_4x4()
+ pose_bone.keyframe_insert("location")
+ pose_bone.keyframe_insert("rotation_quaternion")
+ bpy.context.scene.update()
+ #set back children bon to original position
+ #reverse whirl child bone by quat.inverse()
+
+ for child in childrens:
+ armmat = children_infos[child][0]
+ pos = children_infos[child][1]
+ rotmat = children_infos[child][2]
+
+ child.matrix = Matrix.Translation(pos) * rotmat.to_4x4() * hymat * armmat
+ child.keyframe_insert("location")
+ child.keyframe_insert("rotation_quaternion")
+
+ for bone in pose_bones:
+ if bone.parent != None:
+ whirlSingleBone(bone,Quaternion((0.707,0,0,-0.707)))
+ else:
+ bone.rotation_quaternion *= Quaternion((0.707,-0.707,0,0))*Quaternion((0.707,0,0,-0.707))
+ bone.keyframe_insert("rotation_quaternion")
+
+ break
+
+ context.scene.frame_set(0)
+ if(debug):
+ logf.close()
+
+class IMPORT_OT_psa(bpy.types.Operator):
+ '''Load a skeleton anim psa File'''
+ bl_idname = "import_scene.psa"
+ bl_label = "Import PSA"
+ bl_space_type = "PROPERTIES"
+ bl_region_type = "WINDOW"
+
+ filepath = StringProperty(
+ subtype='FILE_PATH',
+ )
+ filter_glob = StringProperty(
+ default="*.psa",
+ options={'HIDDEN'},
+ )
+
+ def execute(self, context):
+ getInputFilenamepsa(self,self.filepath,context)
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ wm.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+class IMPORT_OT_psa(bpy.types.Operator):
+ '''Load a skeleton anim psa File'''
+ bl_idname = "import_scene.psa"
+ bl_label = "Import PSA"
+ bl_space_type = "PROPERTIES"
+ bl_region_type = "WINDOW"
+
+ filepath = StringProperty(
+ subtype='FILE_PATH',
+ )
+ filter_glob = StringProperty(
+ default="*.psa",
+ options={'HIDDEN'},
+ )
+
+ def execute(self, context):
+ getInputFilenamepsa(self,self.filepath,context)
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ wm.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+def menu_func(self, context):
+ self.layout.operator(IMPORT_OT_psk.bl_idname, text="Skeleton Mesh (.psk)")
+ self.layout.operator(IMPORT_OT_psa.bl_idname, text="Skeleton Anim (.psa)")
+
+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()
+
+#note this only read the data and will not be place in the scene
+#getInputFilename('C:\\blenderfiles\\BotA.psk')
+#getInputFilename('C:\\blenderfiles\\AA.PSK') \ No newline at end of file
diff --git a/io_import_scene_unreal_psk.py b/io_import_scene_unreal_psk.py
deleted file mode 100644
index 96784b1d..00000000
--- a/io_import_scene_unreal_psk.py
+++ /dev/null
@@ -1,804 +0,0 @@
-# ##### 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 #####
-
-bl_info = {
- "name": "Import Unreal Skeleton Mesh (.psk)",
- "author": "Darknet",
- "version": (2, 1),
- "blender": (2, 6, 3),
- "location": "File > Import > Skeleton Mesh (.psk)",
- "description": "Import Skeleleton Mesh",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
- "Scripts/Import-Export/Unreal_psk_psa",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=21366",
- "category": "Import-Export"}
-
-"""
-Version': '2.0' ported by Darknet
-
-Unreal Tournament PSK file to Blender mesh converter V1.0
-Author:
--Darknet (Redesign and reworked)
--D.M. Sturgeon (camg188 at the elYsium forum)
--#2011-01-20 MARIUSZ SZKARADEK GLOGOW POLAND
-
-Imports a *psk file to a new mesh
-
--No UV Texutre
--No Weight
--No Armature Bones
--No Material ID
-"""
-
-import bpy
-import bmesh
-import mathutils
-import math
-from string import *
-from struct import *
-import struct
-from math import *
-from bpy.props import *
-from bpy_extras.io_utils import unpack_list, unpack_face_list
-
-Quaternion = mathutils.Quaternion
-
-bpy.types.Scene.unrealbonesize = FloatProperty(
- name="Bone Length",
- description="Bone Length from head to tail distance",
- default=1,min=0.001,max=1000)
-
-#output log in to txt file
-DEBUGLOG = False
-
-scale = 1.0
-bonesize = 1.0
-skala = 1
-flipyz = False
-flipuv = True
-
-#pack read words
-def word(long):
- s=''
- for j in range(0,long):
- lit = struct.unpack('c',plik.read(1))[0]
- #print(">",lit)
- #print(">",bytes.decode(lit))
- if ord(lit)!=0:
- #print(lit)
- s+=bytes.decode(lit)
- if len(s)>100:
- break
- return s
-#pack read data
-def b(n):
- return struct.unpack(n*'b', plik.read(n))
-def B(n):
- return struct.unpack(n*'B', plik.read(n))
-def h(n):
- return struct.unpack(n*'h', plik.read(n*2))
-def H(n):
- return struct.unpack(n*'H', plik.read(n*2))
-def i(n):
- return struct.unpack(n*'i', plik.read(n*4))
-def f(n):
- return struct.unpack(n*'f', plik.read(n*4))
-
-#work in progress
-#bmesh
-#tess function prefix
-def drawmesh():
- global DEBUGLOG, plik,vertexes,uvcoord,faceslist,num_faces,facemat,facesmooth,m
- global vertexes_ids,bonesdata,meshesdata,groups,num_materials,skala,flipyz,flipuv,mat_faceslist
- global vertices,faces
- print(faces[0])
- print("[CREATING MESH:]")
- me_ob = bpy.data.meshes.new('testmesh')
- #create mesh
- print("-Vertices count:",len(vertices))
- me_ob.vertices.add(len(vertices))
- print("-Faces count:",len(faces))
- me_ob.tessfaces.add(len(faces))
- print("-Creating vertices points...")
- me_ob.vertices.foreach_set("co", unpack_list(vertices))
- print("-Creating faces idx...")
- me_ob.tessfaces.foreach_set("vertices_raw",unpack_list( faces))
- for face in me_ob.tessfaces:
- print(dir(face))
- face.use_smooth = facesmooth[face.index]
- #face.material_index = facemat[face.index]#not yet working
- print("-Creating UV Texture...")
- me_ob.tessface_uv_textures.new('uvtexture')
- #uvtex = me_ob.tessface_uv_textures[0]
- for uv in me_ob.tessface_uv_textures:
- for face in me_ob.tessfaces:
- #uv.data[face.index].uv1.x =
-
- #print(uv.data[face.index].uv1)
- #uv.data[face.index].uv1 = Vector(uvcoord[faces[face.index]][0],uvcoord[face.index][1])
- print(face.vertices_raw[0],face.vertices_raw[1],face.vertices_raw[2])
- uv.data[face.index].uv1 = mathutils.Vector((uvcoord[face.vertices_raw[0]][0],uvcoord[face.vertices_raw[0]][1]))
- uv.data[face.index].uv2 = mathutils.Vector((uvcoord[face.vertices_raw[1]][0],uvcoord[face.vertices_raw[1]][1]))
- uv.data[face.index].uv3 = mathutils.Vector((uvcoord[face.vertices_raw[2]][0],uvcoord[face.vertices_raw[2]][1]))
-
- ob = bpy.data.objects.new("TestObject",me_ob)
- #create vertex group
- for bone_id in range(len(bonesdata)):
- bonedata = bonesdata[str(bone_id)]
- namebone = bonedata[0]#.strip()[-25:]
- #print("NAME:",namebone)
- ob.vertex_groups.new(namebone)
- me_ob.update()
- bpy.context.scene.objects.link(ob)
-
-#Create Armature
-def check_armature():
- global DEBUGLOG, plik,vertexes,uvcoord,faceslist,num_faces,facemat,facesmooth,m
- global vertexes_ids,bonesdata,meshesdata,groups,num_materials,skala,flipyz,flipuv,amt
-
- #create Armature
- bpy.ops.object.mode_set(mode='OBJECT')
- for i in bpy.context.scene.objects: i.select = False #deselect all objects
-
- bpy.ops.object.add(
- type='ARMATURE',
- enter_editmode=True,
- location=(0,0,0))
- ob = bpy.context.object
- ob.show_x_ray = True
- ob.name = "ARM"
- amt = ob.data
- amt.name = 'Amt'
- amt.show_axes = True
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.context.scene.update()
-#Create bones
-def make_bone():
- global DEBUGLOG, plik,vertexes,uvcoord,faceslist,num_faces,facemat,facesmooth,m
- global vertexes_ids,bonesdata,meshesdata,groups,num_materials,skala,flipyz,flipuv,amt
- global bonenames
- bonenames = []
-
- print ('make bone')
-
- for bone_id in range(len(bonesdata)):
- bonedata = bonesdata[str(bone_id)]
- namebone = bonedata[0]#.strip()[-25:]
- newbone = amt.edit_bones.new(namebone)
- #those are need to show in the scene
- newbone.head = (0,0,0)
- newbone.tail = (0,0,1)
- bonenames.append(namebone)
- bpy.context.scene.update()
-#Make bone parent
-def make_bone_parent():
- global DEBUGLOG, plik,vertexes,uvcoord,faceslist,num_faces,facemat,facesmooth,m
- global vertexes_ids,bonesdata,meshesdata,groups,num_materials,skala,flipyz,flipuv,amt
- global children
- children = {}
-
- print ('make bone parent')
- for bone_id in range(len(bonesdata)):
- bonedata = bonesdata[str(bone_id)]
- namebone = bonenames[bone_id]
- nameparent = bonenames[bonedata[1][2]]
- #print(nameparent)
- if nameparent != None:#make sure it has name
- parentbone = amt.edit_bones[nameparent]
- bonecurrnet = amt.edit_bones[namebone]
- bonecurrnet.parent = parentbone
- bpy.context.scene.update()
-
-#make bone martix set
-def bones_matrix():
- global DEBUGLOG, plik,vertexes,uvcoord,faceslist,num_faces,facemat,facesmooth,m
- global vertexes_ids,bonesdata,meshesdata,groups,num_materials,skala,flipyz,flipuv,amt
-
- for bone_id in range(len(bonesdata)):
- bonedata = bonesdata[str(bone_id)]
- namebone = bonedata[0]#.strip()[-25:]
- nameparent = bonenames[bonedata[1][2]]
- pos = bonedata[2][4:7]
- rot = bonedata[2][0:4]
- qx,qy,qz,qw = rot[0],rot[1],rot[2],rot[3]
- #print("Quaternion:",qx,qy,qz,qw)
- if bone_id==0:
- rot = mathutils.Quaternion((qw,-qx,-qy,-qz))
- if bone_id!=0:
- rot = mathutils.Quaternion((qw,qx,qy,qz))
- matrix = mathutils.Matrix()
- rot = rot.to_matrix().inverted()
- #print(rot)
- matrix[0][:3] = rot[0]
- matrix[1][:3] = rot[1]
- matrix[2][:3] = rot[2]
- matrix[3][:3] = pos
- if bone_id>0:
- bonedata.append(matrix*bonesdata[str(bonedata[1][2])][3])
- else:
- bonedata.append(matrix)
- bpy.context.scene.update()
-
-#not working
-def make_bone_position():
- print ('make bone position')
- bpy.ops.object.mode_set(mode='EDIT')
- for bone_id in range(len(bonesdata)):
- bonedata = bonesdata[str(bone_id)]
- namebone = bonedata[0]#.strip()[-25:]
- bone = amt.edit_bones[namebone]
- bone.transform(bonedata[3], scale=True, roll=True)
- bvec = bone.tail- bone.head
- bvec.normalize()
- bone.tail = bone.head + 0.1 * bvec
- #bone.tail = bone.head + 1 * bvec
- bpy.context.scene.update()
-
-#not working
-def make_bone_position1():
- print ('make bone position')
- bpy.ops.object.mode_set(mode='EDIT')
- for bone_id in range(len(bonesdata)):
- bonedata = bonesdata[str(bone_id)]
- namebone = bonedata[0]#.strip()[-25:]
- pos = bonedata[2][4:7]
- pos1 = pos[0]*skala
- pos2 = pos[1]*skala
- pos3 = pos[2]*skala
- if flipyz == False:
- pos = [pos1,pos2,pos3]
- if flipyz == True:
- pos = [pos1,-pos3,pos2]
- rot = bonedata[2][0:4]
- qx,qy,qz,qw = rot[0],rot[1],rot[2],rot[3]
- if bone_id==0:
- rot = mathutils.Quaternion((qw,-qx,-qy,-qz))
- if bone_id!=0:
- rot = mathutils.Quaternion((qw,qx,qy,qz))
- #rot = rot.toMatrix().invert()
- rot = rot.to_matrix().inverted()
- bone = amt.edit_bones[namebone]
- #print("BONES:",amt.bones[0])
-
- if bone_id!=0:
- bone.head = bone.parent.head+mathutils.Vector(pos) * bone.parent.matrix
- #print(dir(rot))
- #print("rot:",rot)
- #print("matrix:",bone.parent.matrix)
-
- tempM = rot.to_4x4()*bone.parent.matrix
- #bone.matrix = tempM
- bone.transform(tempM, scale=False, roll=True)
- #bone.matrix_local = tempM
- else:
- bone.head = mathutils.Vector(pos)
- #bone.matrix = rot
- bone.transform(rot, scale=False, roll=True)
- #bone.matrix_local = rot
- bvec = bone.tail- bone.head
- bvec.normalize()
- bone.tail = bone.head + 0.1 * bvec
- #bone.tail = bone.head + 1 * bvec
-
-
-#http://www.blender.org/forum/viewtopic.php?t=13340&sid=8b17d5de07b17960021bbd72cac0495f
-def fixRollZ(b):
- v = (b.tail-b.head)/b.length
- b.roll -= math.degrees(math.atan2(v[0]*v[2]*(1 - v[1]),v[0]*v[0] + v[1]*v[2]*v[2]))
-def fixRoll(b):
- v = (b.tail-b.head)/b.length
- if v[2]*v[2] > .5:
- #align X-axis
- b.roll += math.degrees(math.atan2(v[0]*v[2]*(1 - v[1]),v[2]*v[2] + v[1]*v[0]*v[0]))
- else:
- #align Z-axis
- b.roll -= math.degrees(math.atan2(v[0]*v[2]*(1 - v[1]),v[0]*v[0] + v[1]*v[2]*v[2]))
-""" #did not port this yet unstable but work in some ways
-def make_bone_position3():
- for bone in md5_bones:
- #print(dir(bone))
- bpy.ops.object.mode_set(mode='EDIT')
- newbone = ob_new.data.edit_bones.new(bone.name)
- #parent the bone
- print("DRI:",dir(newbone))
- parentbone = None
- print("bone name:",bone.name)
- #note bone location is set in the real space or global not local
- bonesize = bpy.types.Scene.unrealbonesize
- if bone.name != bone.parent:
-
- pos_x = bone.bindpos[0]
- pos_y = bone.bindpos[1]
- pos_z = bone.bindpos[2]
-
- #print( "LINKING:" , bone.parent ,"j")
- parentbone = ob_new.data.edit_bones[bone.parent]
- newbone.parent = parentbone
-
- rotmatrix = bone.bindmat.to_matrix().to_4x4().to_3x3() # XXX, redundant matrix conversion?
- newbone.transform(bone.bindmat.to_matrix().to_4x4(),True,True)
- #parent_head = parentbone.matrix.to_quaternion().inverse() * parentbone.head
- #parent_tail = parentbone.matrix.to_quaternion().inverse() * parentbone.tail
- #location=Vector(pos_x,pos_y,pos_z)
- #set_position = (parent_tail - parent_head) + location
- #print("tmp head:",set_position)
-
- #pos_x = set_position.x
- #pos_y = set_position.y
- #pos_z = set_position.z
-
-
- newbone.head.x = parentbone.head.x + pos_x
- newbone.head.y = parentbone.head.y + pos_y
- newbone.head.z = parentbone.head.z + pos_z
- #print("head:",newbone.head)
- newbone.tail.x = parentbone.head.x + (pos_x + bonesize * rotmatrix[0][1])
- newbone.tail.y = parentbone.head.y + (pos_y + bonesize * rotmatrix[1][1])
- newbone.tail.z = parentbone.head.z + (pos_z + bonesize * rotmatrix[2][1])
- #newbone.roll = fixRoll(newbone)
- else:
- #print("rotmatrix:",dir(bone.bindmat.to_matrix().resize_4x4()))
- #rotmatrix = bone.bindmat.to_matrix().resize_4x4().to_3x3() # XXX, redundant matrix conversion?
- rotmatrix = bone.bindmat.to_matrix().to_3x3() # XXX, redundant matrix conversion?
- #newbone.transform(bone.bindmat.to_matrix(),True,True)
- newbone.head.x = bone.bindpos[0]
- newbone.head.y = bone.bindpos[1]
- newbone.head.z = bone.bindpos[2]
- newbone.tail.x = bone.bindpos[0] + bonesize * rotmatrix[0][1]
- newbone.tail.y = bone.bindpos[1] + bonesize * rotmatrix[1][1]
- newbone.tail.z = bone.bindpos[2] + bonesize * rotmatrix[2][1]
- #newbone.roll = fixRoll(newbone)
- #print("no parent")
-"""
-
-
-#import psk file
-def pskimport(filename,importmesh,importbone,bDebugLogPSK,importmultiuvtextures):
- global DEBUGLOG, plik,vertexes,uvcoord,faceslist,num_faces,facemat,facesmooth,m
- global vertexes_ids,bonesdata,meshesdata,groups,num_materials,skala,flipyz,flipuv,amt,vertices,faces
- points = []
- vertexes = []
- vertices = []
- uvcoord = []
- faceslist = []
- datafaces = []
- faces = []
- facemat = []
- facesmooth = []
- groups = []
- vertexes_ids = []
- bonesdata = {}
- meshesdata ={}
-
- DEBUGLOG = bDebugLogPSK
- print ("--------------------------------------------------")
- print ("---------SCRIPT EXECUTING PYTHON IMPORTER---------")
- print ("--------------------------------------------------")
- print (" DEBUG Log:",bDebugLogPSK)
- print ("Importing file: ", filename)
-
- plik = open(filename,'rb')
- word(20),i(3)
-
- #------POINTS------
- print ('reading points')
- word(20)
- data = i(3)
- num_points = data[2]
- for m in range(num_points):
- v=f(3)
- v1 =v[0]*skala
- v2 =v[1]*skala
- v3 =v[2]*skala
- if flipyz == False:
- points.append([v1,v2,v3])
- if flipyz == True:
- points.append([v1,-v3,v2])
- vertexes_ids.append([])
-
- #------VERTEXES----
- print ('reading vertexes')
- word(20)
- data = i(3)
- num_vertexes = data[2]
- for m in range(num_vertexes):
- data1 = H(2)
- vertexes.append(points[data1[0]])
- vertices.append(points[data1[0]])
- #vertices.extend(points[data1[0]])
- #vertices.extend([(points[data1[0]][0],points[data1[0]][1],points[data1[0]][2] )])
- #vertices.extend([(points[data1[0]][0],points[data1[0]][1],points[data1[0]][2] )])
- #print(points[data1[0]])
- if flipuv == False:
- uvcoord.append([f(1)[0],1-f(1)[0]])
- if flipuv == True:
- uvcoord.append([f(1)[0],f(1)[0]])
- vertexes_ids[data1[0]].append(m)
- b(2),h(1)
-
-
- #------FACES-------
- print ('reading faces')
- word(20)
- data = i(3)
- num_faces = data[2]
- for m in range(num_faces):
- v0=H(1)[0]
- v1=H(1)[0]
- v2=H(1)[0]
- faceslist.append([v1,v0,v2])
- faces.extend([(v1,v0,v2,0)])
- #faces.append([v1,v0,v2])
- #print((v1,v0,v2,0))
- mat_ids = B(2)
- facemat.append(mat_ids)
- if str(mat_ids[0]) not in meshesdata:
- meshesdata[str(mat_ids[0])] = []
- meshesdata[str(mat_ids[0])].append(m)
- facesmooth.append(i(1)[0])
- #datafaces.append([v1,v0,v2],mat_ids
-
- #------MATERIALS---
- print ('making materials')
- word(20)
- data = i(3)
- num_materials = data[2]
- for m in range(num_materials):
- name = word(64)
- print ('read materials from',name)
- matdata = bpy.data.materials.new(name)
- #try:
- #mat = Material.Get(namemodel+'-'+str(m))
- #mat = Material.Get(name)
- #except:
- #mat = Material.New(namemodel+'-'+str(m))
- #mat = Material.New(name)
- i(6)
- #make_materials(name,mat)
-
- #-------BONES------
- print ('reading bones')
- #check_armature()
- check_armature()
- word(20)
- data = i(3)
- num_bones = data[2]
- for m in range(num_bones):
- #print(str(m)) #index
- bonesdata[str(m)] = []
- bonename = word(64)
- bonename = bonename#.strip()
- bonename = bonename.strip()
- #print(bonename)#bone name
- bonesdata[str(m)].append(bonename)
- bonesdata[str(m)].append(i(3))
- bonesdata[str(m)].append(f(11))
- make_bone()
- make_bone_parent()
- bones_matrix()
- make_bone_position1()
-
-
- #-------SKINNING---
- print ('making skinning')
- word(20)
- data = i(3)
- num_groups = data[2]
-
- for m in range(num_groups):
- w = f(1)[0]
- v_id = i(1)[0]
- gr = i(1)[0]
- groups.append([w,v_id,gr])
- #create Mesh
- drawmesh()
-
- print ("IMPORTER PSK Blender 2.6 completed")
-#End of def pskimport#########################
-
-def psaimport(filename):
- global plik,bonesdata,animdata,anim_offset,animation_names
- bonesdata = {}
- animation_names = []
- animation_num_bones = []
- animation_num_keys = []
- animation_loc_keys = []
- animation_rot_keys = []
- animdata = {}
- plik = open(filename,'rb')
- print (word(20),i(3))
-
- #-------BONES------
- #check_armature_for_psa()
- print (word(20))
- data = i(3)
- #print data
- num_bones = data[2]
- for m in range(num_bones):
- bonesdata[str(m)] = []
- name = word(64)
- bonesdata[str(m)].append(name)
- bonesdata[str(m)].append(i(3))
- bonesdata[str(m)].append(f(11))
-
-
- #--------ANIMATIONS-INFO
- print (word(20))
- data = i(3)
- #print data
- for m in range(data[2]):
- name_animation = word(64)#name animation
- print("NAME:",name_animation)
- animation_names.append(name_animation)
- word(64)#name of owner of animation ?
- data = i(4)#num bones - 0 - 0 - num keys for all bones for this animation
- num_bones = data[0]
- animation_num_bones.append(num_bones)
- f(3)
- data = i(3)
- num_keys = data[2]
- animation_num_keys.append(num_keys)
- print (plik.tell())
-
- #--------ANIMATIONS-KEYS
- print (word(20))
- data = i(3)
- #print data
- anim_offset = {}
- seek = plik.tell()
- for m in range(len(animation_names)):
- anim_name = animation_names[m]
- anim_bones = animation_num_bones[m]
- anim_keys = animation_num_keys[m]
- anim_offset[anim_name] = []
- anim_offset[anim_name].append(seek)
- anim_offset[anim_name].append(anim_keys)
- anim_offset[anim_name].append(anim_bones)
- seek+=anim_keys*anim_bones*32
-
-
-def getInputFilename(self,filename,importmesh,importbone,bDebugLogPSK,importmultiuvtextures):
- checktype = filename.split('\\')[-1].split('.')[1]
- print ("------------",filename)
- if checktype.lower() != 'psk':
- print (" Selected file = ",filename)
- raise (IOError, "The selected input file is not a *.psk file")
- #self.report({'INFO'}, ("Selected file:"+ filename))
- else:
- pskimport(filename,importmesh,importbone,bDebugLogPSK,importmultiuvtextures)
-#import panel
-class IMPORT_OT_psk(bpy.types.Operator):
- """Load a skeleton mesh psk File"""
- bl_idname = "import_scene.psk"
- bl_label = "Import PSK"
- bl_space_type = "PROPERTIES"
- bl_region_type = "WINDOW"
- bl_options = {'UNDO'}
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- filepath = StringProperty(
- subtype='FILE_PATH',
- )
- filter_glob = StringProperty(
- default="*.psk",
- options={'HIDDEN'},
- )
- importmesh = BoolProperty(
- name="Mesh",
- description="Import mesh only. (not yet build.)",
- default=True,
- )
- importbone = BoolProperty(
- name="Bones",
- description="Import bones only. Current not working yet",
- default=True,
- )
- importmultiuvtextures = BoolProperty(
- name="Single UV Texture(s)",
- description="Single or Multi uv textures",
- default=True,
- )
- bDebugLogPSK = BoolProperty(
- name="Debug Log.txt",
- description="Log the output of raw format. It will save in " \
- "current file dir. Note this just for testing",
- default=False,
- )
- unrealbonesize = FloatProperty(
- name="Bone Length",
- description="Bone Length from head to tail distance",
- default=1,
- min=0.001,
- max=1000,
- )
-
- def execute(self, context):
- bpy.types.Scene.unrealbonesize = self.unrealbonesize
- getInputFilename(self,self.filepath,self.importmesh,self.importbone,self.bDebugLogPSK,self.importmultiuvtextures)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.window_manager
- wm.fileselect_add(self)
- return {'RUNNING_MODAL'}
-#import panel psk
-class OBJECT_OT_PSKPath(bpy.types.Operator):
- bl_idname = "object.pskpath"
- bl_label = "PSK Path"
- __doc__ = ""
-
- filepath = StringProperty(
- subtype='FILE_PATH',
- )
- filter_glob = StringProperty(
- default="*.psk",
- options={'HIDDEN'},
- )
- importmesh = BoolProperty(
- name="Mesh",
- description="Import mesh only. (not yet build.)",
- default=True,
- )
- importbone = BoolProperty(
- name="Bones",
- description="Import bones only. Current not working yet",
- default=True,
- )
- importmultiuvtextures = BoolProperty(
- name="Single UV Texture(s)",
- description="Single or Multi uv textures",
- default=True,
- )
- bDebugLogPSK = BoolProperty(
- name="Debug Log.txt",
- description="Log the output of raw format. It will save in " \
- "current file dir. Note this just for testing",
- default=False,
- )
- unrealbonesize = FloatProperty(
- name="Bone Length",
- description="Bone Length from head to tail distance",
- default=1,
- min=0.001,
- max=1000,
- )
-
- def execute(self, context):
- #context.scene.importpskpath = self.properties.filepath
- bpy.types.Scene.unrealbonesize = self.unrealbonesize
- getInputFilename(self,self.filepath,self.importmesh,self.importbone,self.bDebugLogPSK,self.importmultiuvtextures)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- #bpy.context.window_manager.fileselect_add(self)
- wm = context.window_manager
- wm.fileselect_add(self)
- return {'RUNNING_MODAL'}
-#import panel psa
-class OBJECT_OT_PSAPath(bpy.types.Operator):
- bl_idname = "object.psapath"
- bl_label = "PSA Path"
- __doc__ = ""
-
- filepath = StringProperty(name="PSA File Path", description="Filepath used for importing the PSA file", maxlen= 1024, default= "")
- filter_glob = StringProperty(
- default="*.psa",
- options={'HIDDEN'},
- )
- def execute(self, context):
- #context.scene.importpsapath = self.properties.filepath
- psaimport(self.filepath)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- bpy.context.window_manager.fileselect_add(self)
- return {'RUNNING_MODAL'}
-
-class OBJECT_OT_Path(bpy.types.Operator):
- bl_idname = "object.path"
- bl_label = "MESH BUILD TEST"
- __doc__ = ""
- # generic transform props
- view_align = BoolProperty(
- name="Align to View",
- default=False,
- )
- location = FloatVectorProperty(
- name="Location",
- subtype='TRANSLATION',
- )
- rotation = FloatVectorProperty(
- name="Rotation",
- subtype='EULER',
- )
- def execute(self, context):
- return {'FINISHED'}
-
- def invoke(self, context, event):
- me = bpy.data.meshes.new("test")
- obmade = bpy.data.objects.new("TestObject",me)
- print("Create Simple Mesh")
- bpy.data.scenes[0].objects.link(obmade)
- for i in bpy.context.scene.objects: i.select = False #deselect all objects
- obmade.select = True
- bpy.context.scene.objects.active = obmade
-
- verts = [(0,0,0),(2,0,0),(2,0,2)]
- edges = [(0,1),(1,2),(2,0)]
- faces = []
- faces.extend([(0,1,2,0)])
- #me.vertices.add(len(verts))
- #print(dir(me))
- me.vertices.add(len(verts))
- me.tessfaces.add(len(faces))
- for face in me.tessfaces:
- print(dir(face))
-
- me.vertices.foreach_set("co", unpack_list(verts))
- me.tessfaces.foreach_set("vertices_raw", unpack_list(faces))
- me.edges.add(len(edges))
- me.edges.foreach_set("vertices", unpack_list(edges))
-
- #print(len(me.tessfaces))
- me.tessface_uv_textures.new("uvtexture")
- #for uv in me.tessface_uv_textures:
- #print(len(uv.data))
- #print(dir(uv.data[0]))
- #print(dir(uv.data[0].uv1))
- return {'RUNNING_MODAL'}
-
-#import menu panel tool bar
-class VIEW3D_PT_unrealimport_objectmode(bpy.types.Panel):
- bl_space_type = "VIEW_3D"
- bl_region_type = "TOOLS"
- bl_label = "Import PSK/PSA"
-
- @classmethod
- def poll(cls, context):
- return context.active_object
-
- def draw(self, context):
- layout = self.layout
- rd = context.scene
-
- row2 = layout.row(align=True)
- row2.operator(OBJECT_OT_PSKPath.bl_idname)
- row2.operator(OBJECT_OT_PSAPath.bl_idname)
- row2.operator(OBJECT_OT_Path.bl_idname)
-#import panel
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_psk.bl_idname, text="Skeleton Mesh (.psk)")
-
-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()
-
-#note this only read the data and will not be place in the scene
-#getInputFilename('C:\\blenderfiles\\BotA.psk')
-#getInputFilename('C:\\blenderfiles\\AA.PSK')
-#getInputFilename('C:\\blender26x\\blender-2.psk')